diff --git a/Makefile b/GNUmakefile similarity index 75% rename from Makefile rename to GNUmakefile index c5241339..616430e8 100644 --- a/Makefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -include nall/Makefile +include nall/GNUmakefile fc := fc sfc := sfc @@ -7,17 +7,12 @@ gba := gba profile := accuracy target := higan -# target := loki - -ifeq ($(target),loki) - options += debugger -endif # arch := x86 # console := true # compiler -flags += -I. -O3 -fomit-frame-pointer +flags += -I. -O3 link += objects := libco @@ -43,16 +38,16 @@ ifeq ($(platform),windows) else link += -mwindows endif - link += -s -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32 + link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32 link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc else ifeq ($(platform),macosx) flags += -march=native else ifeq ($(platform),linux) flags += -march=native - link += -s -Wl,-export-dynamic -lX11 -lXext -ldl + link += -Wl,-export-dynamic -lX11 -lXext -ldl else ifeq ($(platform),bsd) flags += -march=native - link += -s -Wl,-export-dynamic -lX11 -lXext + link += -Wl,-export-dynamic -lX11 -lXext else $(error unsupported platform.) endif @@ -76,7 +71,7 @@ all: build; obj/libco.o: libco/libco.c libco/* -include $(ui)/Makefile +include $(ui)/GNUmakefile flags := $(flags) $(foreach o,$(call strupper,$(options)),-D$o) # targets @@ -87,8 +82,6 @@ clean: -@$(call delete,obj/*.so) -@$(call delete,obj/*.dylib) -@$(call delete,obj/*.dll) - -@$(call delete,*.res) - -@$(call delete,*.manifest) archive: if [ -f higan.tar.xz ]; then rm higan.tar.xz; fi @@ -99,16 +92,16 @@ ifeq ($(shell id -un),byuu) if [ -d ./libco ]; then rm -r ./libco; fi if [ -d ./nall ]; then rm -r ./nall; fi if [ -d ./ruby ]; then rm -r ./ruby; fi - if [ -d ./phoenix ]; then rm -r ./phoenix; fi + if [ -d ./hiro ]; then rm -r ./hiro; fi cp -r ../libco ./libco cp -r ../nall ./nall cp -r ../ruby ./ruby - cp -r ../phoenix ./phoenix + cp -r ../hiro ./hiro rm -r libco/doc - rm -r libco/.test - rm -r nall/.test - rm -r ruby/.test - rm -r phoenix/.test + rm -r libco/-test + rm -r nall/-test + rm -r ruby/-test + rm -r hiro/-test endif help:; diff --git a/data/higan.desktop b/data/higan.desktop index 70a2242e..4731230b 100644 --- a/data/higan.desktop +++ b/data/higan.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=higan -Comment=SNES emulator +Comment=Nintendo emulator Exec=higan Icon=higan Terminal=false diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 8b59706b..efa5b2b4 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.08"; + static const char Version[] = "094.09"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; @@ -26,7 +26,6 @@ namespace Emulator { #include <nall/endian.hpp> #include <nall/file.hpp> #include <nall/function.hpp> -#include <nall/http.hpp> #include <nall/image.hpp> #include <nall/invoke.hpp> #include <nall/priority-queue.hpp> @@ -34,12 +33,12 @@ namespace Emulator { #include <nall/random.hpp> #include <nall/serializer.hpp> #include <nall/set.hpp> -#include <nall/sha256.hpp> #include <nall/stdint.hpp> #include <nall/string.hpp> #include <nall/utility.hpp> #include <nall/varint.hpp> #include <nall/vector.hpp> +#include <nall/hash/sha256.hpp> #include <nall/stream/memory.hpp> #include <nall/stream/vector.hpp> using namespace nall; diff --git a/fc/Makefile b/fc/GNUmakefile similarity index 100% rename from fc/Makefile rename to fc/GNUmakefile diff --git a/fc/cartridge/cartridge.cpp b/fc/cartridge/cartridge.cpp index 57dc723b..844c3b0d 100644 --- a/fc/cartridge/cartridge.cpp +++ b/fc/cartridge/cartridge.cpp @@ -24,16 +24,10 @@ void Cartridge::load() { Board::load(information.markup); //this call will set Cartridge::board if successful if(board == nullptr) return; - sha256_ctx sha; - uint8 hash[32]; - sha256_init(&sha); - sha256_chunk(&sha, board->prgrom.data, board->prgrom.size); - sha256_chunk(&sha, board->chrrom.data, board->chrrom.size); - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto& byte : hash) result.append(hex<2>(byte)); - sha256 = result; + Hash::SHA256 sha; + sha.data(board->prgrom.data, board->prgrom.size); + sha.data(board->chrrom.data, board->chrrom.size); + sha256 = sha.digest(); system.load(); loaded = true; diff --git a/gb/Makefile b/gb/GNUmakefile similarity index 100% rename from gb/Makefile rename to gb/GNUmakefile diff --git a/gb/cartridge/cartridge.cpp b/gb/cartridge/cartridge.cpp index fa8b2706..0b85220c 100644 --- a/gb/cartridge/cartridge.cpp +++ b/gb/cartridge/cartridge.cpp @@ -25,7 +25,7 @@ void Cartridge::load_empty(System::Revision revision) { romdata = allocate<uint8>(romsize, 0xff); ramsize = 0; mapper = &mbc0; - sha256 = nall::sha256(romdata, romsize); + sha256 = Hash::SHA256(romdata, romsize).digest(); loaded = true; system.load(revision); } @@ -94,7 +94,7 @@ void Cartridge::load(System::Revision revision) { case Mapper::HuC3: mapper = &huc3; break; } - sha256 = nall::sha256(romdata, romsize); + sha256 = Hash::SHA256(romdata, romsize).digest(); loaded = true; system.load(revision); } diff --git a/gba/Makefile b/gba/GNUmakefile similarity index 100% rename from gba/Makefile rename to gba/GNUmakefile diff --git a/gba/cartridge/cartridge.cpp b/gba/cartridge/cartridge.cpp index e2d787d3..24f6be0f 100644 --- a/gba/cartridge/cartridge.cpp +++ b/gba/cartridge/cartridge.cpp @@ -68,7 +68,7 @@ void Cartridge::load() { } } - sha256 = nall::sha256(rom.data, rom_size); + sha256 = Hash::SHA256(rom.data, rom_size).digest(); system.load(); loaded = true; diff --git a/gba/player/player.cpp b/gba/player/player.cpp index 4248b916..1b7b59bb 100644 --- a/gba/player/player.cpp +++ b/gba/player/player.cpp @@ -20,7 +20,7 @@ void Player::power() { } void Player::frame() { - uint32 hash = crc32_calculate((const uint8*)ppu.output, 240 * 160 * sizeof(uint32)); + uint32 hash = Hash::CRC32(ppu.output, 240 * 160 * sizeof(uint32)).value(); status.logoDetected = (hash == 0x7776eb55); if(status.logoDetected) { diff --git a/hiro/GNUmakefile b/hiro/GNUmakefile new file mode 100644 index 00000000..1be0edb0 --- /dev/null +++ b/hiro/GNUmakefile @@ -0,0 +1,24 @@ +ifeq ($(platform),) + hiroflags = $(cppflags) $(flags) -DHIRO_REFERENCE + hirolink = +else ifeq ($(platform),windows) + hiroflags = $(cppflags) $(flags) -DHIRO_WINDOWS + hirolink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi +else ifeq ($(platform),macosx) + hiroflags = $(objcppflags) $(flags) -DHIRO_COCOA + hirolink = -framework Cocoa -framework Carbon +else + ifeq ($(hiro),) + hiro := gtk + endif + + ifeq ($(hiro),gtk) + hiroflags = $(cppflags) $(flags) -DHIRO_GTK `pkg-config --cflags gtk+-2.0 gtksourceview-2.0` + hirolink = `pkg-config --libs gtk+-2.0 gtksourceview-2.0` -lX11 + endif + + ifeq ($(hiro),qt) + hiroflags = $(cppflags) $(flags) -DHIRO_QT `pkg-config --cflags QtCore QtGui` + hirolink = `pkg-config --libs QtCore QtGui` -lX11 + endif +endif diff --git a/phoenix/cocoa/action/action.cpp b/hiro/cocoa/action/action.cpp similarity index 100% rename from phoenix/cocoa/action/action.cpp rename to hiro/cocoa/action/action.cpp diff --git a/phoenix/cocoa/action/action.hpp b/hiro/cocoa/action/action.hpp similarity index 100% rename from phoenix/cocoa/action/action.hpp rename to hiro/cocoa/action/action.hpp diff --git a/phoenix/cocoa/action/check-item.cpp b/hiro/cocoa/action/check-item.cpp similarity index 100% rename from phoenix/cocoa/action/check-item.cpp rename to hiro/cocoa/action/check-item.cpp diff --git a/phoenix/cocoa/action/check-item.hpp b/hiro/cocoa/action/check-item.hpp similarity index 100% rename from phoenix/cocoa/action/check-item.hpp rename to hiro/cocoa/action/check-item.hpp diff --git a/phoenix/cocoa/action/item.cpp b/hiro/cocoa/action/item.cpp similarity index 100% rename from phoenix/cocoa/action/item.cpp rename to hiro/cocoa/action/item.cpp diff --git a/phoenix/cocoa/action/item.hpp b/hiro/cocoa/action/item.hpp similarity index 100% rename from phoenix/cocoa/action/item.hpp rename to hiro/cocoa/action/item.hpp diff --git a/phoenix/cocoa/action/menu.cpp b/hiro/cocoa/action/menu.cpp similarity index 100% rename from phoenix/cocoa/action/menu.cpp rename to hiro/cocoa/action/menu.cpp diff --git a/phoenix/cocoa/action/menu.hpp b/hiro/cocoa/action/menu.hpp similarity index 100% rename from phoenix/cocoa/action/menu.hpp rename to hiro/cocoa/action/menu.hpp diff --git a/phoenix/cocoa/action/radio-item.cpp b/hiro/cocoa/action/radio-item.cpp similarity index 100% rename from phoenix/cocoa/action/radio-item.cpp rename to hiro/cocoa/action/radio-item.cpp diff --git a/phoenix/cocoa/action/radio-item.hpp b/hiro/cocoa/action/radio-item.hpp similarity index 100% rename from phoenix/cocoa/action/radio-item.hpp rename to hiro/cocoa/action/radio-item.hpp diff --git a/phoenix/cocoa/action/separator.cpp b/hiro/cocoa/action/separator.cpp similarity index 100% rename from phoenix/cocoa/action/separator.cpp rename to hiro/cocoa/action/separator.cpp diff --git a/phoenix/cocoa/action/separator.hpp b/hiro/cocoa/action/separator.hpp similarity index 100% rename from phoenix/cocoa/action/separator.hpp rename to hiro/cocoa/action/separator.hpp diff --git a/phoenix/cocoa/application.cpp b/hiro/cocoa/application.cpp similarity index 100% rename from phoenix/cocoa/application.cpp rename to hiro/cocoa/application.cpp diff --git a/phoenix/cocoa/application.hpp b/hiro/cocoa/application.hpp similarity index 100% rename from phoenix/cocoa/application.hpp rename to hiro/cocoa/application.hpp diff --git a/phoenix/cocoa/browser-window.cpp b/hiro/cocoa/browser-window.cpp similarity index 94% rename from phoenix/cocoa/browser-window.cpp rename to hiro/cocoa/browser-window.cpp index 014cb6dd..9302061b 100644 --- a/phoenix/cocoa/browser-window.cpp +++ b/hiro/cocoa/browser-window.cpp @@ -24,7 +24,7 @@ string pBrowserWindow::open(BrowserWindow::State& state) { @autoreleasepool { NSMutableArray* filters = [[NSMutableArray alloc] init]; for(auto& rule : state.filters) { - string pattern = rule.split<1>("(")(1).rtrim<1>(")"); + string pattern = rule.split<1>("(")(1).rtrim(")"); if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]]; } NSOpenPanel* panel = [NSOpenPanel openPanel]; @@ -49,7 +49,7 @@ string pBrowserWindow::save(BrowserWindow::State& state) { @autoreleasepool { NSMutableArray* filters = [[NSMutableArray alloc] init]; for(auto& rule : state.filters) { - string pattern = rule.split<1>("(")(1).rtrim<1>(")"); + string pattern = rule.split<1>("(")(1).rtrim(")"); if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]]; } NSSavePanel* panel = [NSSavePanel savePanel]; diff --git a/phoenix/cocoa/browser-window.hpp b/hiro/cocoa/browser-window.hpp similarity index 100% rename from phoenix/cocoa/browser-window.hpp rename to hiro/cocoa/browser-window.hpp diff --git a/phoenix/cocoa/desktop.cpp b/hiro/cocoa/desktop.cpp similarity index 100% rename from phoenix/cocoa/desktop.cpp rename to hiro/cocoa/desktop.cpp diff --git a/phoenix/cocoa/desktop.hpp b/hiro/cocoa/desktop.hpp similarity index 100% rename from phoenix/cocoa/desktop.hpp rename to hiro/cocoa/desktop.hpp diff --git a/phoenix/cocoa/font.cpp b/hiro/cocoa/font.cpp similarity index 100% rename from phoenix/cocoa/font.cpp rename to hiro/cocoa/font.cpp diff --git a/phoenix/cocoa/font.hpp b/hiro/cocoa/font.hpp similarity index 100% rename from phoenix/cocoa/font.hpp rename to hiro/cocoa/font.hpp diff --git a/phoenix/cocoa/header.hpp b/hiro/cocoa/header.hpp similarity index 100% rename from phoenix/cocoa/header.hpp rename to hiro/cocoa/header.hpp diff --git a/phoenix/cocoa/keyboard.cpp b/hiro/cocoa/keyboard.cpp similarity index 100% rename from phoenix/cocoa/keyboard.cpp rename to hiro/cocoa/keyboard.cpp diff --git a/phoenix/cocoa/keyboard.hpp b/hiro/cocoa/keyboard.hpp similarity index 100% rename from phoenix/cocoa/keyboard.hpp rename to hiro/cocoa/keyboard.hpp diff --git a/phoenix/cocoa/message-window.cpp b/hiro/cocoa/message-window.cpp similarity index 100% rename from phoenix/cocoa/message-window.cpp rename to hiro/cocoa/message-window.cpp diff --git a/phoenix/cocoa/message-window.hpp b/hiro/cocoa/message-window.hpp similarity index 100% rename from phoenix/cocoa/message-window.hpp rename to hiro/cocoa/message-window.hpp diff --git a/phoenix/cocoa/monitor.cpp b/hiro/cocoa/monitor.cpp similarity index 100% rename from phoenix/cocoa/monitor.cpp rename to hiro/cocoa/monitor.cpp diff --git a/phoenix/cocoa/monitor.hpp b/hiro/cocoa/monitor.hpp similarity index 100% rename from phoenix/cocoa/monitor.hpp rename to hiro/cocoa/monitor.hpp diff --git a/phoenix/cocoa/mouse.cpp b/hiro/cocoa/mouse.cpp similarity index 100% rename from phoenix/cocoa/mouse.cpp rename to hiro/cocoa/mouse.cpp diff --git a/phoenix/cocoa/mouse.hpp b/hiro/cocoa/mouse.hpp similarity index 100% rename from phoenix/cocoa/mouse.hpp rename to hiro/cocoa/mouse.hpp diff --git a/phoenix/cocoa/object.cpp b/hiro/cocoa/object.cpp similarity index 100% rename from phoenix/cocoa/object.cpp rename to hiro/cocoa/object.cpp diff --git a/phoenix/cocoa/object.hpp b/hiro/cocoa/object.hpp similarity index 100% rename from phoenix/cocoa/object.hpp rename to hiro/cocoa/object.hpp diff --git a/phoenix/cocoa/platform.cpp b/hiro/cocoa/platform.cpp similarity index 100% rename from phoenix/cocoa/platform.cpp rename to hiro/cocoa/platform.cpp diff --git a/phoenix/cocoa/platform.hpp b/hiro/cocoa/platform.hpp similarity index 100% rename from phoenix/cocoa/platform.hpp rename to hiro/cocoa/platform.hpp diff --git a/phoenix/cocoa/timer.cpp b/hiro/cocoa/timer.cpp similarity index 100% rename from phoenix/cocoa/timer.cpp rename to hiro/cocoa/timer.cpp diff --git a/phoenix/cocoa/timer.hpp b/hiro/cocoa/timer.hpp similarity index 100% rename from phoenix/cocoa/timer.hpp rename to hiro/cocoa/timer.hpp diff --git a/phoenix/cocoa/utility.cpp b/hiro/cocoa/utility.cpp similarity index 100% rename from phoenix/cocoa/utility.cpp rename to hiro/cocoa/utility.cpp diff --git a/phoenix/cocoa/widget/button.cpp b/hiro/cocoa/widget/button.cpp similarity index 94% rename from phoenix/cocoa/widget/button.cpp rename to hiro/cocoa/widget/button.cpp index 950bffef..3114c7b1 100644 --- a/phoenix/cocoa/widget/button.cpp +++ b/hiro/cocoa/widget/button.cpp @@ -32,7 +32,10 @@ Size pButton::minimumSize() { size.height += button.state.image.height; } - return {size.width + 20, size.height + 4}; + return {size.width + (button.state.text ? 20 : 4), size.height + 4}; +} + +void pButton::setBordered(bool bordered) { } void pButton::setGeometry(Geometry geometry) { diff --git a/phoenix/cocoa/widget/button.hpp b/hiro/cocoa/widget/button.hpp similarity index 93% rename from phoenix/cocoa/widget/button.hpp rename to hiro/cocoa/widget/button.hpp index 98569454..62f16361 100644 --- a/phoenix/cocoa/widget/button.hpp +++ b/hiro/cocoa/widget/button.hpp @@ -13,6 +13,7 @@ struct pButton : public pWidget { CocoaButton* cocoaButton = nullptr; Size minimumSize(); + void setBordered(bool bordered); void setGeometry(Geometry geometry); void setImage(const image& image, Orientation orientation); void setText(string text); diff --git a/phoenix/cocoa/widget/canvas.cpp b/hiro/cocoa/widget/canvas.cpp similarity index 100% rename from phoenix/cocoa/widget/canvas.cpp rename to hiro/cocoa/widget/canvas.cpp diff --git a/phoenix/cocoa/widget/canvas.hpp b/hiro/cocoa/widget/canvas.hpp similarity index 100% rename from phoenix/cocoa/widget/canvas.hpp rename to hiro/cocoa/widget/canvas.hpp diff --git a/phoenix/cocoa/widget/check-button.cpp b/hiro/cocoa/widget/check-button.cpp similarity index 100% rename from phoenix/cocoa/widget/check-button.cpp rename to hiro/cocoa/widget/check-button.cpp diff --git a/phoenix/cocoa/widget/check-button.hpp b/hiro/cocoa/widget/check-button.hpp similarity index 100% rename from phoenix/cocoa/widget/check-button.hpp rename to hiro/cocoa/widget/check-button.hpp diff --git a/phoenix/cocoa/widget/check-label.cpp b/hiro/cocoa/widget/check-label.cpp similarity index 100% rename from phoenix/cocoa/widget/check-label.cpp rename to hiro/cocoa/widget/check-label.cpp diff --git a/phoenix/cocoa/widget/check-label.hpp b/hiro/cocoa/widget/check-label.hpp similarity index 100% rename from phoenix/cocoa/widget/check-label.hpp rename to hiro/cocoa/widget/check-label.hpp diff --git a/phoenix/cocoa/widget/combo-button.cpp b/hiro/cocoa/widget/combo-button.cpp similarity index 100% rename from phoenix/cocoa/widget/combo-button.cpp rename to hiro/cocoa/widget/combo-button.cpp diff --git a/phoenix/cocoa/widget/combo-button.hpp b/hiro/cocoa/widget/combo-button.hpp similarity index 100% rename from phoenix/cocoa/widget/combo-button.hpp rename to hiro/cocoa/widget/combo-button.hpp diff --git a/phoenix/cocoa/widget/console.cpp b/hiro/cocoa/widget/console.cpp similarity index 100% rename from phoenix/cocoa/widget/console.cpp rename to hiro/cocoa/widget/console.cpp diff --git a/phoenix/cocoa/widget/console.hpp b/hiro/cocoa/widget/console.hpp similarity index 100% rename from phoenix/cocoa/widget/console.hpp rename to hiro/cocoa/widget/console.hpp diff --git a/phoenix/cocoa/widget/frame.cpp b/hiro/cocoa/widget/frame.cpp similarity index 100% rename from phoenix/cocoa/widget/frame.cpp rename to hiro/cocoa/widget/frame.cpp diff --git a/phoenix/cocoa/widget/frame.hpp b/hiro/cocoa/widget/frame.hpp similarity index 100% rename from phoenix/cocoa/widget/frame.hpp rename to hiro/cocoa/widget/frame.hpp diff --git a/phoenix/cocoa/widget/hex-edit.cpp b/hiro/cocoa/widget/hex-edit.cpp similarity index 100% rename from phoenix/cocoa/widget/hex-edit.cpp rename to hiro/cocoa/widget/hex-edit.cpp diff --git a/phoenix/cocoa/widget/hex-edit.hpp b/hiro/cocoa/widget/hex-edit.hpp similarity index 100% rename from phoenix/cocoa/widget/hex-edit.hpp rename to hiro/cocoa/widget/hex-edit.hpp diff --git a/phoenix/cocoa/widget/horizontal-scroller.cpp b/hiro/cocoa/widget/horizontal-scroller.cpp similarity index 100% rename from phoenix/cocoa/widget/horizontal-scroller.cpp rename to hiro/cocoa/widget/horizontal-scroller.cpp diff --git a/phoenix/cocoa/widget/horizontal-scroller.hpp b/hiro/cocoa/widget/horizontal-scroller.hpp similarity index 100% rename from phoenix/cocoa/widget/horizontal-scroller.hpp rename to hiro/cocoa/widget/horizontal-scroller.hpp diff --git a/phoenix/cocoa/widget/horizontal-slider.cpp b/hiro/cocoa/widget/horizontal-slider.cpp similarity index 100% rename from phoenix/cocoa/widget/horizontal-slider.cpp rename to hiro/cocoa/widget/horizontal-slider.cpp diff --git a/phoenix/cocoa/widget/horizontal-slider.hpp b/hiro/cocoa/widget/horizontal-slider.hpp similarity index 100% rename from phoenix/cocoa/widget/horizontal-slider.hpp rename to hiro/cocoa/widget/horizontal-slider.hpp diff --git a/phoenix/cocoa/widget/label.cpp b/hiro/cocoa/widget/label.cpp similarity index 100% rename from phoenix/cocoa/widget/label.cpp rename to hiro/cocoa/widget/label.cpp diff --git a/phoenix/cocoa/widget/label.hpp b/hiro/cocoa/widget/label.hpp similarity index 100% rename from phoenix/cocoa/widget/label.hpp rename to hiro/cocoa/widget/label.hpp diff --git a/phoenix/cocoa/widget/layout.hpp b/hiro/cocoa/widget/layout.hpp similarity index 100% rename from phoenix/cocoa/widget/layout.hpp rename to hiro/cocoa/widget/layout.hpp diff --git a/phoenix/cocoa/widget/line-edit.cpp b/hiro/cocoa/widget/line-edit.cpp similarity index 100% rename from phoenix/cocoa/widget/line-edit.cpp rename to hiro/cocoa/widget/line-edit.cpp diff --git a/phoenix/cocoa/widget/line-edit.hpp b/hiro/cocoa/widget/line-edit.hpp similarity index 100% rename from phoenix/cocoa/widget/line-edit.hpp rename to hiro/cocoa/widget/line-edit.hpp diff --git a/phoenix/cocoa/widget/list-view.cpp b/hiro/cocoa/widget/list-view.cpp similarity index 100% rename from phoenix/cocoa/widget/list-view.cpp rename to hiro/cocoa/widget/list-view.cpp diff --git a/phoenix/cocoa/widget/list-view.hpp b/hiro/cocoa/widget/list-view.hpp similarity index 100% rename from phoenix/cocoa/widget/list-view.hpp rename to hiro/cocoa/widget/list-view.hpp diff --git a/phoenix/cocoa/widget/progress-bar.cpp b/hiro/cocoa/widget/progress-bar.cpp similarity index 100% rename from phoenix/cocoa/widget/progress-bar.cpp rename to hiro/cocoa/widget/progress-bar.cpp diff --git a/phoenix/cocoa/widget/progress-bar.hpp b/hiro/cocoa/widget/progress-bar.hpp similarity index 100% rename from phoenix/cocoa/widget/progress-bar.hpp rename to hiro/cocoa/widget/progress-bar.hpp diff --git a/phoenix/cocoa/widget/radio-button.cpp b/hiro/cocoa/widget/radio-button.cpp similarity index 100% rename from phoenix/cocoa/widget/radio-button.cpp rename to hiro/cocoa/widget/radio-button.cpp diff --git a/phoenix/cocoa/widget/radio-button.hpp b/hiro/cocoa/widget/radio-button.hpp similarity index 100% rename from phoenix/cocoa/widget/radio-button.hpp rename to hiro/cocoa/widget/radio-button.hpp diff --git a/phoenix/cocoa/widget/radio-label.cpp b/hiro/cocoa/widget/radio-label.cpp similarity index 100% rename from phoenix/cocoa/widget/radio-label.cpp rename to hiro/cocoa/widget/radio-label.cpp diff --git a/phoenix/cocoa/widget/radio-label.hpp b/hiro/cocoa/widget/radio-label.hpp similarity index 100% rename from phoenix/cocoa/widget/radio-label.hpp rename to hiro/cocoa/widget/radio-label.hpp diff --git a/phoenix/cocoa/widget/sizable.hpp b/hiro/cocoa/widget/sizable.hpp similarity index 100% rename from phoenix/cocoa/widget/sizable.hpp rename to hiro/cocoa/widget/sizable.hpp diff --git a/phoenix/cocoa/widget/tab-frame.cpp b/hiro/cocoa/widget/tab-frame.cpp similarity index 100% rename from phoenix/cocoa/widget/tab-frame.cpp rename to hiro/cocoa/widget/tab-frame.cpp diff --git a/phoenix/cocoa/widget/tab-frame.hpp b/hiro/cocoa/widget/tab-frame.hpp similarity index 100% rename from phoenix/cocoa/widget/tab-frame.hpp rename to hiro/cocoa/widget/tab-frame.hpp diff --git a/phoenix/cocoa/widget/text-edit.cpp b/hiro/cocoa/widget/text-edit.cpp similarity index 100% rename from phoenix/cocoa/widget/text-edit.cpp rename to hiro/cocoa/widget/text-edit.cpp diff --git a/phoenix/cocoa/widget/text-edit.hpp b/hiro/cocoa/widget/text-edit.hpp similarity index 100% rename from phoenix/cocoa/widget/text-edit.hpp rename to hiro/cocoa/widget/text-edit.hpp diff --git a/phoenix/cocoa/widget/vertical-scroller.cpp b/hiro/cocoa/widget/vertical-scroller.cpp similarity index 100% rename from phoenix/cocoa/widget/vertical-scroller.cpp rename to hiro/cocoa/widget/vertical-scroller.cpp diff --git a/phoenix/cocoa/widget/vertical-scroller.hpp b/hiro/cocoa/widget/vertical-scroller.hpp similarity index 100% rename from phoenix/cocoa/widget/vertical-scroller.hpp rename to hiro/cocoa/widget/vertical-scroller.hpp diff --git a/phoenix/cocoa/widget/vertical-slider.cpp b/hiro/cocoa/widget/vertical-slider.cpp similarity index 100% rename from phoenix/cocoa/widget/vertical-slider.cpp rename to hiro/cocoa/widget/vertical-slider.cpp diff --git a/phoenix/cocoa/widget/vertical-slider.hpp b/hiro/cocoa/widget/vertical-slider.hpp similarity index 100% rename from phoenix/cocoa/widget/vertical-slider.hpp rename to hiro/cocoa/widget/vertical-slider.hpp diff --git a/phoenix/cocoa/widget/viewport.cpp b/hiro/cocoa/widget/viewport.cpp similarity index 100% rename from phoenix/cocoa/widget/viewport.cpp rename to hiro/cocoa/widget/viewport.cpp diff --git a/phoenix/cocoa/widget/viewport.hpp b/hiro/cocoa/widget/viewport.hpp similarity index 100% rename from phoenix/cocoa/widget/viewport.hpp rename to hiro/cocoa/widget/viewport.hpp diff --git a/phoenix/cocoa/widget/widget.cpp b/hiro/cocoa/widget/widget.cpp similarity index 100% rename from phoenix/cocoa/widget/widget.cpp rename to hiro/cocoa/widget/widget.cpp diff --git a/phoenix/cocoa/widget/widget.hpp b/hiro/cocoa/widget/widget.hpp similarity index 100% rename from phoenix/cocoa/widget/widget.hpp rename to hiro/cocoa/widget/widget.hpp diff --git a/phoenix/cocoa/window.cpp b/hiro/cocoa/window.cpp similarity index 100% rename from phoenix/cocoa/window.cpp rename to hiro/cocoa/window.cpp diff --git a/phoenix/cocoa/window.hpp b/hiro/cocoa/window.hpp similarity index 100% rename from phoenix/cocoa/window.hpp rename to hiro/cocoa/window.hpp diff --git a/hiro/core/action/action.cpp b/hiro/core/action/action.cpp new file mode 100644 index 00000000..c4199296 --- /dev/null +++ b/hiro/core/action/action.cpp @@ -0,0 +1,12 @@ +auto mAction::allocate() -> pObject* { + return new pAction(*this); +} + +// + +auto mAction::remove() -> type& { + if(auto menu = parentMenu()) menu->remove(*this); + if(auto menuBar = parentMenuBar()) menuBar->remove((mMenu&)*this); + if(auto popupMenu = parentPopupMenu()) popupMenu->remove(*this); + return *this; +} diff --git a/hiro/core/action/menu-check-item.cpp b/hiro/core/action/menu-check-item.cpp new file mode 100644 index 00000000..4b2d6392 --- /dev/null +++ b/hiro/core/action/menu-check-item.cpp @@ -0,0 +1,33 @@ +auto mMenuCheckItem::allocate() -> pObject* { + return new pMenuCheckItem(*this); +} + +// + +auto mMenuCheckItem::checked() const -> bool { + return state.checked; +} + +auto mMenuCheckItem::doToggle() const -> void { + if(state.onToggle) return state.onToggle(); +} + +auto mMenuCheckItem::onToggle(const function<void ()>& function) -> type& { + state.onToggle = function; + return *this; +} + +auto mMenuCheckItem::setChecked(bool checked) -> type& { + state.checked = checked; + signal(setChecked, checked); +} + +auto mMenuCheckItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mMenuCheckItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/action/menu-item.cpp b/hiro/core/action/menu-item.cpp new file mode 100644 index 00000000..25a8ad8f --- /dev/null +++ b/hiro/core/action/menu-item.cpp @@ -0,0 +1,34 @@ +auto mMenuItem::allocate() -> pObject* { + return new pMenuItem(*this); +} + +// + +auto mMenuItem::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mMenuItem::icon() const -> image { + return state.icon; +} + +auto mMenuItem::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mMenuItem::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mMenuItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mMenuItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/action/menu-radio-item.cpp b/hiro/core/action/menu-radio-item.cpp new file mode 100644 index 00000000..c4d940b8 --- /dev/null +++ b/hiro/core/action/menu-radio-item.cpp @@ -0,0 +1,51 @@ +auto mMenuRadioItem::allocate() -> pObject* { + return new pMenuRadioItem(*this); +} + +// + +auto mMenuRadioItem::group(const vector<shared_pointer_weak<mMenuRadioItem>>& group) -> void { + for(auto& weak : group) { + if(auto item = weak.acquire()) item->state.group = group; + } + for(auto& weak : group) { + if(auto item = weak.acquire()) { + if(item->self()) item->self()->setGroup(group); + } + } + if(group.size()) { + if(auto item = group.first().acquire()) item->setChecked(); + } +} + +auto mMenuRadioItem::checked() const -> bool { + return state.checked; +} + +auto mMenuRadioItem::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mMenuRadioItem::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mMenuRadioItem::setChecked() -> type& { + for(auto& weak : state.group) { + if(auto item = weak.acquire()) item->state.checked = false; + } + state.checked = true; + signal(setChecked); + return *this; +} + +auto mMenuRadioItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mMenuRadioItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/action/menu-separator.cpp b/hiro/core/action/menu-separator.cpp new file mode 100644 index 00000000..98246b1b --- /dev/null +++ b/hiro/core/action/menu-separator.cpp @@ -0,0 +1,3 @@ +auto mMenuSeparator::allocate() -> pObject* { + return new pMenuSeparator(*this); +} diff --git a/hiro/core/action/menu.cpp b/hiro/core/action/menu.cpp new file mode 100644 index 00000000..4cfeec33 --- /dev/null +++ b/hiro/core/action/menu.cpp @@ -0,0 +1,60 @@ +auto mMenu::allocate() -> pObject* { + return new pMenu(*this); +} + +auto mMenu::destruct() -> void { + for(auto& action : state.actions) action->destruct(); + mAction::destruct(); +} + +// + +auto mMenu::action(unsigned position) const -> sAction { + if(position >= actions()) throw; + return state.actions[position]; +} + +auto mMenu::actions() const -> unsigned { + return state.actions.size(); +} + +auto mMenu::append(sAction action) -> type& { + state.actions.append(action); + action->setParent(this, actions() - 1); + signal(append, *action); + return *this; +} + +auto mMenu::icon() const -> image { + return state.icon; +} + +auto mMenu::remove(sAction action) -> type& { + signal(remove, *action); + state.actions.remove(action->offset()); + for(auto n : range(action->offset(), actions())) { + state.actions[n]->offset(-1); + } + action->setParent(); +} + +auto mMenu::reset() -> type& { + while(state.actions) remove(state.actions.last()); + return *this; +} + +auto mMenu::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mMenu::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mMenu::text() const -> string { + return state.text; +} diff --git a/hiro/core/application.cpp b/hiro/core/application.cpp new file mode 100644 index 00000000..d6597aad --- /dev/null +++ b/hiro/core/application.cpp @@ -0,0 +1,97 @@ +auto Application::doMain() -> void { + if(state.onMain) return state.onMain(); +} + +auto Application::font() -> string { + return state.font; +} + +auto Application::name() -> string { + return state.name; +} + +auto Application::onMain(const nall::function<void ()>& function) -> void { + state.onMain = function; +} + +auto Application::run() -> void { + return pApplication::run(); +} + +auto Application::pendingEvents() -> bool { + return pApplication::pendingEvents(); +} + +auto Application::processEvents() -> void { + return pApplication::processEvents(); +} + +auto Application::quit() -> void { + state.quit = true; + return pApplication::quit(); +} + +auto Application::setFont(const string& font) -> void { + state.font = font; +} + +auto Application::setName(const string& name) -> void { + state.name = name; +} + +//Windows +//======= + +auto Application::Windows::doModalChange(bool modal) -> void { + if(state.windows.onModalChange) return state.windows.onModalChange(modal); +} + +auto Application::Windows::onModalChange(const function<void (bool)>& function) -> void { + state.windows.onModalChange = function; +} + +//Cocoa +//===== + +auto Application::Cocoa::doAbout() -> void { + if(state.cocoa.onAbout) return state.cocoa.onAbout(); +} + +auto Application::Cocoa::doActivate() -> void { + if(state.cocoa.onActivate) return state.cocoa.onActivate(); +} + +auto Application::Cocoa::doPreferences() -> void { + if(state.cocoa.onPreferences) return state.cocoa.onPreferences(); +} + +auto Application::Cocoa::doQuit() -> void { + if(state.cocoa.onQuit) return state.cocoa.onQuit(); +} + +auto Application::Cocoa::onAbout(const function<void ()>& function) -> void { + state.cocoa.onAbout = function; +} + +auto Application::Cocoa::onActivate(const function<void ()>& function) -> void { + state.cocoa.onActivate = function; +} + +auto Application::Cocoa::onPreferences(const function<void ()>& function) -> void { + state.cocoa.onPreferences = function; +} + +auto Application::Cocoa::onQuit(const function<void ()>& function) -> void { + state.cocoa.onQuit = function; +} + +//Internal +//======== + +auto Application::initialize() -> void { + static bool initialized = false; + if(initialized == false) { + initialized = true; + return pApplication::initialize(); + } +} diff --git a/hiro/core/browser-window.cpp b/hiro/core/browser-window.cpp new file mode 100644 index 00000000..7d24a1c5 --- /dev/null +++ b/hiro/core/browser-window.cpp @@ -0,0 +1,31 @@ +auto BrowserWindow::directory() -> string { + return pBrowserWindow::directory(state); +} + +auto BrowserWindow::open() -> string { + return pBrowserWindow::open(state); +} + +auto BrowserWindow::save() -> string { + return pBrowserWindow::save(state); +} + +auto BrowserWindow::setFilters(const lstring& filters) -> type& { + state.filters = filters; + return *this; +} + +auto BrowserWindow::setParent(shared_pointer<mWindow> parent) -> type& { + state.parent = parent; + return *this; +} + +auto BrowserWindow::setPath(const string& path) -> type& { + state.path = path; + return *this; +} + +auto BrowserWindow::setTitle(const string& title) -> type& { + state.title = title; + return *this; +} diff --git a/hiro/core/color.cpp b/hiro/core/color.cpp new file mode 100644 index 00000000..dd43696c --- /dev/null +++ b/hiro/core/color.cpp @@ -0,0 +1,83 @@ +Color::Color() { + setColor(0, 0, 0, 0); +} + +Color::Color(signed red, signed green, signed blue) { + setColor(255, red, green, blue); +} + +Color::Color(signed alpha, signed red, signed green, signed blue) { + setColor(alpha, red, green, blue); +} + +Color::operator bool() const { + return !empty(); +} + +auto Color::operator==(const Color& source) const -> bool { + return alpha() == source.alpha() && red() == source.red() && green() == source.green() && blue() == source.blue(); +} + +auto Color::operator!=(const Color& source) const -> bool { + return !operator==(source); +} + +auto Color::alpha() const -> uint8_t { + return state.alpha; +} + +auto Color::blue() const -> uint8_t { + return state.blue; +} + +auto Color::empty() const -> bool { + return state.alpha == 0 && state.red == 0 && state.green == 0 && state.blue == 0; +} + +auto Color::green() const -> uint8_t { + return state.green; +} + +auto Color::red() const -> uint8_t { + return state.red; +} + +auto Color::setAlpha(signed alpha) -> type& { + state.alpha = max(0, min(255, alpha)); + return *this; +} + +auto Color::setBlue(signed blue) -> type& { + state.blue = max(0, min(255, blue)); + return *this; +} + +auto Color::setColor(Color color) -> type& { + return setColor(color.alpha(), color.red(), color.green(), color.blue()); +} + +auto Color::setColor(signed red, signed green, signed blue) -> type& { + return setColor(255, red, green, blue); +} + +auto Color::setColor(signed alpha, signed red, signed green, signed blue) -> type& { + state.alpha = max(0, min(255, alpha)); + state.red = max(0, min(255, red )); + state.green = max(0, min(255, green)); + state.blue = max(0, min(255, blue )); + return *this; +} + +auto Color::setGreen(signed green) -> type& { + state.green = max(0, min(255, green)); + return *this; +} + +auto Color::setRed(signed red) -> type& { + state.red = max(0, min(255, red)); + return *this; +} + +auto Color::value() const -> uint32_t { + return (state.alpha << 24) + (state.red << 16) + (state.green << 8) + (state.blue << 0); +} diff --git a/hiro/core/core.cpp b/hiro/core/core.cpp new file mode 100644 index 00000000..531b94d7 --- /dev/null +++ b/hiro/core/core.cpp @@ -0,0 +1,100 @@ +#if defined(HIRO_WINDOWS) + #include "../windows/header.hpp" +#elif defined(HIRO_QT) + #include "../qt/header.hpp" +#elif defined(HIRO_GTK) + #include "../gtk/header.hpp" +#elif defined(HIRO_COCOA) + #include "../cocoa/header.hpp" +#elif defined(HIRO_REFERENCE) + #include "../reference/header.hpp" +#endif + +#include "core.hpp" +using namespace nall; + +namespace hiro { + Application::State Application::state; + Keyboard::State Keyboard::state; +} + +#if defined(HIRO_WINDOWS) + #include "../windows/platform.cpp" +#elif defined(HIRO_QT) + #include "../qt/platform.cpp" +#elif defined(HIRO_GTK) + #include "../gtk/platform.cpp" +#elif defined(HIRO_COCOA) + #include "../cocoa/platform.cpp" +#elif defined(HIRO_REFERENCE) + #include "../reference/platform.cpp" +#endif + +#define signal(function, ...) \ + (delegate ? self()->function(__VA_ARGS__) : decltype(self()->function(__VA_ARGS__))()) + +namespace hiro { + #include "application.cpp" + #include "color.cpp" + #include "position.cpp" + #include "size.cpp" + #include "geometry.cpp" + #include "font.cpp" + #include "desktop.cpp" + #include "monitor.cpp" + #include "keyboard.cpp" + #include "mouse.cpp" + #include "browser-window.cpp" + #include "message-window.cpp" + #include "object.cpp" + #include "hotkey.cpp" + #include "timer.cpp" + #include "window.cpp" + #include "status-bar.cpp" + #include "menu-bar.cpp" + #include "popup-menu.cpp" + + #include "action/action.cpp" + #include "action/menu.cpp" + #include "action/menu-separator.cpp" + #include "action/menu-item.cpp" + #include "action/menu-check-item.cpp" + #include "action/menu-radio-item.cpp" + + #include "sizable.cpp" + #include "layout.cpp" + + #include "widget/widget.cpp" + #include "widget/button.cpp" + #include "widget/canvas.cpp" + #include "widget/check-button.cpp" + #include "widget/check-label.cpp" + #include "widget/combo-button.cpp" + #include "widget/combo-button-item.cpp" + #include "widget/console.cpp" + #include "widget/frame.cpp" + #include "widget/hex-edit.cpp" + #include "widget/horizontal-scroller.cpp" + #include "widget/horizontal-slider.cpp" + #include "widget/icon-view.cpp" + #include "widget/icon-view-item.cpp" + #include "widget/label.cpp" + #include "widget/line-edit.cpp" + #include "widget/list-view.cpp" + #include "widget/list-view-column.cpp" + #include "widget/list-view-item.cpp" + #include "widget/progress-bar.cpp" + #include "widget/radio-button.cpp" + #include "widget/radio-label.cpp" + #include "widget/source-edit.cpp" + #include "widget/tab-frame.cpp" + #include "widget/tab-frame-item.cpp" + #include "widget/text-edit.cpp" + #include "widget/tree-view.cpp" + #include "widget/tree-view-item.cpp" + #include "widget/vertical-scroller.cpp" + #include "widget/vertical-slider.cpp" + #include "widget/viewport.cpp" +} + +#undef signal diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp new file mode 100644 index 00000000..47e3d6e1 --- /dev/null +++ b/hiro/core/core.hpp @@ -0,0 +1,1571 @@ +#include <nall/platform.hpp> +#include <nall/config.hpp> +#include <nall/directory.hpp> +#include <nall/function.hpp> +#include <nall/image.hpp> +#include <nall/maybe.hpp> +#include <nall/range.hpp> +#include <nall/shared-pointer.hpp> +#include <nall/stdint.hpp> +#include <nall/string.hpp> +#include <nall/traits.hpp> +#include <nall/utility.hpp> +#include <nall/vector.hpp> + +using nall::function; +using nall::image; +using nall::lstring; +using nall::maybe; +using nall::shared_pointer; +using nall::shared_pointer_weak; +using nall::string; +using nall::vector; + +namespace hiro { + +#define Declare(Name) \ + struct m##Name; \ + struct p##Name; \ + using s##Name = shared_pointer<m##Name>; \ + using w##Name = shared_pointer_weak<m##Name>; \ + +Declare(Keyboard) +Declare(Object) +Declare(Timer) +Declare(Hotkey) +Declare(Window) +Declare(StatusBar) +Declare(MenuBar) +Declare(PopupMenu) +Declare(Action) +Declare(Menu) +Declare(MenuSeparator) +Declare(MenuItem) +Declare(MenuCheckItem) +Declare(MenuRadioItem) +Declare(Sizable) +Declare(Layout) +Declare(Widget) +Declare(Button) +Declare(Canvas) +Declare(CheckButton) +Declare(CheckLabel) +Declare(ComboButton) +Declare(ComboButtonItem) +Declare(Console) +Declare(Frame) +Declare(HexEdit) +Declare(HorizontalScroller) +Declare(HorizontalSlider) +Declare(IconView) +Declare(IconViewItem) +Declare(Label) +Declare(LineEdit) +Declare(ListView) +Declare(ListViewColumn) +Declare(ListViewItem) +Declare(ProgressBar) +Declare(RadioButton) +Declare(RadioLabel) +Declare(SourceEdit) +Declare(TabFrame) +Declare(TabFrameItem) +Declare(TextEdit) +Declare(TreeView) +Declare(TreeViewItem) +Declare(VerticalScroller) +Declare(VerticalSlider) +Declare(Viewport) + +#undef Declare + +enum class Edge : unsigned { Top, Bottom, Left, Right }; + +enum class Orientation : unsigned { Horizontal, Vertical }; + +struct Application { + Application() = delete; + + static auto doMain() -> void; + static auto font() -> string; + static auto name() -> string; + static auto onMain(const function<void ()>& function = {}) -> void; + static auto run() -> void; + static auto pendingEvents() -> bool; + static auto processEvents() -> void; + static auto quit() -> void; + static auto setFont(const string& font = "") -> void; + static auto setName(const string& name = "") -> void; + + struct Windows { + static auto doModalChange(bool modal) -> void; + static auto onModalChange(const function<void (bool)>& function = {}) -> void; + }; + + struct Cocoa { + static auto doAbout() -> void; + static auto doActivate() -> void; + static auto doPreferences() -> void; + static auto doQuit() -> void; + static auto onAbout(const function<void ()>& function = {}) -> void; + static auto onActivate(const function<void ()>& function = {}) -> void; + static auto onPreferences(const function<void ()>& function = {}) -> void; + static auto onQuit(const function<void ()>& function = {}) -> void; + }; + +//private: + struct State { + string font; + string name; + function<void ()> onMain; + bool quit = false; + + struct Windows { + function<void (bool)> onModalChange; + } windows; + + struct Cocoa { + function<void ()> onAbout; + function<void ()> onActivate; + function<void ()> onPreferences; + function<void ()> onQuit; + } cocoa; + }; + static State state; + static auto initialize() -> void; +}; + +struct Color { + using type = Color; + + Color(); + Color(signed red, signed green, signed blue); + Color(signed alpha, signed red, signed green, signed blue); + + explicit operator bool() const; + auto operator==(const Color& source) const -> bool; + auto operator!=(const Color& source) const -> bool; + + auto alpha() const -> uint8_t; + auto blue() const -> uint8_t; + auto empty() const -> bool; + auto green() const -> uint8_t; + auto red() const -> uint8_t; + auto setAlpha(signed alpha) -> type&; + auto setBlue(signed blue) -> type&; + auto setColor(Color color = {}) -> type&; + auto setColor(signed red, signed green, signed blue) -> type&; + auto setColor(signed alpha, signed red, signed green, signed blue) -> type&; + auto setGreen(signed green) -> type&; + auto setRed(signed red) -> type&; + auto value() const -> uint32_t; + +//private: + struct State { + signed alpha; + signed red; + signed green; + signed blue; + } state; +}; + +struct Position { + using type = Position; + + Position(); + Position(signed x, signed y); + + auto operator==(const Position& source) const -> bool; + auto operator!=(const Position& source) const -> bool; + + auto setPosition(Position position = {}) -> type&; + auto setPosition(signed x, signed y) -> type&; + auto setX(signed x) -> type&; + auto setY(signed y) -> type&; + auto x() const -> signed; + auto y() const -> signed; + +//private: + struct State { + signed x; + signed y; + } state; +}; + +struct Size { + using type = Size; + + Size(); + Size(signed width, signed height); + + auto operator==(const Size& source) const -> bool; + auto operator!=(const Size& source) const -> bool; + + auto height() const -> signed; + auto setHeight(signed height) -> type&; + auto setSize(Size source = {}) -> type&; + auto setSize(signed width, signed height) -> type&; + auto setWidth(signed width) -> type&; + auto width() const -> signed; + + static const signed Maximum = ~0; //~0 == -1 + static const signed Minimum = 0; + +//private: + struct State { + signed width; + signed height; + } state; +}; + +struct Geometry { + using type = Geometry; + + Geometry(); + Geometry(Position position, Size size); + Geometry(signed x, signed y, signed width, signed height); + Geometry(const string& text); + + auto operator==(const Geometry& source) const -> bool; + auto operator!=(const Geometry& source) const -> bool; + + auto height() const -> signed; + auto position() const -> Position; + auto setGeometry(Geometry geometry = {}) -> type&; + auto setGeometry(Position position, Size size) -> type&; + auto setGeometry(signed x, signed y, signed width, signed height) -> type&; + auto setHeight(signed height) -> type&; + auto setPosition(Position position = {}) -> type&; + auto setPosition(signed x, signed y) -> type&; + auto setSize(Size size = {}) -> type&; + auto setSize(signed width, signed height) -> type&; + auto setWidth(signed width) -> type&; + auto setX(signed x) -> type&; + auto setY(signed y) -> type&; + auto size() const -> Size; + auto text() const -> string; + auto width() const -> signed; + auto x() const -> signed; + auto y() const -> signed; + +//private: + struct State { + signed x; + signed y; + signed width; + signed height; + } state; +}; + +struct Font { + Font() = delete; + + static auto serif(unsigned size = 0, const string& style = "") -> string; + static auto sans(unsigned size = 0, const string& style = "") -> string; + static auto monospace(unsigned size = 0, const string& style = "") -> string; + static auto size(const string& font, const string& text = " ") -> Size; +}; + +struct Desktop { + Desktop() = delete; + + static auto size() -> Size; + static auto workspace() -> Geometry; +}; + +struct Monitor { + Monitor() = delete; + + static auto count() -> unsigned; + static auto geometry(unsigned monitor) -> Geometry; + static auto primary() -> unsigned; +}; + +struct Keyboard { + Keyboard() = delete; + + static auto append(sHotkey hotkey) -> void; + static auto hotkey(unsigned position) -> sHotkey; + static auto hotkeys() -> unsigned; + static auto poll() -> vector<bool>; + static auto pressed(const string& key) -> bool; + static auto released(const string& key) -> bool; + static auto remove(sHotkey hotkey) -> void; + + static const vector<string> keys; + +//private: + struct State { + vector<sHotkey> hotkeys; + }; + static State state; +}; + +struct Mouse { + enum class Button : unsigned { Left, Middle, Right }; + + Mouse() = delete; + + static auto position() -> Position; + static auto pressed(Button) -> bool; + static auto released(Button) -> bool; +}; + +struct BrowserWindow { + using type = BrowserWindow; + + auto directory() -> string; + auto open() -> string; + auto save() -> string; + auto setFilters(const lstring& filters = {"*"}) -> type&; + auto setParent(sWindow parent) -> type&; + auto setPath(const string& path = "") -> type&; + auto setTitle(const string& title = "") -> type&; + +//private: + struct State { + lstring filters; + sWindow parent; + string path; + string title; + } state; +}; + +struct MessageWindow { + enum class Buttons : unsigned { Ok, OkCancel, YesNo, YesNoCancel }; + enum class Response : unsigned { Ok, Cancel, Yes, No }; + + using type = MessageWindow; + + MessageWindow(const string& text = ""); + + auto error(Buttons = Buttons::Ok) -> Response; + auto information(Buttons = Buttons::Ok) -> Response; + auto question(Buttons = Buttons::YesNo) -> Response; + auto setParent(sWindow parent) -> type&; + auto setText(const string& text = "") -> type&; + auto setTitle(const string& title = "") -> type&; + auto warning(Buttons = Buttons::Ok) -> Response; + +//private: + struct State { + MessageWindow::Buttons buttons = MessageWindow::Buttons::Ok; + sWindow parent; + string text; + string title; + } state; +}; + +#define Declare(Name) \ + using type = m##Name; \ + operator s##Name() const { return instance; } \ + auto self() -> p##Name* { return (p##Name*)delegate; } \ + auto self() const -> const p##Name* { return (const p##Name*)delegate; } \ + auto bind(const s##Name& instance) -> void { \ + this->instance = instance; \ + if(!abstract()) construct(); \ + } \ + auto unbind() -> void { \ + reset(); \ + destruct(); \ + instance.reset(); \ + } \ + virtual auto allocate() -> pObject*; \ + +struct mObject { + Declare(Object) + + mObject(); + virtual ~mObject(); + mObject(const mObject&) = delete; + mObject& operator=(const mObject&) = delete; + + auto abstract() const -> bool; + auto enabled(bool recursive = false) const -> bool; + virtual auto focused() const -> bool; + auto font(bool recursive = false) const -> string; + auto offset() const -> signed; + auto offset(signed displacement) -> type&; + auto parent() const -> mObject*; + auto parentComboButton(bool recursive = false) const -> mComboButton*; + auto parentFrame(bool recursive = false) const -> mFrame*; + auto parentIconView(bool recursive = false) const -> mIconView*; + auto parentLayout(bool recursive = false) const -> mLayout*; + auto parentListView(bool recursive = false) const -> mListView*; + auto parentMenu(bool recursive = false) const -> mMenu*; + auto parentMenuBar(bool recursive = false) const -> mMenuBar*; + auto parentPopupMenu(bool recursive = false) const -> mPopupMenu*; + auto parentSizable(bool recursive = false) const -> mSizable*; + auto parentTabFrame(bool recursive = false) const -> mTabFrame*; + auto parentTabFrameItem(bool recursive = false) const -> mTabFrameItem*; + auto parentTreeView(bool recursive = false) const -> mTreeView*; + auto parentTreeViewItem(bool recursive = false) const -> mTreeViewItem*; + auto parentWidget(bool recursive = false) const -> mWidget*; + auto parentWindow(bool recursive = false) const -> mWindow*; + virtual auto remove() -> type&; + virtual auto reset() -> type&; + virtual auto setEnabled(bool enabled = true) -> type&; + virtual auto setFocused() -> type&; + virtual auto setFont(const string& font = "") -> type&; + virtual auto setParent(mObject* parent = nullptr, signed offset = -1) -> type&; + virtual auto setVisible(bool visible = true) -> type&; + auto visible(bool recursive = false) const -> bool; + +//private: + struct State { + bool enabled = true; + string font; + signed offset = -1; + mObject* parent = nullptr; + bool visible = true; + } state; + + wObject instance; + pObject* delegate = nullptr; + + virtual auto construct() -> void; + virtual auto destruct() -> void; +}; + +struct mHotkey : mObject { + Declare(Hotkey) + + auto doPress() const -> void; + auto doRelease() const -> void; + auto onPress(const function<void ()>& function = {}) -> type&; + auto onRelease(const function<void ()>& function = {}) -> type&; + auto parent() const -> wObject; + auto remove() -> type& override; + auto sequence() const -> string; + auto setParent(sObject parent) -> type&; + auto setSequence(const string& sequence = "") -> type&; + +//private: + struct State { + bool active = false; + vector<unsigned> keys; + function<void ()> onPress; + function<void ()> onRelease; + wObject parent; + string sequence; + } state; +}; + +struct mTimer : mObject { + Declare(Timer) + + auto doActivate() const -> void; + auto interval() const -> unsigned; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto setInterval(unsigned interval = 0) -> type&; + +//private: + struct State { + unsigned interval = 0; + function<void ()> onActivate; + } state; +}; + +struct mWindow : mObject { + Declare(Window) + using mObject::remove; + + auto append(sLayout layout) -> type&; + auto append(sMenuBar menuBar) -> type&; + auto append(sStatusBar statusBar) -> type&; + auto backgroundColor() const -> Color; + auto doClose() const -> void; + auto doDrop(lstring) const -> void; + auto doKeyPress(signed) const -> void; + auto doKeyRelease(signed) const -> void; + auto doMove() const -> void; + auto doSize() const -> void; + auto droppable() const -> bool; + auto frameGeometry() const -> Geometry; + auto fullScreen() const -> bool; + auto geometry() const -> Geometry; + auto layout() const -> sLayout; + auto menuBar() const -> sMenuBar; + auto modal() const -> bool; + auto onClose(const function<void ()>& function = {}) -> type&; + auto onDrop(const function<void (lstring)>& function = {}) -> type&; + auto onKeyPress(const function<void (signed)>& function = {}) -> type&; + auto onKeyRelease(const function<void (signed)>& function = {}) -> type&; + auto onMove(const function<void ()>& function = {}) -> type&; + auto onSize(const function<void ()>& function = {}) -> type&; + auto remove(sLayout layout) -> type&; + auto remove(sMenuBar menuBar) -> type&; + auto remove(sStatusBar statusBar) -> type&; + auto reset() -> type& override; + auto resizable() const -> bool; + auto setBackgroundColor(Color color = {}) -> type&; + auto setCentered() -> type&; + auto setCentered(sWindow parent) -> type&; + auto setDroppable(bool droppable = true) -> type&; + auto setFrameGeometry(Geometry geometry) -> type&; + auto setFramePosition(Position position) -> type&; + auto setFrameSize(Size size) -> type&; + auto setFullScreen(bool fullScreen = true) -> type&; + auto setGeometry(Geometry geometry) -> type&; + auto setModal(bool modal = true) -> type&; + auto setPosition(Position position) -> type&; + auto setResizable(bool resizable = true) -> type&; + auto setSize(Size size) -> type&; + auto setTitle(const string& title = "") -> type&; + auto statusBar() const -> sStatusBar; + auto title() const -> string; + +//private: + struct State { + Color backgroundColor; + bool droppable = false; + bool fullScreen = false; + Geometry geometry = {128, 128, 256, 256}; + sLayout layout; + sMenuBar menuBar; + bool modal = false; + function<void ()> onClose; + function<void (lstring)> onDrop; + function<void (signed)> onKeyPress; + function<void (signed)> onKeyRelease; + function<void ()> onMove; + function<void ()> onSize; + bool resizable = true; + sStatusBar statusBar; + string title; + } state; + + auto destruct() -> void; +}; + +struct mStatusBar : mObject { + Declare(StatusBar) + + auto remove() -> type& override; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + string text; + } state; +}; + +struct mMenuBar : mObject { + Declare(MenuBar) + + auto append(sMenu menu) -> type&; + auto menu(unsigned position) const -> sMenu; + auto menus() const -> unsigned; + auto remove() -> type& override; + auto remove(sMenu menu) -> type&; + auto reset() -> type&; + +//private: + struct State { + vector<sMenu> menus; + } state; + + auto destruct() -> void override; +}; + +struct mPopupMenu : mObject { + Declare(PopupMenu) + using mObject::remove; + + auto action(unsigned position) const -> sAction; + auto actions() const -> unsigned; + auto append(sAction action) -> type&; + auto remove(sAction action) -> type&; + auto reset() -> type&; + auto setVisible(bool visible = true) -> type& override; + +//private: + struct State { + vector<sAction> actions; + } state; + + auto destruct() -> void override; +}; + +struct mAction : mObject { + Declare(Action) + + auto remove() -> type& override; + +//private: + struct State { + } state; +}; + +struct mMenu : mAction { + Declare(Menu) + using mObject::remove; + + auto action(unsigned position) const -> sAction; + auto actions() const -> unsigned; + auto append(sAction action) -> type&; + auto icon() const -> image; + auto remove(sAction action) -> type&; + auto reset() -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + vector<sAction> actions; + image icon; + string text; + } state; + + auto destruct() -> void override; +}; + +struct mMenuSeparator : mAction { + Declare(MenuSeparator) + +//private: + struct State { + } state; +}; + +struct mMenuItem : mAction { + Declare(MenuItem) + + auto doActivate() const -> void; + auto icon() const -> image; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + image icon; + function<void ()> onActivate; + string text; + } state; +}; + +struct mMenuCheckItem : mAction { + Declare(MenuCheckItem) + + auto checked() const -> bool; + auto doToggle() const -> void; + auto onToggle(const function<void ()>& function = {}) -> type&; + auto setChecked(bool checked = true) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool checked = false; + function<void ()> onToggle; + string text; + } state; +}; + +struct mMenuRadioItem : mAction { + Declare(MenuRadioItem) + + auto checked() const -> bool; + auto doActivate() const -> void; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto setChecked() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + + static auto group(const vector<wMenuRadioItem>& group) -> void; + +//private: + struct State { + bool checked = true; + vector<wMenuRadioItem> group; + function<void ()> onActivate; + string text; + } state; +}; + +struct mSizable : mObject { + Declare(Sizable) + + auto geometry() const -> Geometry; + virtual auto minimumSize() const -> Size; + virtual auto setGeometry(Geometry geometry) -> type&; + +//private: + struct State { + Geometry geometry; + } state; +}; + +struct mLayout : mSizable { + Declare(Layout) + + virtual auto append(sSizable sizable) -> type&; + virtual auto remove() -> type& override; + virtual auto remove(sSizable sizable) -> type&; + virtual auto reset() -> type&; + auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override; + auto sizable(unsigned position) const -> sSizable; + auto sizables() const -> unsigned; + +//private: + struct State { + vector<sSizable> sizables; + } state; + + auto destruct() -> void override; +}; + +struct mWidget : mSizable { + Declare(Widget) + + auto doSize() const -> void; + auto onSize(const function<void ()>& function = {}) -> type&; + auto remove() -> type& override; + +//private: + struct State { + function<void ()> onSize; + } state; +}; + +struct mButton : mWidget { + Declare(Button) + + auto bordered() const -> bool; + auto doActivate() const -> void; + auto icon() const -> image; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto orientation() const -> Orientation; + auto setBordered(bool bordered = true) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool bordered = true; + image icon; + function<void ()> onActivate; + Orientation orientation = Orientation::Horizontal; + string text; + } state; +}; + +struct mCanvas : mWidget { + Declare(Canvas) + + auto color() const -> Color; + auto data() -> uint32_t*; + auto droppable() const -> bool; + auto doDrop(lstring names) const -> void; + auto doMouseLeave() const -> void; + auto doMouseMove(Position position) const -> void; + auto doMousePress(Mouse::Button button) const -> void; + auto doMouseRelease(Mouse::Button button) const -> void; + auto gradient() const -> vector<Color>; + auto icon() const -> image; + auto onDrop(const function<void (lstring)>& function = {}) -> type&; + auto onMouseLeave(const function<void ()>& function = {}) -> type&; + auto onMouseMove(const function<void (Position)>& function = {}) -> type&; + auto onMousePress(const function<void (Mouse::Button)>& function = {}) -> type&; + auto onMouseRelease(const function<void (Mouse::Button)>& function = {}) -> type&; + auto setColor(Color color) -> type&; + auto setData(Size size) -> type&; + auto setDroppable(bool droppable = true) -> type&; + auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> type&; + auto setHorizontalGradient(Color left, Color right) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setVerticalGradient(Color top, Color bottom) -> type&; + auto size() const -> Size; + auto update() -> type&; + +//private: + struct State { + Color color; + vector<uint32_t> data; + bool droppable = false; + vector<Color> gradient = {{}, {}, {}, {}}; + image icon; + function<void (lstring)> onDrop; + function<void ()> onMouseLeave; + function<void (Position)> onMouseMove; + function<void (Mouse::Button)> onMousePress; + function<void (Mouse::Button)> onMouseRelease; + Size size; + } state; +}; + +struct mCheckButton : mWidget { + Declare(CheckButton) + + auto bordered() const -> bool; + auto checked() const -> bool; + auto doToggle() const -> void; + auto icon() const -> image; + auto onToggle(const function<void ()>& function = {}) -> type&; + auto orientation() const -> Orientation; + auto setBordered(bool bordered = true) -> type&; + auto setChecked(bool checked = true) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool bordered = false; + bool checked = false; + image icon; + function<void ()> onToggle; + Orientation orientation = Orientation::Horizontal; + string text; + } state; +}; + +struct mCheckLabel : mWidget { + Declare(CheckLabel) + + auto checked() const -> bool; + auto doToggle() const -> void; + auto onToggle(const function<void ()>& function = {}) -> type&; + auto setChecked(bool checked = true) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool checked = false; + function<void ()> onToggle; + string text; + } state; +}; + +struct mComboButton : mWidget { + Declare(ComboButton) + using mObject::remove; + + auto append(sComboButtonItem item) -> type&; + auto doChange() const -> void; + auto item(unsigned position) const -> sComboButtonItem; + auto items() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto remove(sComboButtonItem item) -> type&; + auto reset() -> type&; + auto selected() const -> sComboButtonItem; + +//private: + struct State { + vector<sComboButtonItem> items; + function<void ()> onChange; + signed selected = -1; + } state; + + auto destruct() -> void override; +}; + +struct mComboButtonItem : mObject { + Declare(ComboButtonItem) + + auto icon() const -> image; + auto remove() -> type& override; + auto selected() const -> bool; + auto setIcon(const image& icon = {}) -> type&; + auto setSelected() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + image icon; + string text; + } state; +}; + +struct mConsole : mWidget { + Declare(Console) + + auto backgroundColor() const -> Color; + auto doActivate(string) const -> void; + auto foregroundColor() const -> Color; + auto onActivate(const function<void (string)>& function = {}) -> type&; + auto print(const string& text) -> type&; + auto prompt() const -> string; + auto reset() -> type&; + auto setBackgroundColor(Color color = {}) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setPrompt(const string& prompt = "") -> type&; + +//private: + struct State { + Color backgroundColor; + Color foregroundColor; + function<void (string)> onActivate; + string prompt; + } state; +}; + +struct mFrame : mWidget { + Declare(Frame) + using mObject::remove; + + auto append(sLayout layout) -> type&; + auto layout() const -> sLayout; + auto remove(sLayout layout) -> type&; + auto reset() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + sLayout layout; + string text; + } state; + + auto destruct() -> void override; +}; + +struct mHexEdit : mWidget { + Declare(HexEdit) + + auto backgroundColor() const -> Color; + auto columns() const -> unsigned; + auto doRead(unsigned offset) const -> uint8_t; + auto doWrite(unsigned offset, uint8_t data) const -> void; + auto foregroundColor() const -> Color; + auto length() const -> unsigned; + auto offset() const -> unsigned; + auto onRead(const function<uint8_t (unsigned)>& function = {}) -> type&; + auto onWrite(const function<void (unsigned, uint8_t)>& function = {}) -> type&; + auto rows() const -> unsigned; + auto setBackgroundColor(Color color = {}) -> type&; + auto setColumns(unsigned columns = 16) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setLength(unsigned length) -> type&; + auto setOffset(unsigned offset) -> type&; + auto setRows(unsigned rows = 16) -> type&; + auto update() -> type&; + +//private: + struct State { + Color backgroundColor; + unsigned columns = 16; + Color foregroundColor; + unsigned length = 0; + unsigned offset = 0; + function<uint8_t (unsigned)> onRead; + function<void (unsigned, uint8_t)> onWrite; + unsigned rows = 16; + } state; +}; + +struct mHorizontalScroller : mWidget { + Declare(HorizontalScroller) + + auto doChange() const -> void; + auto length() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto position() const -> unsigned; + auto setLength(unsigned length = 101) -> type&; + auto setPosition(unsigned position = 0) -> type&; + +//private: + struct State { + unsigned length = 101; + function<void ()> onChange; + unsigned position = 0; + } state; +}; + +struct mHorizontalSlider : mWidget { + Declare(HorizontalSlider) + + auto doChange() const -> void; + auto length() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto position() const -> unsigned; + auto setLength(unsigned length = 101) -> type&; + auto setPosition(unsigned position = 0) -> type&; + +//private: + struct State { + unsigned length = 101; + function<void ()> onChange; + unsigned position = 0; + } state; +}; + +struct mIconView : mWidget { + Declare(IconView) + using mObject::remove; + + auto append(sIconViewItem item) -> type&; + auto backgroundColor() const -> Color; + auto doActivate() const -> void; + auto doChange() const -> void; + auto doContext() const -> void; + auto flow() const -> Orientation; + auto foregroundColor() const -> Color; + auto item(unsigned position) const -> sIconViewItem; + auto items() const -> unsigned; + auto multiSelect() const -> bool; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onContext(const function<void ()>& function = {}) -> type&; + auto orientation() const -> Orientation; + auto remove(sIconViewItem item) -> type&; + auto reset() -> type&; + auto selected() const -> maybe<unsigned>; + auto selectedItems() const -> vector<unsigned>; + auto setBackgroundColor(Color color = {}) -> type&; + auto setFlow(Orientation flow = Orientation::Vertical) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setMultiSelect(bool multipleSelections = true) -> type&; + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type&; + auto setSelected(const vector<signed>& selections) -> type&; + +//private: + struct State { + Color backgroundColor; + Color foregroundColor; + Orientation flow = Orientation::Vertical; + vector<sIconViewItem> items; + bool multiSelect = false; + function<void ()> onActivate; + function<void ()> onChange; + function<void ()> onContext; + Orientation orientation = Orientation::Horizontal; + } state; + + auto destruct() -> void override; +}; + +struct mIconViewItem : mObject { + Declare(IconViewItem) + + auto icon() const -> image; + auto remove() -> type& override; + auto selected() const -> bool; + auto setIcon(const image& icon = {}) -> type&; + auto setSelected(bool selected = true) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + image icon; + bool selected = false; + string text; + } state; +}; + +struct mLabel : mWidget { + Declare(Label) + + auto horizontalAlignment() const -> double; + auto setHorizontalAlignment(double alignment = 0.0) -> type&; + auto setText(const string& text = "") -> type&; + auto setVerticalAlignment(double alignment = 0.5) -> type&; + auto text() const -> string; + auto verticalAlignment() const -> double; + +//private: + struct State { + double horizontalAlignment = 0.0; + string text; + double verticalAlignment = 0.5; + } state; +}; + +struct mLineEdit : mWidget { + Declare(LineEdit) + + auto backgroundColor() const -> Color; + auto doActivate() const -> void; + auto doChange() const -> void; + auto editable() const -> bool; + auto foregroundColor() const -> Color; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto onChange(const function<void ()>& function = {}) -> type&; + auto setBackgroundColor(Color color = {}) -> type&; + auto setEditable(bool editable = true) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + Color backgroundColor; + bool editable = true; + Color foregroundColor; + function<void ()> onActivate; + function<void ()> onChange; + string text; + } state; +}; + +struct mListView : mWidget { + Declare(ListView) + using mObject::remove; + + auto append(sListViewColumn column) -> type&; + auto append(sListViewItem item) -> type&; + auto backgroundColor() const -> Color; + auto checkable() const -> bool; + auto checked() const -> vector<sListViewItem>; + auto column(unsigned position) const -> sListViewColumn; + auto columns() const -> unsigned; + auto doActivate() const -> void; + auto doChange() const -> void; + auto doContext() const -> void; + auto doEdit(sListViewItem item, sListViewColumn column) const -> void; + auto doSort(sListViewColumn column) const -> void; + auto doToggle(sListViewItem item) const -> void; + auto foregroundColor() const -> Color; + auto gridVisible() const -> bool; + auto headerVisible() const -> bool; + auto item(unsigned position) const -> sListViewItem; + auto items() const -> unsigned; + auto multiSelect() const -> bool; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onContext(const function<void ()>& function = {}) -> type&; + auto onEdit(const function<void (sListViewItem, sListViewColumn)>& function = {}) -> type&; + auto onSort(const function<void (sListViewColumn)>& function = {}) -> type&; + auto onToggle(const function<void (sListViewItem)>& function = {}) -> type&; + auto remove(sListViewColumn column) -> type&; + auto remove(sListViewItem item) -> type&; + auto reset() -> type&; + auto resizeColumns() -> type&; + auto selected() const -> sListViewItem; + auto selectedItems() const -> vector<sListViewItem>; + auto setBackgroundColor(Color color = {}) -> type&; + auto setCheckable(bool checkable = true) -> type&; + auto setChecked(bool checked = true) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setGridVisible(bool visible = true) -> type&; + auto setHeaderVisible(bool visible = true) -> type&; + auto setMultiSelect(bool multiSelect = true) -> type&; + auto setSelected(bool selected = true) -> type&; + +//private: + struct State { + unsigned activeColumn = 0; + Color backgroundColor; + bool checkable = false; + vector<sListViewColumn> columns; + Color foregroundColor; + bool gridVisible = false; + bool headerVisible = false; + vector<sListViewItem> items; + bool multiSelect = false; + function<void ()> onActivate; + function<void ()> onChange; + function<void ()> onContext; + function<void (sListViewItem, sListViewColumn)> onEdit; + function<void (sListViewColumn)> onSort; + function<void (sListViewItem)> onToggle; + } state; + + auto destruct() -> void override; +}; + +struct mListViewColumn : mObject { + Declare(ListViewColumn) + + auto active() const -> bool; + auto backgroundColor() const -> Color; + auto editable() const -> bool; + auto foregroundColor() const -> Color; + auto horizontalAlignment() const -> double; + auto icon() const -> image; + auto remove() -> type& override; + auto resizable() const -> bool; + auto setActive() -> type&; + auto setBackgroundColor(Color color = {}) -> type&; + auto setEditable(bool editable = true) -> type&; + auto setFont(const string& font = "") -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setHorizontalAlignment(double alignment = 0.0) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setResizable(bool resizable = true) -> type&; + auto setSortable(bool sortable = true) -> type&; + auto setText(const string& text = "") -> type&; + auto setVerticalAlignment(double alignment = 0.5) -> type&; + auto setVisible(bool visible = true) -> type&; + auto setWidth(signed width = 0) -> type&; + auto sortable() const -> bool; + auto text() const -> string; + auto verticalAlignment() const -> double; + auto width() const -> signed; + +//private: + struct State { + Color backgroundColor; + bool editable = false; + string font; + Color foregroundColor; + double horizontalAlignment = 0.0; + image icon; + bool resizable = true; + bool sortable = false; + string text; + double verticalAlignment = 0.5; + bool visible = true; + signed width = 0; + } state; +}; + +struct mListViewItem : mObject { + Declare(ListViewItem) + + auto checked() const -> bool; + auto icon(unsigned column = 0) const -> image; + auto remove() -> type& override; + auto selected() const -> bool; + auto setChecked(bool checked = true) -> type&; + auto setFocused() -> type& override; + auto setIcon(unsigned column, const image& icon = {}) -> type&; + auto setSelected(bool selected = true) -> type&; + auto setText(const lstring& text) -> type&; + auto setText(unsigned column, const string& text = "") -> type&; + auto text(unsigned column = 0) const -> string; + +//private: + struct State { + bool checked = false; + vector<image> icon; + bool selected = false; + lstring text; + } state; +}; + +struct mProgressBar : mWidget { + Declare(ProgressBar) + + auto position() const -> unsigned; + auto setPosition(unsigned position) -> type&; + +//private: + struct State { + unsigned position = 0; + } state; +}; + +struct mRadioButton : mWidget { + Declare(RadioButton) + + auto bordered() const -> bool; + auto checked() const -> bool; + auto doActivate() const -> void; + auto icon() const -> image; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto orientation() const -> Orientation; + auto setBordered(bool bordered = true) -> type&; + auto setChecked() -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + + static auto group(const vector<wRadioButton>& group) -> void; + +//private: + struct State { + bool bordered = true; + bool checked = true; + vector<wRadioButton> group; + image icon; + function<void ()> onActivate; + Orientation orientation = Orientation::Horizontal; + string text; + } state; +}; + +struct mRadioLabel : mWidget { + Declare(RadioLabel) + + auto checked() const -> bool; + auto doActivate() const -> void; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto setChecked() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + + static auto group(const vector<wRadioLabel>& group) -> void; + +//private: + struct State { + bool checked = true; + vector<wRadioLabel> group; + function<void ()> onActivate; + string text; + } state; +}; + +struct mSourceEdit : mWidget { + Declare(SourceEdit) + + auto doChange() const -> void; + auto doMove() const -> void; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onMove(const function<void ()>& function = {}) -> type&; + auto position() const -> unsigned; + auto setPosition(signed position) -> type&; + auto setSelected(Position selected) -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + function<void ()> onChange; + function<void ()> onMove; + unsigned position = 0; + Position selected; + string text; + } state; +}; + +struct mTabFrame : mWidget { + Declare(TabFrame) + using mObject::remove; + friend class mTabFrameItem; + + auto append(sTabFrameItem item) -> type&; + auto doChange() const -> void; + auto doClose(sTabFrameItem item) const -> void; + auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void; + auto edge() const -> Edge; + auto item(unsigned position) const -> sTabFrameItem; + auto items() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onClose(const function<void (sTabFrameItem)>& function = {}) -> type&; + auto onMove(const function<void (sTabFrameItem, sTabFrameItem)>& function = {}) -> type&; + auto remove(sTabFrameItem item) -> type&; + auto reset() -> type&; + auto selected() const -> sTabFrameItem; + auto setEdge(Edge edge = Edge::Top) -> type&; + auto setParent(mObject* object = nullptr, signed offset = -1) -> type& override; + +//private: + struct State { + Edge edge = Edge::Top; + vector<sTabFrameItem> items; + function<void ()> onChange; + function<void (sTabFrameItem)> onClose; + function<void (sTabFrameItem, sTabFrameItem)> onMove; + unsigned selected = 0; + } state; + + auto destruct() -> void override; +}; + +struct mTabFrameItem : mObject { + Declare(TabFrameItem) + + auto append(sLayout layout) -> type&; + auto closable() const -> bool; + auto icon() const -> image; + auto layout() const -> sLayout; + auto movable() const -> bool; + auto remove() -> type& override; + auto remove(sLayout layout) -> type&; + auto reset() -> type&; + auto selected() const -> bool; + auto setClosable(bool closable = true) -> type&; + auto setIcon(const image& icon = {}) -> type&; + auto setMovable(bool movable = true) -> type&; + auto setParent(mObject* object = nullptr, signed offset = -1) -> type& override; + auto setSelected() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool closable = false; + image icon; + sLayout layout; + bool movable = false; + string text; + } state; + + auto destruct() -> void override; +}; + +struct mTextEdit : mWidget { + Declare(TextEdit) + + auto backgroundColor() const -> Color; + auto cursorPosition() const -> unsigned; + auto doChange() const -> void; + auto doMove() const -> void; + auto editable() const -> bool; + auto foregroundColor() const -> Color; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onMove(const function<void ()>& function = {}) -> type&; + auto setBackgroundColor(Color color = {}) -> type&; + auto setCursorPosition(unsigned position) -> type&; + auto setEditable(bool editable = true) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + auto setText(const string& text = "") -> type&; + auto setWordWrap(bool wordWrap = true) -> type&; + auto text() const -> string; + auto wordWrap() const -> bool; + +//private: + struct State { + Color backgroundColor; + unsigned cursorPosition = 0; + bool editable = true; + Color foregroundColor; + function<void ()> onChange; + function<void ()> onMove; + string text; + bool wordWrap = true; + } state; +}; + +struct mTreeView : mWidget { + Declare(TreeView) + using mObject::remove; + + auto append(sTreeViewItem item) -> type&; + auto backgroundColor() const -> Color; + auto checkable() const -> bool; + auto collapse() -> type&; + auto doActivate() const -> void; + auto doChange() const -> void; + auto doContext() const -> void; + auto doToggle(sTreeViewItem item) const -> void; + auto expand() -> type&; + auto foregroundColor() const -> Color; + auto item(const string& path) const -> sTreeViewItem; + auto items() const -> unsigned; + auto onActivate(const function<void ()>& function = {}) -> type&; + auto onChange(const function<void ()>& function = {}) -> type&; + auto onContext(const function<void ()>& function = {}) -> type&; + auto onToggle(const function<void (sTreeViewItem)>& function = {}) -> type&; + auto remove(sTreeViewItem item) -> type&; + auto reset() -> type&; + auto selected() const -> sTreeViewItem; + auto setBackgroundColor(Color color = {}) -> type&; + auto setCheckable(bool checkable = true) -> type&; + auto setForegroundColor(Color color = {}) -> type&; + +//private: + struct State { + Color backgroundColor; + bool checkable = false; + Color foregroundColor; + vector<sTreeViewItem> items; + function<void ()> onActivate; + function<void ()> onChange; + function<void ()> onContext; + function<void (sTreeViewItem)> onToggle; + string selectedPath; + } state; + + auto destruct() -> void override; +}; + +struct mTreeViewItem : mObject { + Declare(TreeViewItem) + + auto append(sTreeViewItem item) -> type&; + auto checked() const -> bool; + auto icon() const -> image; + auto item(const string& path) const -> sTreeViewItem; + auto items() const -> unsigned; + auto path() const -> string; + auto remove() -> type& override; + auto remove(sTreeViewItem item) -> type&; + auto selected() const -> bool; + auto setChecked(bool checked = true) -> type&; + auto setFocused() -> type& override; + auto setIcon(const image& icon = {}) -> type&; + auto setSelected() -> type&; + auto setText(const string& text = "") -> type&; + auto text() const -> string; + +//private: + struct State { + bool checked = false; + image icon; + vector<sTreeViewItem> items; + string text; + } state; + + auto destruct() -> void override; +}; + +struct mVerticalScroller : mWidget { + Declare(VerticalScroller) + + auto doChange() const -> void; + auto length() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto position() const -> unsigned; + auto setLength(unsigned length = 101) -> type&; + auto setPosition(unsigned position = 0) -> type&; + +//private: + struct State { + unsigned length = 101; + function<void ()> onChange; + unsigned position = 0; + } state; +}; + +struct mVerticalSlider : mWidget { + Declare(VerticalSlider) + + auto doChange() const -> void; + auto length() const -> unsigned; + auto onChange(const function<void ()>& function = {}) -> type&; + auto position() const -> unsigned; + auto setLength(unsigned length = 101) -> type&; + auto setPosition(unsigned position = 0) -> type&; + +//private: + struct State { + unsigned length = 101; + function<void ()> onChange; + unsigned position = 0; + } state; +}; + +struct mViewport : mWidget { + Declare(Viewport) + + auto doDrop(lstring names) const -> void; + auto doMouseLeave() const -> void; + auto doMouseMove(Position position) const -> void; + auto doMousePress(Mouse::Button button) const -> void; + auto doMouseRelease(Mouse::Button button) const -> void; + auto droppable() const -> bool; + auto handle() const -> uintptr_t; + auto onDrop(const function<void (lstring)>& function = {}) -> type&; + auto onMouseLeave(const function<void ()>& function = {}) -> type&; + auto onMouseMove(const function<void (Position position)>& function = {}) -> type&; + auto onMousePress(const function<void (Mouse::Button)>& function = {}) -> type&; + auto onMouseRelease(const function<void (Mouse::Button)>& function = {}) -> type&; + auto setDroppable(bool droppable = true) -> type&; + +//private: + struct State { + bool droppable = false; + function<void (lstring)> onDrop; + function<void ()> onMouseLeave; + function<void (Position)> onMouseMove; + function<void (Mouse::Button)> onMousePress; + function<void (Mouse::Button)> onMouseRelease; + } state; +}; + +#undef Declare + +} diff --git a/hiro/core/desktop.cpp b/hiro/core/desktop.cpp new file mode 100644 index 00000000..f8981629 --- /dev/null +++ b/hiro/core/desktop.cpp @@ -0,0 +1,7 @@ +auto Desktop::size() -> Size { + return pDesktop::size(); +} + +auto Desktop::workspace() -> Geometry { + return pDesktop::workspace(); +} diff --git a/hiro/core/font.cpp b/hiro/core/font.cpp new file mode 100644 index 00000000..0ca2deaf --- /dev/null +++ b/hiro/core/font.cpp @@ -0,0 +1,15 @@ +auto Font::serif(unsigned size, const string& style) -> string { + return pFont::serif(size, style); +} + +auto Font::sans(unsigned size, const string& style) -> string { + return pFont::sans(size, style); +} + +auto Font::monospace(unsigned size, const string& style) -> string { + return pFont::monospace(size, style); +} + +auto Font::size(const string& font, const string& text) -> Size { + return pFont::size(font, text); +} diff --git a/hiro/core/geometry.cpp b/hiro/core/geometry.cpp new file mode 100644 index 00000000..21cd32f5 --- /dev/null +++ b/hiro/core/geometry.cpp @@ -0,0 +1,112 @@ +Geometry::Geometry() { + setGeometry(0, 0, 0, 0); +} + +Geometry::Geometry(Position position, Size size) { + setGeometry(position, size); +} + +Geometry::Geometry(signed x, signed y, signed width, signed height) { + setGeometry(x, y, width, height); +} + +Geometry::Geometry(const string& text) { + lstring part = text.split(",").strip(); + state.x = integer(part(0)); + state.y = integer(part(1)); + state.width = integer(part(2)); + state.height = integer(part(3)); +} + +auto Geometry::operator==(const Geometry& source) const -> bool { + return x() == source.x() && y() == source.y() && width() == source.width() && height() == source.height(); +} + +auto Geometry::operator!=(const Geometry& source) const -> bool { + return !operator==(source); +} + +auto Geometry::height() const -> signed { + return state.height; +} + +auto Geometry::position() const -> Position { + return {state.x, state.y}; +} + +auto Geometry::setHeight(signed height) -> type& { + state.height = height; + return *this; +} + +auto Geometry::setGeometry(Geometry geometry) -> type& { + return setGeometry(geometry.x(), geometry.y(), geometry.width(), geometry.height()); +} + +auto Geometry::setGeometry(Position position, Size size) -> type& { + setGeometry(position.x(), position.y(), size.width(), size.height()); + return *this; +} + +auto Geometry::setGeometry(signed x, signed y, signed width, signed height) -> type& { + state.x = x; + state.y = y; + state.width = width; + state.height = height; + return *this; +} + +auto Geometry::setPosition(Position position) -> type& { + return setPosition(position.x(), position.y()); +} + +auto Geometry::setPosition(signed x, signed y) -> type& { + state.x = x; + state.y = y; + return *this; +} + +auto Geometry::setSize(Size size) -> type& { + return setSize(size.width(), size.height()); +} + +auto Geometry::setSize(signed width, signed height) -> type& { + state.width = width; + state.height = height; + return *this; +} + +auto Geometry::setWidth(signed width) -> type& { + state.width = width; + return *this; +} + +auto Geometry::setX(signed x) -> type& { + state.x = x; + return *this; +} + +auto Geometry::setY(signed y) -> type& { + state.y = y; + return *this; +} + +auto Geometry::size() const -> Size { + return {state.width, state.height}; +} + +auto Geometry::text() const -> string { + return {state.x, ",", state.y, ",", state.width, ",", state.height}; +} + +auto Geometry::width() const -> signed { + return state.width; +} + +auto Geometry::x() const -> signed { + return state.x; +} + +auto Geometry::y() const -> signed { + return state.y; +} diff --git a/hiro/core/hotkey.cpp b/hiro/core/hotkey.cpp new file mode 100644 index 00000000..432fa659 --- /dev/null +++ b/hiro/core/hotkey.cpp @@ -0,0 +1,53 @@ +auto mHotkey::allocate() -> pObject* { + return new pHotkey(*this); +} + +// + +auto mHotkey::doPress() const -> void { + if(state.onPress) return state.onPress(); +} + +auto mHotkey::doRelease() const -> void { + if(state.onRelease) return state.onRelease(); +} + +auto mHotkey::onPress(const function<void ()>& function) -> type& { + state.onPress = function; + return *this; +} + +auto mHotkey::onRelease(const function<void ()>& function) -> type& { + state.onRelease = function; + return *this; +} + +auto mHotkey::parent() const -> wObject { + return state.parent; +} + +auto mHotkey::remove() -> type& { +//todo: remove from Keyboard::hotkeys + return *this; +} + +auto mHotkey::sequence() const -> string { + return state.sequence; +} + +auto mHotkey::setParent(sObject parent) -> type& { + state.parent = parent; + return *this; +} + +auto mHotkey::setSequence(const string& sequence) -> type& { + state.active = false; + state.sequence = sequence; + state.keys.reset(); + for(auto& key : sequence.split("+")) { + if(auto position = Keyboard::keys.find(key)) { + state.keys.append(*position); + } + } + return *this; +} diff --git a/hiro/core/keyboard.cpp b/hiro/core/keyboard.cpp new file mode 100644 index 00000000..4ab5d1ff --- /dev/null +++ b/hiro/core/keyboard.cpp @@ -0,0 +1,74 @@ +const vector<string> Keyboard::keys = { + //physical keyboard buttons + "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", + "PrintScreen", "ScrollLock", "Pause", + "Insert", "Delete", "Home", "End", "PageUp", "PageDown", + "Up", "Down", "Left", "Right", + "Grave", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Dash", "Equal", "Backspace", + "Tab", "CapsLock", "LeftEnter", "LeftShift", "RightShift", + "LeftControl", "RightControl", "LeftAlt", "RightAlt", "LeftSuper", "RightSuper", "Menu", "Space", + "OpenBracket", "CloseBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", + "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + "NumLock", "Divide", "Multiply", "Subtract", "Add", "RightEnter", "Point", + "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Zero", + + //group aliases + "Shift", //"LeftShift" | "RightShift" + "Control", //"LeftControl" | "RightControl" + "Alt", //"LeftAlt" | "RightAlt" + "Super", //"LeftSuper" | "RightSuper" + "Enter", //"LeftEnter" | "RightEnter" +}; + +auto Keyboard::append(sHotkey hotkey) -> void { + state.hotkeys.append(hotkey); +} + +auto Keyboard::hotkey(unsigned position) -> sHotkey { + if(position >= hotkeys()) throw; + return state.hotkeys[position]; +} + +auto Keyboard::hotkeys() -> unsigned { + return state.hotkeys.size(); +} + +auto Keyboard::poll() -> vector<bool> { + auto pressed = pKeyboard::poll(); + + for(auto& hotkey : state.hotkeys) { + bool active = hotkey->state.sequence.size() > 0; + for(auto& key : hotkey->state.keys) { + if(pressed[key]) continue; + active = false; + break; + } + if(auto parent = hotkey->state.parent.acquire()) { + //todo: set active = false if parent no longer exists + active &= parent->focused(); + } + if(hotkey->state.active != active) { + hotkey->state.active = active; + if( active) hotkey->doPress(); + if(!active) hotkey->doRelease(); + } + } + + return pressed; +} + +auto Keyboard::pressed(const string& key) -> bool { + if(auto code = keys.find(key)) return pKeyboard::pressed(*code); + return false; +} + +auto Keyboard::released(const string& key) -> bool { + return !pressed(key); +} + +auto Keyboard::remove(sHotkey hotkey) -> void { + if(auto offset = state.hotkeys.find(hotkey)) { + state.hotkeys.remove(*offset); + } +} diff --git a/hiro/core/layout.cpp b/hiro/core/layout.cpp new file mode 100644 index 00000000..73a66996 --- /dev/null +++ b/hiro/core/layout.cpp @@ -0,0 +1,58 @@ +auto mLayout::allocate() -> pObject* { + return new pLayout(*this); +} + +auto mLayout::destruct() -> void { + for(auto& sizable : state.sizables) sizable->destruct(); + mSizable::destruct(); +} + +// + +auto mLayout::append(shared_pointer<mSizable> sizable) -> type& { + state.sizables.append(sizable); + sizable->setParent(this, sizables() - 1); + setGeometry(geometry()); + return *this; +} + +auto mLayout::remove() -> type& { + if(auto tabFrameItem = parentTabFrameItem()) tabFrameItem->remove(tabFrameItem->layout()); + if(auto layout = parentLayout()) layout->remove(layout->sizable(offset())); + if(auto window = parentWindow()) window->remove(window->layout()); + setParent(); + for(auto& sizable : state.sizables) sizable->setParent(this, sizable->offset()); + return *this; +} + +auto mLayout::remove(shared_pointer<mSizable> sizable) -> type& { + auto offset = sizable->offset(); + sizable->setParent(); + state.sizables.remove(offset); + for(auto n : range(offset, sizables())) { + state.sizables[n]->offset(-1); + } + setGeometry(geometry()); + return *this; +} + +auto mLayout::reset() -> type& { + while(state.sizables) remove(state.sizables.last()); + return *this; +} + +auto mLayout::setParent(mObject* parent, signed offset) -> type& { + for(auto& sizable : state.sizables) sizable->destruct(); + mObject::setParent(parent, offset); + for(auto& sizable : state.sizables) sizable->setParent(this, sizable->offset()); + return *this; +} + +auto mLayout::sizable(unsigned position) const -> shared_pointer<mSizable> { + if(position >= sizables()) throw; + return state.sizables[position]; +} + +auto mLayout::sizables() const -> unsigned { + return state.sizables.size(); +} diff --git a/hiro/core/menu-bar.cpp b/hiro/core/menu-bar.cpp new file mode 100644 index 00000000..c8559ddc --- /dev/null +++ b/hiro/core/menu-bar.cpp @@ -0,0 +1,47 @@ +auto mMenuBar::allocate() -> pObject* { + return new pMenuBar(*this); +} + +auto mMenuBar::destruct() -> void { + for(auto& menu : state.menus) menu->destruct(); + mObject::destruct(); +} + +// + +auto mMenuBar::append(shared_pointer<mMenu> menu) -> type& { + state.menus.append(menu); + menu->setParent(this, menus() - 1); + signal(append, menu); + return *this; +} + +auto mMenuBar::menu(unsigned position) const -> shared_pointer<mMenu> { + if(position >= menus()) throw; + return state.menus[position]; +} + +auto mMenuBar::menus() const -> unsigned { + return state.menus.size(); +} + +auto mMenuBar::remove() -> type& { + if(auto window = parentWindow()) window->remove(window->menuBar()); + return *this; +} + +auto mMenuBar::remove(shared_pointer<mMenu> menu) -> type& { + signed offset = menu->offset(); + signal(remove, *menu); + state.menus.remove(offset); + for(auto n : range(offset, menus())) { + state.menus[n]->offset(-1); + } + menu->setParent(); + return *this; +} + +auto mMenuBar::reset() -> type& { + while(state.menus) remove(state.menus.last()); + return *this; +} diff --git a/hiro/core/message-window.cpp b/hiro/core/message-window.cpp new file mode 100644 index 00000000..287e336d --- /dev/null +++ b/hiro/core/message-window.cpp @@ -0,0 +1,38 @@ +MessageWindow::MessageWindow(const string& text) { + state.text = text; +} + +auto MessageWindow::error(Buttons buttons) -> Response { + state.buttons = buttons; + return pMessageWindow::error(state); +} + +auto MessageWindow::information(Buttons buttons) -> Response { + state.buttons = buttons; + return pMessageWindow::information(state); +} + +auto MessageWindow::question(Buttons buttons) -> Response { + state.buttons = buttons; + return pMessageWindow::question(state); +} + +auto MessageWindow::setParent(shared_pointer<mWindow> parent) -> type& { + state.parent = parent; + return *this; +} + +auto MessageWindow::setText(const string& text) -> type& { + state.text = text; + return *this; +} + +auto MessageWindow::setTitle(const string& title) -> type& { + state.title = title; + return *this; +} + +auto MessageWindow::warning(MessageWindow::Buttons buttons) -> Response { + state.buttons = buttons; + return pMessageWindow::warning(state); +} diff --git a/hiro/core/monitor.cpp b/hiro/core/monitor.cpp new file mode 100644 index 00000000..6ca1984a --- /dev/null +++ b/hiro/core/monitor.cpp @@ -0,0 +1,11 @@ +auto Monitor::count() -> unsigned { + return pMonitor::count(); +} + +auto Monitor::geometry(unsigned monitor) -> Geometry { + return pMonitor::geometry(monitor); +} + +auto Monitor::primary() -> unsigned { + return pMonitor::primary(); +} diff --git a/hiro/core/mouse.cpp b/hiro/core/mouse.cpp new file mode 100644 index 00000000..49fe1574 --- /dev/null +++ b/hiro/core/mouse.cpp @@ -0,0 +1,11 @@ +auto Mouse::position() -> Position { + return pMouse::position(); +} + +auto Mouse::pressed(Mouse::Button button) -> bool { + return pMouse::pressed(button); +} + +auto Mouse::released(Mouse::Button button) -> bool { + return !pressed(button); +} diff --git a/hiro/core/object.cpp b/hiro/core/object.cpp new file mode 100644 index 00000000..3b97fe28 --- /dev/null +++ b/hiro/core/object.cpp @@ -0,0 +1,233 @@ +mObject::mObject() { + Application::initialize(); +} + +mObject::~mObject() { +} + +auto mObject::allocate() -> pObject* { + return new pObject(*this); +} + +auto mObject::construct() -> void { + if(delegate) return; + delegate = allocate(); + signal(construct); +} + +auto mObject::destruct() -> void { + if(!delegate) return; + signal(destruct); + delete delegate; + delegate = nullptr; +} + +// + +//this is used to control dynamic allocation of pObject delegates +//an mObject is abstract only if it has no top-level object (eg a Button not attached to any Window) +//if the mObject is not abstract, the pObject delegate is allocated immediately +//otherwise, the pObject is not allocated until it is attached to a non-abstract parent +auto mObject::abstract() const -> bool { + if(dynamic_cast<const mWindow*>(this)) return false; + if(dynamic_cast<const mPopupMenu*>(this)) return false; + if(auto object = parent()) return object->abstract(); + return true; +} + +auto mObject::enabled(bool recursive) const -> bool { + if(!recursive || !state.enabled) return state.enabled; + if(auto object = parent()) return object->enabled(true); + return true; +} + +auto mObject::focused() const -> bool { + if(signal(focused)) return true; + return false; +} + +auto mObject::font(bool recursive) const -> string { + if(!recursive || state.font) return state.font; + if(auto object = parent()) return object->font(true); + return Application::font(); +} + +auto mObject::offset() const -> signed { + return state.offset; +} + +auto mObject::offset(signed displacement) -> type& { + state.offset += displacement; + return *this; +} + +auto mObject::parent() const -> mObject* { + return state.parent; +} + +auto mObject::parentComboButton(bool recursive) const -> mComboButton* { + if(auto comboButton = dynamic_cast<mComboButton*>(parent())) return comboButton; + if(recursive) { + if(auto object = parent()) return object->parentComboButton(true); + } + return nullptr; +} + +auto mObject::parentFrame(bool recursive) const -> mFrame* { + if(auto frame = dynamic_cast<mFrame*>(parent())) return frame; + if(recursive) { + if(auto object = parent()) return object->parentFrame(true); + } + return nullptr; +} + +auto mObject::parentIconView(bool recursive) const -> mIconView* { + if(auto iconView = dynamic_cast<mIconView*>(parent())) return iconView; + if(recursive) { + if(auto object = parent()) return object->parentIconView(true); + } + return nullptr; +} + +auto mObject::parentLayout(bool recursive) const -> mLayout* { + if(auto layout = dynamic_cast<mLayout*>(parent())) return layout; + if(recursive) { + if(auto object = parent()) return object->parentLayout(true); + } + return nullptr; +} + +auto mObject::parentListView(bool recursive) const -> mListView* { + if(auto listView = dynamic_cast<mListView*>(parent())) return listView; + if(recursive) { + if(auto object = parent()) return object->parentListView(true); + } + return nullptr; +} + +auto mObject::parentMenu(bool recursive) const -> mMenu* { + if(auto menu = dynamic_cast<mMenu*>(parent())) return menu; + if(recursive) { + if(auto object = parent()) return object->parentMenu(true); + } + return nullptr; +} + +auto mObject::parentMenuBar(bool recursive) const -> mMenuBar* { + if(auto menuBar = dynamic_cast<mMenuBar*>(parent())) return menuBar; + if(recursive) { + if(auto object = parent()) return object->parentMenuBar(true); + } + return nullptr; +} + +auto mObject::parentPopupMenu(bool recursive) const -> mPopupMenu* { + if(auto popupMenu = dynamic_cast<mPopupMenu*>(parent())) return popupMenu; + if(recursive) { + if(auto object = parent()) return object->parentPopupMenu(true); + } + return nullptr; +} + +auto mObject::parentSizable(bool recursive) const -> mSizable* { + if(auto sizable = dynamic_cast<mSizable*>(parent())) return sizable; + if(recursive) { + if(auto object = parent()) return object->parentSizable(true); + } + return nullptr; +} + +auto mObject::parentTabFrame(bool recursive) const -> mTabFrame* { + if(auto tabFrame = dynamic_cast<mTabFrame*>(parent())) return tabFrame; + if(recursive) { + if(auto object = parent()) return object->parentTabFrame(true); + } + return nullptr; +} + +auto mObject::parentTabFrameItem(bool recursive) const -> mTabFrameItem* { + if(auto tabFrameItem = dynamic_cast<mTabFrameItem*>(parent())) return tabFrameItem; + if(recursive) { + if(auto object = parent()) return object->parentTabFrameItem(true); + } + return nullptr; +} + +auto mObject::parentTreeView(bool recursive) const -> mTreeView* { + if(auto treeView = dynamic_cast<mTreeView*>(parent())) return treeView; + if(recursive) { + if(auto object = parent()) return object->parentTreeView(true); + } + return nullptr; +} + +auto mObject::parentTreeViewItem(bool recursive) const -> mTreeViewItem* { + if(auto treeViewItem = dynamic_cast<mTreeViewItem*>(parent())) return treeViewItem; + if(recursive) { + if(auto object = parent()) return object->parentTreeViewItem(true); + } + return nullptr; +} + +auto mObject::parentWidget(bool recursive) const -> mWidget* { + if(auto widget = dynamic_cast<mWidget*>(parent())) return widget; + if(recursive) { + if(auto object = parent()) return object->parentWidget(true); + } + return nullptr; +} + +auto mObject::parentWindow(bool recursive) const -> mWindow* { + if(auto window = dynamic_cast<mWindow*>(parent())) return window; + if(recursive) { + if(auto object = parent()) return object->parentWindow(true); + } + return nullptr; +} + +auto mObject::remove() -> type& { + signal(remove); + return *this; +} + +auto mObject::reset() -> type& { + signal(reset); + return *this; +} + +auto mObject::setEnabled(bool enabled) -> type& { + state.enabled = enabled; + signal(setEnabled, this->enabled(true)); + return *this; +} + +auto mObject::setFocused() -> type& { + signal(setFocused); + return *this; +} + +auto mObject::setFont(const string& font) -> type& { + state.font = font; + signal(setFont, this->font(true)); + return *this; +} + +auto mObject::setParent(mObject* parent, signed offset) -> type& { + destruct(); + state.parent = parent; + state.offset = offset; + if(!abstract()) construct(); + return *this; +} + +auto mObject::setVisible(bool visible) -> type& { + state.visible = visible; + signal(setVisible, this->visible(true)); + return *this; +} + +auto mObject::visible(bool recursive) const -> bool { + if(!recursive || !state.visible) return state.visible; + if(auto object = parent()) return object->visible(true); + return true; +} diff --git a/hiro/core/popup-menu.cpp b/hiro/core/popup-menu.cpp new file mode 100644 index 00000000..6e74fd7f --- /dev/null +++ b/hiro/core/popup-menu.cpp @@ -0,0 +1,47 @@ +auto mPopupMenu::allocate() -> pObject* { + return new pPopupMenu(*this); +} + +auto mPopupMenu::destruct() -> void { + for(auto& action : state.actions) action->destruct(); + mObject::destruct(); +} + +// + +auto mPopupMenu::action(unsigned position) const -> sAction { + if(position >= actions()) throw; + return state.actions[position]; +} + +auto mPopupMenu::actions() const -> unsigned { + return state.actions.size(); +} + +auto mPopupMenu::append(sAction action) -> type& { + state.actions.append(action); + action->setParent(this, actions() - 1); + signal(append, action); + return *this; +} + +auto mPopupMenu::remove(sAction action) -> type& { + signed offset = action->offset(); + signal(remove, action); + state.actions.remove(offset); + for(auto n : range(offset, actions())) { + state.actions[n]->offset(-1); + } + action->setParent(); + return *this; +} + +auto mPopupMenu::reset() -> type& { + while(state.actions) remove(state.actions.last()); + return *this; +} + +auto mPopupMenu::setVisible(bool visible) -> type& { + signal(setVisible, visible); + return *this; +} diff --git a/hiro/core/position.cpp b/hiro/core/position.cpp new file mode 100644 index 00000000..f878fc01 --- /dev/null +++ b/hiro/core/position.cpp @@ -0,0 +1,43 @@ +Position::Position() { + setPosition(0, 0); +} + +Position::Position(signed x, signed y) { + setPosition(x, y); +} + +auto Position::operator==(const Position& source) const -> bool { + return x() == source.x() && y() == source.y(); +} + +auto Position::operator!=(const Position& source) const -> bool { + return !operator==(source); +} + +auto Position::setPosition(Position position) -> type& { + return setPosition(position.x(), position.y()); +} + +auto Position::setPosition(signed x, signed y) -> type& { + state.x = x; + state.y = y; + return *this; +} + +auto Position::setX(signed x) -> type& { + state.x = x; + return *this; +} + +auto Position::setY(signed y) -> type& { + state.y = y; + return *this; +} + +auto Position::x() const -> signed { + return state.x; +} + +auto Position::y() const -> signed { + return state.y; +} diff --git a/hiro/core/sizable.cpp b/hiro/core/sizable.cpp new file mode 100644 index 00000000..210226fd --- /dev/null +++ b/hiro/core/sizable.cpp @@ -0,0 +1,17 @@ +auto mSizable::allocate() -> pObject* { + return new pSizable(*this); +} + +auto mSizable::geometry() const -> Geometry { + return state.geometry; +} + +auto mSizable::minimumSize() const -> Size { + return signal(minimumSize); +} + +auto mSizable::setGeometry(Geometry geometry) -> type& { + state.geometry = geometry; + signal(setGeometry, geometry); + return *this; +} diff --git a/hiro/core/size.cpp b/hiro/core/size.cpp new file mode 100644 index 00000000..950189b4 --- /dev/null +++ b/hiro/core/size.cpp @@ -0,0 +1,43 @@ +Size::Size() { + setSize(0, 0); +} + +Size::Size(signed width, signed height) { + setSize(width, height); +} + +auto Size::operator==(const Size& source) const -> bool { + return width() == source.width() && height() == source.height(); +} + +auto Size::operator!=(const Size& source) const -> bool { + return !operator==(source); +} + +auto Size::height() const -> signed { + return state.height; +} + +auto Size::setHeight(signed height) -> type& { + state.height = height; + return *this; +} + +auto Size::setSize(Size size) -> type& { + return setSize(size.width(), size.height()); +} + +auto Size::setSize(signed width, signed height) -> type& { + state.width = width; + state.height = height; + return *this; +} + +auto Size::setWidth(signed width) -> type& { + state.width = width; + return *this; +} + +auto Size::width() const -> signed { + return state.width; +} diff --git a/hiro/core/status-bar.cpp b/hiro/core/status-bar.cpp new file mode 100644 index 00000000..2f5cf46b --- /dev/null +++ b/hiro/core/status-bar.cpp @@ -0,0 +1,20 @@ +auto mStatusBar::allocate() -> pObject* { + return new pStatusBar(*this); +} + +// + +auto mStatusBar::remove() -> type& { + if(auto window = parentWindow()) window->remove(window->statusBar()); + return *this; +} + +auto mStatusBar::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mStatusBar::text() const -> string { + return state.text; +} diff --git a/hiro/core/timer.cpp b/hiro/core/timer.cpp new file mode 100644 index 00000000..e8488c5e --- /dev/null +++ b/hiro/core/timer.cpp @@ -0,0 +1,24 @@ +auto mTimer::allocate() -> pObject* { + return new pTimer(*this); +} + +// + +auto mTimer::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mTimer::interval() const -> unsigned { + return state.interval; +} + +auto mTimer::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mTimer::setInterval(unsigned interval) -> type& { + state.interval = interval; + signal(setInterval, interval); + return *this; +} diff --git a/hiro/core/widget/button.cpp b/hiro/core/widget/button.cpp new file mode 100644 index 00000000..6382bf0f --- /dev/null +++ b/hiro/core/widget/button.cpp @@ -0,0 +1,54 @@ +auto mButton::allocate() -> pObject* { + return new pButton(*this); +} + +// + +auto mButton::bordered() const -> bool { + return state.bordered; +} + +auto mButton::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mButton::icon() const -> image { + return state.icon; +} + +auto mButton::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mButton::orientation() const -> Orientation { + return state.orientation; +} + +auto mButton::setBordered(bool bordered) -> type& { + state.bordered = bordered; + signal(setBordered, bordered); + return *this; +} + +auto mButton::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mButton::setOrientation(Orientation orientation) -> type& { + state.orientation = orientation; + signal(setOrientation, orientation); + return *this; +} + +auto mButton::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mButton::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/canvas.cpp b/hiro/core/widget/canvas.cpp new file mode 100644 index 00000000..4499e0e1 --- /dev/null +++ b/hiro/core/widget/canvas.cpp @@ -0,0 +1,125 @@ +auto mCanvas::allocate() -> pObject* { + return new pCanvas(*this); +} + +// + +auto mCanvas::color() const -> Color { + return state.color; +} + +auto mCanvas::data() -> uint32_t* { + return state.data.data(); +} + +auto mCanvas::droppable() const -> bool { + return state.droppable; +} + +auto mCanvas::doDrop(lstring names) const -> void { + if(state.onDrop) return state.onDrop(names); +} + +auto mCanvas::doMouseLeave() const -> void { + if(state.onMouseLeave) return state.onMouseLeave(); +} + +auto mCanvas::doMouseMove(Position position) const -> void { + if(state.onMouseMove) return state.onMouseMove(position); +} + +auto mCanvas::doMousePress(Mouse::Button button) const -> void { + if(state.onMousePress) return state.onMousePress(button); +} + +auto mCanvas::doMouseRelease(Mouse::Button button) const -> void { + if(state.onMouseRelease) return state.onMouseRelease(button); +} + +auto mCanvas::gradient() const -> vector<Color> { + return state.gradient; +} + +auto mCanvas::icon() const -> image { + return state.icon; +} + +auto mCanvas::onDrop(const function<void (lstring)>& function) -> type& { + state.onDrop = function; + return *this; +} + +auto mCanvas::onMouseLeave(const function<void ()>& function) -> type& { + state.onMouseLeave = function; + return *this; +} + +auto mCanvas::onMouseMove(const function<void (Position)>& function) -> type& { + state.onMouseMove = function; + return *this; +} + +auto mCanvas::onMousePress(const function<void (Mouse::Button)>& function) -> type& { + state.onMousePress = function; + return *this; +} + +auto mCanvas::onMouseRelease(const function<void (Mouse::Button)>& function) -> type& { + state.onMouseRelease = function; + return *this; +} + +auto mCanvas::setColor(Color color) -> type& { + state.size = {}; + state.color = color; + signal(setColor, color); + return *this; +} + +auto mCanvas::setData(Size size) -> type& { + state.size = size; + state.data.resize(size.width() * size.height()); + memory::fill(state.data.data(), size.width() * size.height() * sizeof(uint32_t)); + signal(setData, size); + return *this; +} + +auto mCanvas::setDroppable(bool droppable) -> type& { + state.droppable = droppable; + signal(setDroppable, droppable); + return *this; +} + +auto mCanvas::setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> type& { + state.size = {}; + state.gradient[0] = topLeft; + state.gradient[1] = topRight; + state.gradient[2] = bottomLeft; + state.gradient[3] = bottomRight; + signal(setGradient, topLeft, topRight, bottomLeft, bottomRight); + return *this; +} + +auto mCanvas::setHorizontalGradient(Color left, Color right) -> type& { + return setGradient(left, right, left, right); +} + +auto mCanvas::setIcon(const image& icon) -> type& { + state.size = {(signed)icon.width, (signed)icon.height}; + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mCanvas::setVerticalGradient(Color top, Color bottom) -> type& { + return setGradient(top, top, bottom, bottom); +} + +auto mCanvas::size() const -> Size { + return state.size; +} + +auto mCanvas::update() -> type& { + signal(update); + return *this; +} diff --git a/hiro/core/widget/check-button.cpp b/hiro/core/widget/check-button.cpp new file mode 100644 index 00000000..16411d80 --- /dev/null +++ b/hiro/core/widget/check-button.cpp @@ -0,0 +1,64 @@ +auto mCheckButton::allocate() -> pObject* { + return new pCheckButton(*this); +} + +// + +auto mCheckButton::bordered() const -> bool { + return state.bordered; +} + +auto mCheckButton::checked() const -> bool { + return state.checked; +} + +auto mCheckButton::doToggle() const -> void { + if(state.onToggle) return state.onToggle(); +} + +auto mCheckButton::icon() const -> image { + return state.icon; +} + +auto mCheckButton::onToggle(const function<void ()>& function) -> type& { + state.onToggle = function; + return *this; +} + +auto mCheckButton::orientation() const -> Orientation { + return state.orientation; +} + +auto mCheckButton::setBordered(bool bordered) -> type& { + state.bordered = bordered; + signal(setBordered, bordered); + return *this; +} + +auto mCheckButton::setChecked(bool checked) -> type& { + state.checked = checked; + signal(setChecked, checked); + return *this; +} + +auto mCheckButton::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mCheckButton::setOrientation(Orientation orientation) -> type& { + state.orientation = orientation; + signal(setOrientation, orientation); + return *this; +} + +auto mCheckButton::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mCheckButton::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/check-label.cpp b/hiro/core/widget/check-label.cpp new file mode 100644 index 00000000..7f072545 --- /dev/null +++ b/hiro/core/widget/check-label.cpp @@ -0,0 +1,34 @@ +auto mCheckLabel::allocate() -> pObject* { + return new pCheckLabel(*this); +} + +// + +auto mCheckLabel::checked() const -> bool { + return state.checked; +} + +auto mCheckLabel::doToggle() const -> void { + if(state.onToggle) return state.onToggle(); +} + +auto mCheckLabel::onToggle(const function<void ()>& function) -> type& { + state.onToggle = function; + return *this; +} + +auto mCheckLabel::setChecked(bool checked) -> type& { + state.checked = checked; + signal(setChecked, checked); + return *this; +} + +auto mCheckLabel::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mCheckLabel::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/combo-button-item.cpp b/hiro/core/widget/combo-button-item.cpp new file mode 100644 index 00000000..e2b7422b --- /dev/null +++ b/hiro/core/widget/combo-button-item.cpp @@ -0,0 +1,43 @@ +auto mComboButtonItem::allocate() -> pObject* { + return new pComboButtonItem(*this); +} + +// + +auto mComboButtonItem::icon() const -> image { + return state.icon; +} + +auto mComboButtonItem::remove() -> type& { + if(auto comboButton = parentComboButton()) comboButton->remove(*this); + return *this; +} + +auto mComboButtonItem::selected() const -> bool { + if(auto comboButton = parentComboButton()) return comboButton->state.selected == offset(); + return false; +} + +auto mComboButtonItem::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mComboButtonItem::setSelected() -> type& { + if(auto parent = parentComboButton()) { + parent->state.selected = offset(); + signal(setSelected); + } + return *this; +} + +auto mComboButtonItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mComboButtonItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/combo-button.cpp b/hiro/core/widget/combo-button.cpp new file mode 100644 index 00000000..daf3f68a --- /dev/null +++ b/hiro/core/widget/combo-button.cpp @@ -0,0 +1,61 @@ +auto mComboButton::allocate() -> pObject* { + return new pComboButton(*this); +} + +auto mComboButton::destruct() -> void { + for(auto& item : state.items) item->destruct(); + mWidget::destruct(); +} + +// + +auto mComboButton::append(sComboButtonItem item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + if(state.selected < 0) item->setSelected(); + return *this; +} + +auto mComboButton::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mComboButton::item(unsigned position) const -> sComboButtonItem { + if(position < items()) return state.items[position]; + return {}; +} + +auto mComboButton::items() const -> unsigned { + return state.items.size(); +} + +auto mComboButton::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mComboButton::remove(sComboButtonItem item) -> type& { + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(item->offset(), items())) { + state.items[n]->offset(-1); + } + item->setParent(); + return *this; +} + +auto mComboButton::reset() -> type& { + signal(reset); + for(auto& item : state.items) { + item->setParent(); + } + state.items.reset(); + state.selected = -1; + return *this; +} + +auto mComboButton::selected() const -> sComboButtonItem { + if(state.selected >= 0) return state.items[state.selected]; + return {}; +} diff --git a/hiro/core/widget/console.cpp b/hiro/core/widget/console.cpp new file mode 100644 index 00000000..2db0408c --- /dev/null +++ b/hiro/core/widget/console.cpp @@ -0,0 +1,54 @@ +auto mConsole::allocate() -> pObject* { + return new pConsole(*this); +} + +// + +auto mConsole::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mConsole::doActivate(string command) const -> void { + if(state.onActivate) return state.onActivate(command); +} + +auto mConsole::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mConsole::onActivate(const function<void (string)>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mConsole::print(const string& text) -> type& { + signal(print, text); + return *this; +} + +auto mConsole::prompt() const -> string { + return state.prompt; +} + +auto mConsole::reset() -> type& { + signal(reset); + return *this; +} + +auto mConsole::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mConsole::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mConsole::setPrompt(const string& prompt) -> type& { + state.prompt = prompt; + signal(setPrompt, prompt); + return *this; +} diff --git a/hiro/core/widget/frame.cpp b/hiro/core/widget/frame.cpp new file mode 100644 index 00000000..b6abe85c --- /dev/null +++ b/hiro/core/widget/frame.cpp @@ -0,0 +1,42 @@ +auto mFrame::allocate() -> pObject* { + return new pFrame(*this); +} + +auto mFrame::destruct() -> void { + if(auto& layout = state.layout) layout->destruct(); + mWidget::destruct(); +} + +// + +auto mFrame::append(shared_pointer<mLayout> layout) -> type& { + if(auto& layout = state.layout) remove(layout); + state.layout = layout; + layout->setParent(this, 0); + return *this; +} + +auto mFrame::layout() const -> shared_pointer<mLayout> { + return state.layout; +} + +auto mFrame::remove(shared_pointer<mLayout> layout) -> type& { + layout->setParent(); + state.layout.reset(); + return *this; +} + +auto mFrame::reset() -> type& { + if(auto& layout = state.layout) remove(layout); + return *this; +} + +auto mFrame::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mFrame::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/hex-edit.cpp b/hiro/core/widget/hex-edit.cpp new file mode 100644 index 00000000..3a9d5a10 --- /dev/null +++ b/hiro/core/widget/hex-edit.cpp @@ -0,0 +1,89 @@ +auto mHexEdit::allocate() -> pObject* { + return new pHexEdit(*this); +} + +// + +auto mHexEdit::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mHexEdit::columns() const -> unsigned { + return state.columns; +} + +auto mHexEdit::doRead(unsigned offset) const -> uint8_t { + if(state.onRead) return state.onRead(offset); + return 0x00; +} + +auto mHexEdit::doWrite(unsigned offset, uint8_t data) const -> void { + if(state.onWrite) return state.onWrite(offset, data); +} + +auto mHexEdit::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mHexEdit::length() const -> unsigned { + return state.length; +} + +auto mHexEdit::offset() const -> unsigned { + return state.offset; +} + +auto mHexEdit::onRead(const function<uint8_t (unsigned)>& function) -> type& { + state.onRead = function; + return *this; +} + +auto mHexEdit::onWrite(const function<void (unsigned, uint8_t)>& function) -> type& { + state.onWrite = function; + return *this; +} + +auto mHexEdit::rows() const -> unsigned { + return state.rows; +} + +auto mHexEdit::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mHexEdit::setColumns(unsigned columns) -> type& { + state.columns = columns; + signal(setColumns, columns); + return *this; +} + +auto mHexEdit::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mHexEdit::setLength(unsigned length) -> type& { + state.length = length; + signal(setLength, length); + return *this; +} + +auto mHexEdit::setOffset(unsigned offset) -> type& { + state.offset = offset; + signal(setOffset, offset); + return *this; +} + +auto mHexEdit::setRows(unsigned rows) -> type& { + state.rows = rows; + signal(setRows, rows); + return *this; +} + +auto mHexEdit::update() -> type& { + signal(update); + return *this; +} diff --git a/hiro/core/widget/horizontal-scroller.cpp b/hiro/core/widget/horizontal-scroller.cpp new file mode 100644 index 00000000..6af6856e --- /dev/null +++ b/hiro/core/widget/horizontal-scroller.cpp @@ -0,0 +1,34 @@ +auto mHorizontalScroller::allocate() -> pObject* { + return new pHorizontalScroller(*this); +} + +// + +auto mHorizontalScroller::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mHorizontalScroller::length() const -> unsigned { + return state.length; +} + +auto mHorizontalScroller::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mHorizontalScroller::position() const -> unsigned { + return state.position; +} + +auto mHorizontalScroller::setLength(unsigned length) -> type& { + state.length = length; + signal(setLength, length); + return *this; +} + +auto mHorizontalScroller::setPosition(unsigned position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} diff --git a/hiro/core/widget/horizontal-slider.cpp b/hiro/core/widget/horizontal-slider.cpp new file mode 100644 index 00000000..f9a9c04d --- /dev/null +++ b/hiro/core/widget/horizontal-slider.cpp @@ -0,0 +1,34 @@ +auto mHorizontalSlider::allocate() -> pObject* { + return new pHorizontalSlider(*this); +} + +// + +auto mHorizontalSlider::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mHorizontalSlider::length() const -> unsigned { + return state.length; +} + +auto mHorizontalSlider::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mHorizontalSlider::position() const -> unsigned { + return state.position; +} + +auto mHorizontalSlider::setLength(unsigned length) -> type& { + state.length = length; + signal(setLength, length); + return *this; +} + +auto mHorizontalSlider::setPosition(unsigned position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} diff --git a/hiro/core/widget/icon-view-item.cpp b/hiro/core/widget/icon-view-item.cpp new file mode 100644 index 00000000..db6dac33 --- /dev/null +++ b/hiro/core/widget/icon-view-item.cpp @@ -0,0 +1,40 @@ +auto mIconViewItem::allocate() -> pObject* { + return new pIconViewItem(*this); +} + +// + +auto mIconViewItem::icon() const -> image { + return state.icon; +} + +auto mIconViewItem::remove() -> type& { + if(auto iconView = parentIconView()) iconView->remove(*this); + return *this; +} + +auto mIconViewItem::selected() const -> bool { + return state.selected; +} + +auto mIconViewItem::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mIconViewItem::setSelected(bool selected) -> type& { + state.selected = selected; + signal(setSelected, selected); + return *this; +} + +auto mIconViewItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mIconViewItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/icon-view.cpp b/hiro/core/widget/icon-view.cpp new file mode 100644 index 00000000..283e1cc9 --- /dev/null +++ b/hiro/core/widget/icon-view.cpp @@ -0,0 +1,148 @@ +auto mIconView::allocate() -> pObject* { + return new pIconView(*this); +} + +auto mIconView::destruct() -> void { + for(auto& item : state.items) item->destruct(); + mWidget::destruct(); +} + +// + +auto mIconView::append(shared_pointer<mIconViewItem> item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + return *this; +} + +auto mIconView::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mIconView::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mIconView::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mIconView::doContext() const -> void { + if(state.onContext) return state.onContext(); +} + +auto mIconView::flow() const -> Orientation { + return state.flow; +} + +auto mIconView::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mIconView::item(unsigned position) const -> shared_pointer<mIconViewItem> { + if(position >= items()) throw; + return state.items[position]; +} + +auto mIconView::items() const -> unsigned { + return state.items.size(); +} + +auto mIconView::multiSelect() const -> bool { + return state.multiSelect; +} + +auto mIconView::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mIconView::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mIconView::onContext(const function<void ()>& function) -> type& { + state.onContext = function; + return *this; +} + +auto mIconView::orientation() const -> Orientation { + return state.orientation; +} + +auto mIconView::remove(shared_pointer<mIconViewItem> item) -> type& { + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(item->offset(), items())) { + state.items[n]->offset(-1); + } + item->setParent(); + return *this; +} + +auto mIconView::reset() -> type& { + signal(reset); + for(auto& item : state.items) item->setParent(); + state.items.reset(); + return *this; +} + +auto mIconView::selected() const -> maybe<unsigned> { + for(auto& item : state.items) { + if(item->selected()) return (unsigned)item->offset(); + } + return nothing; +} + +auto mIconView::selectedItems() const -> vector<unsigned> { + vector<unsigned> result; + for(auto& item : state.items) { + if(item->selected()) result.append(item->offset()); + } + return result; +} + +auto mIconView::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mIconView::setFlow(Orientation flow) -> type& { + state.flow = flow; + signal(setFlow, flow); + return *this; +} + +auto mIconView::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mIconView::setMultiSelect(bool multiSelect) -> type& { + state.multiSelect = multiSelect; + signal(setMultiSelect, multiSelect); + return *this; +} + +auto mIconView::setOrientation(Orientation orientation) -> type& { + state.orientation = orientation; + signal(setOrientation, orientation); + return *this; +} + +auto mIconView::setSelected(const vector<signed>& selections) -> type& { + bool selectAll = selections(0, 0) == ~0; + for(auto& item : state.items) item->state.selected = selectAll; + if(selectAll) return signal(setItemSelectedAll), *this; + if(!selections) return signal(setItemSelectedNone), *this; + for(auto& position : selections) { + if(position >= items()) continue; + state.items[position]->state.selected = true; + } + signal(setItemSelected, selections); + return *this; +} diff --git a/hiro/core/widget/label.cpp b/hiro/core/widget/label.cpp new file mode 100644 index 00000000..d0e2df91 --- /dev/null +++ b/hiro/core/widget/label.cpp @@ -0,0 +1,37 @@ +auto mLabel::allocate() -> pObject* { + return new pLabel(*this); +} + +// + +auto mLabel::horizontalAlignment() const -> double { + return state.horizontalAlignment; +} + +auto mLabel::setHorizontalAlignment(double alignment) -> type& { + alignment = max(0.0, min(1.0, alignment)); + state.horizontalAlignment = alignment; + signal(setHorizontalAlignment, alignment); + return *this; +} + +auto mLabel::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mLabel::setVerticalAlignment(double alignment) -> type& { + alignment = max(0.0, min(1.0, alignment)); + state.verticalAlignment = alignment; + signal(setVerticalAlignment, alignment); + return *this; +} + +auto mLabel::text() const -> string { + return state.text; +} + +auto mLabel::verticalAlignment() const -> double { + return state.verticalAlignment; +} diff --git a/hiro/core/widget/line-edit.cpp b/hiro/core/widget/line-edit.cpp new file mode 100644 index 00000000..96672fe5 --- /dev/null +++ b/hiro/core/widget/line-edit.cpp @@ -0,0 +1,63 @@ +auto mLineEdit::allocate() -> pObject* { + return new pLineEdit(*this); +} + +// + +auto mLineEdit::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mLineEdit::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mLineEdit::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mLineEdit::editable() const -> bool { + return state.editable; +} + +auto mLineEdit::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mLineEdit::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mLineEdit::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mLineEdit::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mLineEdit::setEditable(bool editable) -> type& { + state.editable = editable; + signal(setEditable, editable); + return *this; +} + +auto mLineEdit::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mLineEdit::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mLineEdit::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/list-view-column.cpp b/hiro/core/widget/list-view-column.cpp new file mode 100644 index 00000000..cb180748 --- /dev/null +++ b/hiro/core/widget/list-view-column.cpp @@ -0,0 +1,135 @@ +auto mListViewColumn::allocate() -> pObject* { + return new pListViewColumn(*this); +} + +// + +auto mListViewColumn::active() const -> bool { + if(auto listView = parentListView()) return listView->state.activeColumn == offset(); + return false; +} + +auto mListViewColumn::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mListViewColumn::editable() const -> bool { + return state.editable; +} + +auto mListViewColumn::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mListViewColumn::horizontalAlignment() const -> double { + return state.horizontalAlignment; +} + +auto mListViewColumn::icon() const -> image { + return state.icon; +} + +auto mListViewColumn::remove() -> type& { + if(auto listView = parentListView()) listView->remove(*this); + return *this; +} + +auto mListViewColumn::resizable() const -> bool { + return state.resizable; +} + +auto mListViewColumn::setActive() -> type& { + if(auto listView = parentListView()) listView->state.activeColumn = offset(); + signal(setActive); + return *this; +} + +auto mListViewColumn::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mListViewColumn::setEditable(bool editable) -> type& { + state.editable = editable; + signal(setEditable, editable); + return *this; +} + +auto mListViewColumn::setFont(const string& font) -> type& { + state.font = font; + signal(setFont, this->font(true)); + return *this; +} + +auto mListViewColumn::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mListViewColumn::setHorizontalAlignment(double alignment) -> type& { + alignment = max(0.0, min(1.0, alignment)); + state.horizontalAlignment = alignment; + signal(setHorizontalAlignment, alignment); + return *this; +} + +auto mListViewColumn::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mListViewColumn::setResizable(bool resizable) -> type& { + state.resizable = resizable; + signal(setResizable, resizable); + return *this; +} + +auto mListViewColumn::setSortable(bool sortable) -> type& { + state.sortable = sortable; + signal(setSortable, sortable); + return *this; +} + +auto mListViewColumn::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mListViewColumn::setVerticalAlignment(double alignment) -> type& { + alignment = max(0.0, min(1.0, alignment)); + state.verticalAlignment = alignment; + signal(setVerticalAlignment, alignment); + return *this; +} + +auto mListViewColumn::setVisible(bool visible) -> type& { + state.visible = visible; + signal(setVisible, visible); + return *this; +} + +auto mListViewColumn::setWidth(signed width) -> type& { + state.width = width; + signal(setWidth, width); + return *this; +} + +auto mListViewColumn::sortable() const -> bool { + return state.sortable; +} + +auto mListViewColumn::text() const -> string { + return state.text; +} + +auto mListViewColumn::verticalAlignment() const -> double { + return state.verticalAlignment; +} + +auto mListViewColumn::width() const -> signed { + return state.width; +} diff --git a/hiro/core/widget/list-view-item.cpp b/hiro/core/widget/list-view-item.cpp new file mode 100644 index 00000000..bdc5ad88 --- /dev/null +++ b/hiro/core/widget/list-view-item.cpp @@ -0,0 +1,65 @@ +auto mListViewItem::allocate() -> pObject* { + return new pListViewItem(*this); +} + +// + +auto mListViewItem::checked() const -> bool { + return state.checked; +} + +auto mListViewItem::icon(unsigned column) const -> image { + return state.icon(column, {}); +} + +auto mListViewItem::remove() -> type& { + if(auto listView = parentListView()) listView->remove(*this); + return *this; +} + +auto mListViewItem::selected() const -> bool { + return state.selected; +} + +auto mListViewItem::setChecked(bool checked) -> type& { + state.checked = checked; + signal(setChecked, checked); + return *this; +} + +auto mListViewItem::setFocused() -> type& { + signal(setFocused); + return *this; +} + +auto mListViewItem::setIcon(unsigned column, const image& icon) -> type& { + state.icon(column) = icon; + signal(setIcon, column, icon); + return *this; +} + +auto mListViewItem::setSelected(bool selected) -> type& { + state.selected = selected; + signal(setSelected, selected); + return *this; +} + +auto mListViewItem::setText(const lstring& text) -> type& { + state.text = text; + if(auto listView = parentListView()) { + for(auto column : range(listView->columns())) { + setText(column, text(column, "")); + } + } + return *this; +} + +auto mListViewItem::setText(unsigned column, const string& text) -> type& { + state.text(column) = text; + signal(setText, column, text); + return *this; +} + +auto mListViewItem::text(unsigned column) const -> string { + return state.text(column, ""); +} diff --git a/hiro/core/widget/list-view.cpp b/hiro/core/widget/list-view.cpp new file mode 100644 index 00000000..7c9e915d --- /dev/null +++ b/hiro/core/widget/list-view.cpp @@ -0,0 +1,228 @@ +auto mListView::allocate() -> pObject* { + return new pListView(*this); +} + +auto mListView::destruct() -> void { + for(auto& item : state.items) item->destruct(); + for(auto& column : state.columns) column->destruct(); + mWidget::destruct(); +} + +// + +auto mListView::append(sListViewColumn column) -> type& { + state.columns.append(column); + column->setParent(this, columns() - 1); + signal(append, column); + return *this; +} + +auto mListView::append(sListViewItem item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + return *this; +} + +auto mListView::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mListView::checkable() const -> bool { + return state.checkable; +} + +auto mListView::checked() const -> vector<sListViewItem> { + vector<sListViewItem> items; + for(auto& item : state.items) { + if(item->checked()) items.append(item); + } + return items; +} + +auto mListView::column(unsigned position) const -> sListViewColumn { + if(position < columns()) return state.columns[position]; + return {}; +} + +auto mListView::columns() const -> unsigned { + return state.columns.size(); +} + +auto mListView::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mListView::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mListView::doContext() const -> void { + if(state.onContext) return state.onContext(); +} + +auto mListView::doEdit(sListViewItem item, sListViewColumn column) const -> void { + if(state.onEdit) return state.onEdit(item, column); +} + +auto mListView::doSort(sListViewColumn column) const -> void { + if(state.onSort) return state.onSort(column); +} + +auto mListView::doToggle(sListViewItem item) const -> void { + if(state.onToggle) return state.onToggle(item); +} + +auto mListView::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mListView::gridVisible() const -> bool { + return state.gridVisible; +} + +auto mListView::headerVisible() const -> bool { + return state.headerVisible; +} + +auto mListView::item(unsigned position) const -> sListViewItem { + if(position < items()) return state.items[position]; + return {}; +} + +auto mListView::items() const -> unsigned { + return state.items.size(); +} + +auto mListView::multiSelect() const -> bool { + return state.multiSelect; +} + +auto mListView::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mListView::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mListView::onContext(const function<void ()>& function) -> type& { + state.onContext = function; + return *this; +} + +auto mListView::onEdit(const function<void (sListViewItem, sListViewColumn)>& function) -> type& { + state.onEdit = function; + return *this; +} + +auto mListView::onSort(const function<void (sListViewColumn)>& function) -> type& { + state.onSort = function; + return *this; +} + +auto mListView::onToggle(const function<void (sListViewItem)>& function) -> type& { + state.onToggle = function; + return *this; +} + +auto mListView::remove(sListViewColumn column) -> type& { + signal(remove, column); + for(auto& item : state.items) item->setParent(); + state.items.reset(); + state.columns.remove(column->offset()); + for(auto n : range(column->offset(), columns())) { + state.columns[n]->offset(-1); + } + column->setParent(); + return *this; +} + +auto mListView::remove(sListViewItem item) -> type& { + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(item->offset(), items())) { + state.items[n]->offset(-1); + } + item->setParent(); + return *this; +} + +auto mListView::reset() -> type& { + signal(reset); + for(auto& column : state.columns) column->setParent(); + state.columns.reset(); + for(auto& item : state.items) item->setParent(); + state.items.reset(); + return *this; +} + +auto mListView::resizeColumns() -> type& { + signal(resizeColumns); + return *this; +} + +auto mListView::selected() const -> sListViewItem { + for(auto& item : state.items) { + if(item->selected()) return item; + } + return {}; +} + +auto mListView::selectedItems() const -> vector<sListViewItem> { + vector<sListViewItem> items; + for(auto& item : state.items) { + if(item->selected()) items.append(item); + } + return items; +} + +auto mListView::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mListView::setCheckable(bool checkable) -> type& { + state.checkable = checkable; + signal(setCheckable, checkable); + return *this; +} + +auto mListView::setChecked(bool checked) -> type& { + for(auto& item : state.items) item->state.checked = checked; + signal(setChecked, checked); + return *this; +} + +auto mListView::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mListView::setGridVisible(bool visible) -> type& { + state.gridVisible = visible; + signal(setGridVisible, visible); + return *this; +} + +auto mListView::setHeaderVisible(bool visible) -> type& { + state.headerVisible = visible; + signal(setHeaderVisible, visible); + return *this; +} + +auto mListView::setMultiSelect(bool multiSelect) -> type& { + state.multiSelect = multiSelect; + signal(setMultiSelect, multiSelect); + return *this; +} + +auto mListView::setSelected(bool selected) -> type& { + for(auto& item : state.items) item->state.selected = selected; + signal(setSelected, selected); + return *this; +} diff --git a/hiro/core/widget/progress-bar.cpp b/hiro/core/widget/progress-bar.cpp new file mode 100644 index 00000000..726cfaec --- /dev/null +++ b/hiro/core/widget/progress-bar.cpp @@ -0,0 +1,15 @@ +auto mProgressBar::allocate() -> pObject* { + return new pProgressBar(*this); +} + +// + +auto mProgressBar::position() const -> unsigned { + return state.position; +} + +auto mProgressBar::setPosition(unsigned position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} diff --git a/hiro/core/widget/radio-button.cpp b/hiro/core/widget/radio-button.cpp new file mode 100644 index 00000000..cf64cfd8 --- /dev/null +++ b/hiro/core/widget/radio-button.cpp @@ -0,0 +1,81 @@ +auto mRadioButton::allocate() -> pObject* { + return new pRadioButton(*this); +} + +// + +auto mRadioButton::group(const vector<shared_pointer_weak<mRadioButton>>& group) -> void { + for(auto& weak : group) { + if(auto item = weak.acquire()) item->state.group = group; + } + for(auto& weak : group) { + if(auto item = weak.acquire()) { + if(item->self()) item->self()->setGroup(group); + } + } + if(group.size()) { + if(auto item = group.first().acquire()) item->setChecked(); + } +} + +auto mRadioButton::bordered() const -> bool { + return state.bordered; +} + +auto mRadioButton::checked() const -> bool { + return state.checked; +} + +auto mRadioButton::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mRadioButton::icon() const -> image { + return state.icon; +} + +auto mRadioButton::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mRadioButton::orientation() const -> Orientation { + return state.orientation; +} + +auto mRadioButton::setBordered(bool bordered) -> type& { + state.bordered = bordered; + signal(setBordered, bordered); + return *this; +} + +auto mRadioButton::setChecked() -> type& { + for(auto& weak : state.group) { + if(auto item = weak.acquire()) item->state.checked = false; + } + state.checked = true; + signal(setChecked); + return *this; +} + +auto mRadioButton::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mRadioButton::setOrientation(Orientation orientation) -> type& { + state.orientation = orientation; + signal(setOrientation, orientation); + return *this; +} + +auto mRadioButton::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mRadioButton::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/radio-label.cpp b/hiro/core/widget/radio-label.cpp new file mode 100644 index 00000000..9142643f --- /dev/null +++ b/hiro/core/widget/radio-label.cpp @@ -0,0 +1,51 @@ +auto mRadioLabel::allocate() -> pObject* { + return new pRadioLabel(*this); +} + +// + +auto mRadioLabel::group(const vector<shared_pointer_weak<mRadioLabel>>& group) -> void { + for(auto& weak : group) { + if(auto item = weak.acquire()) item->state.group = group; + } + for(auto& weak : group) { + if(auto item = weak.acquire()) { + if(item->self()) item->self()->setGroup(group); + } + } + if(group.size()) { + if(auto item = group.first().acquire()) item->setChecked(); + } +} + +auto mRadioLabel::checked() const -> bool { + return state.checked; +} + +auto mRadioLabel::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mRadioLabel::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mRadioLabel::setChecked() -> type& { + for(auto& weak : state.group) { + if(auto item = weak.acquire()) item->state.checked = false; + } + state.checked = true; + signal(setChecked); + return *this; +} + +auto mRadioLabel::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mRadioLabel::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/source-edit.cpp b/hiro/core/widget/source-edit.cpp new file mode 100644 index 00000000..d9dd0f8e --- /dev/null +++ b/hiro/core/widget/source-edit.cpp @@ -0,0 +1,52 @@ +auto mSourceEdit::allocate() -> pObject* { + return new pSourceEdit(*this); +} + +// + +auto mSourceEdit::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mSourceEdit::doMove() const -> void { + if(state.onMove) return state.onMove(); +} + +auto mSourceEdit::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mSourceEdit::onMove(const function<void ()>& function) -> type& { + state.onMove = function; + return *this; +} + +auto mSourceEdit::position() const -> unsigned { + return state.position; +} + +auto mSourceEdit::setPosition(signed position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} + +auto mSourceEdit::setSelected(Position selected) -> type& { + if(selected.x() < 0) return *this; + if(selected.y() < 0) selected.setY(-1); + else if(selected.x() > selected.y()) return *this; + state.selected = selected; + signal(setSelected, selected); + return *this; +} + +auto mSourceEdit::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mSourceEdit::text() const -> string { + return signal(text); +} diff --git a/hiro/core/widget/tab-frame-item.cpp b/hiro/core/widget/tab-frame-item.cpp new file mode 100644 index 00000000..0eae926a --- /dev/null +++ b/hiro/core/widget/tab-frame-item.cpp @@ -0,0 +1,95 @@ +auto mTabFrameItem::allocate() -> pObject* { + return new pTabFrameItem(*this); +} + +auto mTabFrameItem::destruct() -> void { + if(auto& layout = state.layout) layout->destruct(); + mObject::destruct(); +} + +// + +auto mTabFrameItem::append(sLayout layout) -> type& { + if(auto& layout = state.layout) remove(layout); + state.layout = layout; + layout->setParent(this, 0); + return *this; +} + +auto mTabFrameItem::closable() const -> bool { + return state.closable; +} + +auto mTabFrameItem::icon() const -> image { + return state.icon; +} + +auto mTabFrameItem::layout() const -> sLayout { + return state.layout; +} + +auto mTabFrameItem::movable() const -> bool { + return state.movable; +} + +auto mTabFrameItem::remove() -> type& { + if(auto tabFrame = parentTabFrame()) tabFrame->remove(*this); + return *this; +} + +auto mTabFrameItem::remove(sLayout layout) -> type& { + layout->setParent(); + state.layout.reset(); + return *this; +} + +auto mTabFrameItem::reset() -> type& { + if(auto layout = state.layout) remove(layout); + return *this; +} + +auto mTabFrameItem::selected() const -> bool { + if(auto tabFrame = parentTabFrame()) return offset() == tabFrame->state.selected; + return false; +} + +auto mTabFrameItem::setClosable(bool closable) -> type& { + state.closable = closable; + signal(setClosable, closable); + return *this; +} + +auto mTabFrameItem::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mTabFrameItem::setMovable(bool movable) -> type& { + state.movable = movable; + signal(setMovable, movable); + return *this; +} + +auto mTabFrameItem::setParent(mObject* parent, signed offset) -> type& { + if(auto layout = state.layout) layout->destruct(); + mObject::setParent(parent, offset); + if(auto layout = state.layout) layout->setParent(this, layout->offset()); + return *this; +} + +auto mTabFrameItem::setSelected() -> type& { + if(auto tabFrame = parentTabFrame()) tabFrame->state.selected = offset(); + signal(setSelected); + return *this; +} + +auto mTabFrameItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mTabFrameItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/tab-frame.cpp b/hiro/core/widget/tab-frame.cpp new file mode 100644 index 00000000..c50ff819 --- /dev/null +++ b/hiro/core/widget/tab-frame.cpp @@ -0,0 +1,90 @@ +auto mTabFrame::allocate() -> pObject* { + return new pTabFrame(*this); +} + +auto mTabFrame::destruct() -> void { + for(auto& item : state.items) item->destruct(); + mWidget::destruct(); +} + +// + +auto mTabFrame::append(sTabFrameItem item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + return *this; +} + +auto mTabFrame::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mTabFrame::doClose(sTabFrameItem item) const -> void { + if(state.onClose) return state.onClose(item); +} + +auto mTabFrame::doMove(sTabFrameItem from, sTabFrameItem to) const -> void { + if(state.onMove) return state.onMove(from, to); +} + +auto mTabFrame::edge() const -> Edge { + return state.edge; +} + +auto mTabFrame::item(unsigned position) const -> sTabFrameItem { + if(position < items()) return state.items[position]; + return {}; +} + +auto mTabFrame::items() const -> unsigned { + return state.items.size(); +} + +auto mTabFrame::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mTabFrame::onClose(const function<void (sTabFrameItem)>& function) -> type& { + state.onClose = function; + return *this; +} + +auto mTabFrame::onMove(const function<void (sTabFrameItem, sTabFrameItem)>& function) -> type& { + state.onMove = function; + return *this; +} + +auto mTabFrame::remove(sTabFrameItem item) -> type& { + auto offset = item->offset(); + item->setParent(); + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(offset, items())) { + state.items[n]->offset(-1); + } + return *this; +} + +auto mTabFrame::reset() -> type& { + while(state.items) remove(state.items.last()); + return *this; +} + +auto mTabFrame::selected() const -> sTabFrameItem { + return state.items[state.selected]; +} + +auto mTabFrame::setEdge(Edge edge) -> type& { + state.edge = edge; + signal(setEdge, edge); + return *this; +} + +auto mTabFrame::setParent(mObject* parent, signed offset) -> type& { + for(auto& item : state.items) item->destruct(); + mObject::setParent(parent, offset); + for(auto& item : state.items) item->setParent(this, item->offset()); + return *this; +} diff --git a/hiro/core/widget/text-edit.cpp b/hiro/core/widget/text-edit.cpp new file mode 100644 index 00000000..ae0982b4 --- /dev/null +++ b/hiro/core/widget/text-edit.cpp @@ -0,0 +1,83 @@ +auto mTextEdit::allocate() -> pObject* { + return new pTextEdit(*this); +} + +// + +auto mTextEdit::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mTextEdit::cursorPosition() const -> unsigned { + return state.cursorPosition; +} + +auto mTextEdit::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mTextEdit::doMove() const -> void { + if(state.onMove) return state.onMove(); +} + +auto mTextEdit::editable() const -> bool { + return state.editable; +} + +auto mTextEdit::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mTextEdit::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mTextEdit::onMove(const function<void ()>& function) -> type& { + state.onMove = function; + return *this; +} + +auto mTextEdit::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mTextEdit::setCursorPosition(unsigned position) -> type& { + state.cursorPosition = position; + signal(setCursorPosition, position); + return *this; +} + +auto mTextEdit::setEditable(bool editable) -> type& { + state.editable = editable; + signal(setEditable, editable); + return *this; +} + +auto mTextEdit::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} + +auto mTextEdit::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mTextEdit::setWordWrap(bool wordWrap) -> type& { + state.wordWrap = wordWrap; + signal(setWordWrap, wordWrap); + return *this; +} + +auto mTextEdit::text() const -> string { + return signal(text); +} + +auto mTextEdit::wordWrap() const -> bool { + return state.wordWrap; +} diff --git a/hiro/core/widget/tree-view-item.cpp b/hiro/core/widget/tree-view-item.cpp new file mode 100644 index 00000000..40995fdf --- /dev/null +++ b/hiro/core/widget/tree-view-item.cpp @@ -0,0 +1,98 @@ +auto mTreeViewItem::allocate() -> pObject* { + return new pTreeViewItem(*this); +} + +auto mTreeViewItem::destruct() -> void { + for(auto& item : state.items) item->destruct(); + mObject::destruct(); +} + +// + +auto mTreeViewItem::append(sTreeViewItem item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + return *this; +} + +auto mTreeViewItem::checked() const -> bool { + return state.checked; +} + +auto mTreeViewItem::icon() const -> image { + return state.icon; +} + +auto mTreeViewItem::item(const string& path) const -> sTreeViewItem { + if(path.empty()) return {}; + auto paths = path.split("/"); + unsigned position = decimal(paths.takeFirst()); + if(position >= items()) return {}; + if(paths.empty()) return state.items[position]; + return state.items[position]->item(paths.merge("/")); +} + +auto mTreeViewItem::items() const -> unsigned { + return state.items.size(); +} + +auto mTreeViewItem::path() const -> string { + if(auto treeViewItem = parentTreeViewItem()) return {treeViewItem->path(), "/", offset()}; + return {offset()}; +} + +auto mTreeViewItem::remove() -> type& { + if(auto treeView = parentTreeView()) treeView->remove(*this); + if(auto treeViewItem = parentTreeViewItem()) treeViewItem->remove(*this); + return *this; +} + +auto mTreeViewItem::remove(sTreeViewItem item) -> type& { + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(item->offset(), items())) { + state.items[n]->offset(-1); + } + item->setParent(); + return *this; +} + +auto mTreeViewItem::selected() const -> bool { + if(auto treeView = parentTreeView(true)) { + return path() == treeView->state.selectedPath; + } + return false; +} + +auto mTreeViewItem::setChecked(bool checked) -> type& { + state.checked = checked; + signal(setChecked, checked); + return *this; +} + +auto mTreeViewItem::setFocused() -> type& { + signal(setFocused); + return *this; +} + +auto mTreeViewItem::setIcon(const image& icon) -> type& { + state.icon = icon; + signal(setIcon, icon); + return *this; +} + +auto mTreeViewItem::setSelected() -> type& { + signal(setSelected); + return *this; +} + +auto mTreeViewItem::setText(const string& text) -> type& { + state.text = text; + signal(setText, text); + return *this; +} + +auto mTreeViewItem::text() const -> string { + return state.text; +} diff --git a/hiro/core/widget/tree-view.cpp b/hiro/core/widget/tree-view.cpp new file mode 100644 index 00000000..217638e2 --- /dev/null +++ b/hiro/core/widget/tree-view.cpp @@ -0,0 +1,128 @@ +auto mTreeView::allocate() -> pObject* { + return new pTreeView(*this); +} + +auto mTreeView::destruct() -> void { + for(auto& item : state.items) item->destruct(); + mWidget::destruct(); +} + +// + +auto mTreeView::append(sTreeViewItem item) -> type& { + state.items.append(item); + item->setParent(this, items() - 1); + signal(append, item); + return *this; +} + +auto mTreeView::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mTreeView::checkable() const -> bool { + return state.checkable; +} + +auto mTreeView::collapse() -> type& { + signal(collapse); + return *this; +} + +auto mTreeView::doActivate() const -> void { + if(state.onActivate) return state.onActivate(); +} + +auto mTreeView::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mTreeView::doContext() const -> void { + if(state.onContext) return state.onContext(); +} + +auto mTreeView::doToggle(sTreeViewItem item) const -> void { + if(state.onToggle) return state.onToggle(item); +} + +auto mTreeView::expand() -> type& { + signal(expand); + return *this; +} + +auto mTreeView::foregroundColor() const -> Color { + return state.foregroundColor; +} + +auto mTreeView::item(const string& path) const -> sTreeViewItem { + if(path.empty()) return {}; + auto paths = path.split("/"); + unsigned position = decimal(paths.takeFirst()); + if(position >= items()) return {}; + if(paths.empty()) return state.items[position]; + return state.items[position]->item(paths.merge("/")); +} + +auto mTreeView::items() const -> unsigned { + return state.items.size(); +} + +auto mTreeView::onActivate(const function<void ()>& function) -> type& { + state.onActivate = function; + return *this; +} + +auto mTreeView::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mTreeView::onContext(const function<void ()>& function) -> type& { + state.onContext = function; + return *this; +} + +auto mTreeView::onToggle(const function<void (sTreeViewItem)>& function) -> type& { + state.onToggle = function; + return *this; +} + +auto mTreeView::remove(sTreeViewItem item) -> type& { + signal(remove, item); + state.items.remove(item->offset()); + for(auto n : range(item->offset(), items())) { + state.items[n]->offset(-1); + } + item->setParent(); + return *this; +} + +auto mTreeView::reset() -> type& { + state.selectedPath.reset(); + signal(reset); + for(auto& item : state.items) item->setParent(); + state.items.reset(); + return *this; +} + +auto mTreeView::selected() const -> sTreeViewItem { + return item(state.selectedPath); +} + +auto mTreeView::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mTreeView::setCheckable(bool checkable) -> type& { + state.checkable = checkable; + signal(setCheckable, checkable); + return *this; +} + +auto mTreeView::setForegroundColor(Color color) -> type& { + state.foregroundColor = color; + signal(setForegroundColor, color); + return *this; +} diff --git a/hiro/core/widget/vertical-scroller.cpp b/hiro/core/widget/vertical-scroller.cpp new file mode 100644 index 00000000..fb7f41ad --- /dev/null +++ b/hiro/core/widget/vertical-scroller.cpp @@ -0,0 +1,34 @@ +auto mVerticalScroller::allocate() -> pObject* { + return new pVerticalScroller(*this); +} + +// + +auto mVerticalScroller::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mVerticalScroller::length() const -> unsigned { + return state.length; +} + +auto mVerticalScroller::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mVerticalScroller::position() const -> unsigned { + return state.position; +} + +auto mVerticalScroller::setLength(unsigned length) -> type& { + state.length = length; + signal(setLength, length); + return *this; +} + +auto mVerticalScroller::setPosition(unsigned position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} diff --git a/hiro/core/widget/vertical-slider.cpp b/hiro/core/widget/vertical-slider.cpp new file mode 100644 index 00000000..e9f51a8c --- /dev/null +++ b/hiro/core/widget/vertical-slider.cpp @@ -0,0 +1,34 @@ +auto mVerticalSlider::allocate() -> pObject* { + return new pVerticalSlider(*this); +} + +// + +auto mVerticalSlider::doChange() const -> void { + if(state.onChange) return state.onChange(); +} + +auto mVerticalSlider::length() const -> unsigned { + return state.length; +} + +auto mVerticalSlider::onChange(const function<void ()>& function) -> type& { + state.onChange = function; + return *this; +} + +auto mVerticalSlider::position() const -> unsigned { + return state.position; +} + +auto mVerticalSlider::setLength(unsigned length) -> type& { + state.length = length; + signal(setLength, length); + return *this; +} + +auto mVerticalSlider::setPosition(unsigned position) -> type& { + state.position = position; + signal(setPosition, position); + return *this; +} diff --git a/hiro/core/widget/viewport.cpp b/hiro/core/widget/viewport.cpp new file mode 100644 index 00000000..b60ec9d9 --- /dev/null +++ b/hiro/core/widget/viewport.cpp @@ -0,0 +1,64 @@ +auto mViewport::allocate() -> pObject* { + return new pViewport(*this); +} + +// + +auto mViewport::doDrop(lstring names) const -> void { + if(state.onDrop) return state.onDrop(names); +} + +auto mViewport::doMouseLeave() const -> void { + if(state.onMouseLeave) return state.onMouseLeave(); +} + +auto mViewport::doMouseMove(Position position) const -> void { + if(state.onMouseMove) return state.onMouseMove(position); +} + +auto mViewport::doMousePress(Mouse::Button button) const -> void { + if(state.onMousePress) return state.onMousePress(button); +} + +auto mViewport::doMouseRelease(Mouse::Button button) const -> void { + if(state.onMouseRelease) return state.onMouseRelease(button); +} + +auto mViewport::droppable() const -> bool { + return state.droppable; +} + +auto mViewport::handle() const -> uintptr_t { + return signal(handle); +} + +auto mViewport::onDrop(const function<void (lstring)>& function) -> type& { + state.onDrop = function; + return *this; +} + +auto mViewport::onMouseLeave(const function<void ()>& function) -> type& { + state.onMouseLeave = function; + return *this; +} + +auto mViewport::onMouseMove(const function<void (Position)>& function) -> type& { + state.onMouseMove = function; + return *this; +} + +auto mViewport::onMousePress(const function<void (Mouse::Button)>& function) -> type& { + state.onMousePress = function; + return *this; +} + +auto mViewport::onMouseRelease(const function<void (Mouse::Button)>& function) -> type& { + state.onMouseRelease = function; + return *this; +} + +auto mViewport::setDroppable(bool droppable) -> type& { + state.droppable = droppable; + signal(setDroppable, droppable); + return *this; +} diff --git a/hiro/core/widget/widget.cpp b/hiro/core/widget/widget.cpp new file mode 100644 index 00000000..599fdac4 --- /dev/null +++ b/hiro/core/widget/widget.cpp @@ -0,0 +1,20 @@ +auto mWidget::allocate() -> pObject* { + return new pWidget(*this); +} + +// + +auto mWidget::doSize() const -> void { + if(state.onSize) return state.onSize(); +} + +auto mWidget::onSize(const function<void ()>& function) -> type& { + state.onSize = function; + return *this; +} + +auto mWidget::remove() -> type& { + if(auto layout = parentLayout()) layout->remove(layout->sizable(offset())); + setParent(); + return *this; +} diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp new file mode 100644 index 00000000..964ae940 --- /dev/null +++ b/hiro/core/window.cpp @@ -0,0 +1,271 @@ +auto mWindow::allocate() -> pObject* { + return new pWindow(*this); +} + +auto mWindow::destruct() -> void { + if(auto& layout = state.layout) layout->destruct(); + if(auto& menuBar = state.menuBar) menuBar->destruct(); + if(auto& statusBar = state.statusBar) statusBar->destruct(); + mObject::destruct(); +} + +// + +auto mWindow::append(shared_pointer<mLayout> layout) -> type& { + if(auto& layout = state.layout) remove(layout); + state.layout = layout; + layout->setGeometry(geometry().setPosition(0, 0)); + layout->setParent(this, 0); + layout->setGeometry(geometry().setPosition(0, 0)); + return *this; +} + +auto mWindow::append(shared_pointer<mMenuBar> menuBar) -> type& { + if(auto& menuBar = state.menuBar) remove(menuBar); + menuBar->setParent(this, 0); + state.menuBar = menuBar; + signal(append, menuBar); + return *this; +} + +auto mWindow::append(shared_pointer<mStatusBar> statusBar) -> type& { + if(auto& statusBar = state.statusBar) remove(statusBar); + statusBar->setParent(this, 0); + state.statusBar = statusBar; + signal(append, statusBar); + return *this; +} + +auto mWindow::backgroundColor() const -> Color { + return state.backgroundColor; +} + +auto mWindow::doClose() const -> void { + if(state.onClose) return state.onClose(); +} + +auto mWindow::doDrop(lstring names) const -> void { + if(state.onDrop) return state.onDrop(names); +} + +auto mWindow::doKeyPress(signed key) const -> void { + if(state.onKeyPress) return state.onKeyPress(key); +} + +auto mWindow::doKeyRelease(signed key) const -> void { + if(state.onKeyRelease) return state.onKeyRelease(key); +} + +auto mWindow::doMove() const -> void { + if(state.onMove) return state.onMove(); +} + +auto mWindow::doSize() const -> void { + if(state.onSize) return state.onSize(); +} + +auto mWindow::droppable() const -> bool { + return state.droppable; +} + +auto mWindow::frameGeometry() const -> Geometry { + Geometry margin = signal(frameMargin); + return { + state.geometry.x() - margin.x(), state.geometry.y() - margin.y(), + state.geometry.width() + margin.width(), state.geometry.height() + margin.height() + }; +} + +auto mWindow::fullScreen() const -> bool { + return state.fullScreen; +} + +auto mWindow::geometry() const -> Geometry { + return state.geometry; +} + +auto mWindow::layout() const -> shared_pointer<mLayout> { + return state.layout; +} + +auto mWindow::menuBar() const -> shared_pointer<mMenuBar> { + return state.menuBar; +} + +auto mWindow::modal() const -> bool { + return state.modal; +} + +auto mWindow::onClose(const function<void ()>& function) -> type& { + state.onClose = function; + return *this; +} + +auto mWindow::onDrop(const function<void (lstring)>& function) -> type& { + state.onDrop = function; + return *this; +} + +auto mWindow::onKeyPress(const function<void (signed)>& function) -> type& { + state.onKeyPress = function; + return *this; +} + +auto mWindow::onKeyRelease(const function<void (signed)>& function) -> type& { + state.onKeyRelease = function; + return *this; +} + +auto mWindow::onMove(const function<void ()>& function) -> type& { + state.onMove = function; + return *this; +} + +auto mWindow::onSize(const function<void ()>& function) -> type& { + state.onSize = function; + return *this; +} + +auto mWindow::remove(shared_pointer<mLayout> layout) -> type& { + layout->setParent(); + state.layout.reset(); + return *this; +} + +auto mWindow::remove(shared_pointer<mMenuBar> menuBar) -> type& { + signal(remove, menuBar); + menuBar->reset(); + menuBar->setParent(); + state.menuBar.reset(); + return *this; +} + +auto mWindow::remove(shared_pointer<mStatusBar> statusBar) -> type& { + signal(remove, statusBar); + statusBar->setParent(); + state.statusBar.reset(); + return *this; +} + +auto mWindow::reset() -> type& { + if(auto& layout = state.layout) remove(layout); + if(auto& menuBar = state.menuBar) remove(menuBar); + if(auto& statusBar = state.statusBar) remove(statusBar); + return *this; +} + +auto mWindow::resizable() const -> bool { + return state.resizable; +} + +auto mWindow::setBackgroundColor(Color color) -> type& { + state.backgroundColor = color; + signal(setBackgroundColor, color); + return *this; +} + +auto mWindow::setCentered() -> type& { + Geometry workspace = Desktop::workspace(); + Geometry geometry = frameGeometry(); + signed x = workspace.x(); + signed y = workspace.y(); + if(workspace.width() > geometry.width()) x += (workspace.width() - geometry.width()) / 2; + if(workspace.height() > geometry.height()) y += (workspace.height() - geometry.height()) / 2; + return setFrameGeometry({x, y, geometry.width(), geometry.height()}); +} + +auto mWindow::setCentered(shared_pointer<mWindow> parent) -> type& { + if(!parent) return setCentered(); + Geometry workspace = parent->frameGeometry(); + Geometry geometry = frameGeometry(); + signed x = workspace.x(); + signed y = workspace.y(); + if(workspace.width() > geometry.width()) x += (workspace.width() - geometry.width()) / 2; + if(workspace.height() > geometry.height()) y += (workspace.height() - geometry.height()) / 2; + return setFrameGeometry({x, y, geometry.width(), geometry.height()}); +} + +auto mWindow::setDroppable(bool droppable) -> type& { + state.droppable = droppable; + signal(setDroppable, droppable); + return *this; +} + +auto mWindow::setFrameGeometry(Geometry geometry) -> type& { + Geometry margin = signal(frameMargin); + return setGeometry({ + geometry.x() + margin.x(), geometry.y() + margin.y(), + geometry.width() - margin.width(), geometry.height() - margin.height() + }); +} + +auto mWindow::setFramePosition(Position position) -> type& { + Geometry margin = signal(frameMargin); + return setGeometry({ + position.x() + margin.x(), position.y() + margin.y(), + state.geometry.width(), state.geometry.height() + }); +} + +auto mWindow::setFrameSize(Size size) -> type& { + Geometry margin = signal(frameMargin); + return setGeometry({ + state.geometry.x(), state.geometry.y(), + size.width() - margin.width(), size.height() - margin.height() + }); +} + +auto mWindow::setFullScreen(bool fullScreen) -> type& { + state.fullScreen = fullScreen; + signal(setFullScreen, fullScreen); + return *this; +} + +auto mWindow::setGeometry(Geometry geometry) -> type& { + state.geometry = geometry; + signal(setGeometry, geometry); + if(auto& layout = state.layout) { + layout->setGeometry(geometry.setPosition(0, 0)); + } + return *this; +} + +auto mWindow::setModal(bool modal) -> type& { + state.modal = modal; + signal(setModal, modal); + return *this; +} + +auto mWindow::setPosition(Position position) -> type& { + return setGeometry({ + position.x(), position.y(), + state.geometry.width(), state.geometry.height() + }); +} + +auto mWindow::setResizable(bool resizable) -> type& { + state.resizable = resizable; + signal(setResizable, resizable); + return *this; +} + +auto mWindow::setSize(Size size) -> type& { + return setGeometry({ + state.geometry.x(), state.geometry.y(), + size.width(), size.height() + }); +} + +auto mWindow::setTitle(const string& title) -> type& { + state.title = title; + signal(setTitle, title); + return *this; +} + +auto mWindow::statusBar() const -> shared_pointer<mStatusBar> { + return state.statusBar; +} + +auto mWindow::title() const -> string { + return state.title; +} diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp new file mode 100644 index 00000000..232cb2b6 --- /dev/null +++ b/hiro/extension/browser-dialog.cpp @@ -0,0 +1,231 @@ +struct BrowserDialogWindow { + BrowserDialogWindow(BrowserDialog::State& state) : state(state) {} + auto accept() -> void; + auto activate() -> void; + auto change() -> void; + auto isFolder(const string& name) -> bool; + auto run() -> lstring; + auto setPath(string path) -> void; + +private: + Window window; + VerticalLayout layout{&window}; + HorizontalLayout pathLayout{&layout, Size{~0, 0}, 8}; + LineEdit pathName{&pathLayout, Size{~0, 0}, 0}; + Button pathHome{&pathLayout, Size{0, 0}, 0}; + Button pathRefresh{&pathLayout, Size{0, 0}, 0}; + Button pathUp{&pathLayout, Size{0, 0}, 0}; + ListView view{&layout, Size{~0, ~0}, 8}; + HorizontalLayout controlLayout{&layout, Size{~0, 0}}; + ComboButton filterList{&controlLayout, Size{120, 0}, 8}; + LineEdit fileName{&controlLayout, Size{~0, 0}, 8}; + Button acceptButton{&controlLayout, Size{80, 0}, 8}; + Button cancelButton{&controlLayout, Size{80, 0}, 8}; + + BrowserDialog::State& state; +}; + +//accept button clicked, or enter pressed on file name line edit +//also called by list view activate after special case handling +auto BrowserDialogWindow::accept() -> void { + auto selectedItems = view.selectedItems(); + + if(state.action == "openFile" && selectedItems) { + string name = selectedItems.first()->text(0); + if(isFolder(name)) return setPath({state.path, name}); + state.response.append(string{state.path, name}); + } + + if(state.action == "openFiles") { + for(auto selectedItem : selectedItems) { + string name = selectedItem->text(0); + state.response.append(string{state.path, name, isFolder(name) ? "/" : ""}); + } + } + + if(state.action == "saveFile") { + string name = fileName.text(); + if(!name && selectedItems) name = selectedItems.first()->text(0); + if(!name || isFolder(name)) return; + if(file::exists({state.path, name})) { + if(MessageDialog("File already exists; overwrite it?").question() != 0) return; + } + state.response.append(string{state.path, name}); + } + + if(state.action == "selectFolder" && selectedItems) { + string name = selectedItems.first()->text(0); + if(isFolder(name)) state.response.append(string{state.path, name, "/"}); + } + + if(state.response) window.setModal(false); +} + +//list view item double-clicked, or enter pressed on selected list view item +auto BrowserDialogWindow::activate() -> void { + auto selectedItem = view.selected(); + if(state.action == "saveFile" && selectedItem) { + string name = selectedItem->text(0); + if(isFolder(name)) return setPath({state.path, name}); + fileName.setText(isFolder(name) ? "" : name); + } + if(state.action == "selectFolder" && selectedItem) { + string name = selectedItem->text(0); + if(isFolder(name)) return setPath({state.path, name}); + } + accept(); +} + +//list view item changed +auto BrowserDialogWindow::change() -> void { + fileName.setText(""); + if(state.action == "saveFile") { + if(auto selectedItem = view.selected()) { + string name = selectedItem->text(0); + if(!isFolder(name)) fileName.setText(name); + } + } +} + +auto BrowserDialogWindow::isFolder(const string& name) -> bool { + return directory::exists({state.path, name}); +} + +auto BrowserDialogWindow::run() -> lstring { + state.response.reset(); + + layout.setMargin(8); + pathName.onActivate([&] { setPath(pathName.text()); }); + pathHome.onActivate([&] { setPath(userpath()); }); + pathHome.setBordered(false).setIcon(Icon::Go::Home); + pathRefresh.onActivate([&] { setPath(state.path); }); + pathRefresh.setBordered(false).setIcon(Icon::Action::Refresh); + pathUp.onActivate([&] { setPath(state.path.dirname()); }); + pathUp.setBordered(false).setIcon(Icon::Go::Up); + view.onActivate([&] { activate(); }); + view.onChange([&] { change(); }); + view.setMultiSelect(state.action == "openFiles"); + filterList.onChange([&] { setPath(state.path); }); + for(auto& filter : state.filters) { + auto part = filter.split<1>("|"); + filterList.append(ComboButtonItem().setText(part.first())); + } + filterList.setVisible(state.action != "selectFolder"); + fileName.onActivate([&] { accept(); }); + fileName.setVisible(state.action == "saveFile"); + acceptButton.onActivate([&] { accept(); }); + if(state.action == "openFile" || state.action == "openFiles") acceptButton.setText("Open"); + if(state.action == "saveFile") acceptButton.setText("Save"); + if(state.action == "selectFolder") acceptButton.setText("Select"); + cancelButton.onActivate([&] { window.setModal(false); }); + cancelButton.setText("Cancel"); + + setPath(state.path); + + window.onClose([&] { window.setModal(false); }); + window.onSize([&] { view.resizeColumns(); }); + window.setTitle(state.title); + window.setSize({640, 480}); + window.setCentered(state.parent); + window.setVisible(); + view.resizeColumns(); + window.setModal(); + window.setVisible(false); + + return state.response; +} + +auto BrowserDialogWindow::setPath(string path) -> void { + path.transform("\\", "/"); + if(!path.endsWith("/")) path.append("/"); + pathName.setText(state.path = path); + + view.reset(); + view.append(ListViewColumn().setWidth(~0)); + view.append(ListViewColumn().setWidth( 0).setForegroundColor({192, 128, 128})); + + for(auto& folder : directory::folders(path)) { + ListViewItem item{&view}; + item.setIcon(0, Icon::Emblem::Folder); + item.setText(0, folder.rtrim("/")); + item.setText(1, octal<3>(storage::mode({path, folder}) & 0777)); + } + + if(state.action != "selectFolder") { //don't show files during folder selection + string filter = "*"; + if(auto selected = filterList.selected()) { + auto part = state.filters[selected->offset()].split<1>("|"); + filter = part.last(); + } + + for(auto& file : directory::files(path)) { + if(!file.match(filter)) continue; + ListViewItem item{&view}; + item.setIcon(0, Icon::Emblem::File); + item.setText(0, file); + item.setText(1, octal<3>(storage::mode({path, file}) & 0777)); + } + } + + if(view.items()) view.setSelected({0}); + Application::processEvents(); + view.resizeColumns().setFocused().doChange(); +} + +// + +BrowserDialog::BrowserDialog() { +} + +auto BrowserDialog::openFile() -> string { + state.action = "openFile"; + if(!state.title) state.title = "Open File"; + if(auto result = _run()) return result.first(); + return {}; +} + +auto BrowserDialog::openFiles() -> lstring { + state.action = "openFiles"; + if(!state.title) state.title = "Open Files"; + if(auto result = _run()) return result; + return {}; +}; + +auto BrowserDialog::saveFile() -> string { + state.action = "saveFile"; + if(!state.title) state.title = "Save File"; + if(auto result = _run()) return result.first(); + return {}; +} + +auto BrowserDialog::selectFolder() -> string { + state.action = "selectFolder"; + if(!state.title) state.title = "Select Folder"; + if(auto result = _run()) return result.first(); + return {}; +} + +auto BrowserDialog::setFilters(const lstring& filters) -> type& { + state.filters = filters; + return *this; +} + +auto BrowserDialog::setParent(const shared_pointer<mWindow>& parent) -> type& { + state.parent = parent; + return *this; +} + +auto BrowserDialog::setPath(const string& path) -> type& { + state.path = path; + return *this; +} + +auto BrowserDialog::setTitle(const string& title) -> type& { + state.title = title; + return *this; +} + +auto BrowserDialog::_run() -> lstring { + if(!state.path) state.path = userpath(); + return BrowserDialogWindow(state).run(); +} diff --git a/hiro/extension/browser-dialog.hpp b/hiro/extension/browser-dialog.hpp new file mode 100644 index 00000000..510ab697 --- /dev/null +++ b/hiro/extension/browser-dialog.hpp @@ -0,0 +1,29 @@ +struct BrowserDialogWindow; + +struct BrowserDialog { + using type = BrowserDialog; + + BrowserDialog(); + auto openFile() -> nall::string; //one existing file + auto openFiles() -> nall::lstring; //any existing files or folders + auto saveFile() -> nall::string; //one file + auto selectFolder() -> nall::string; //one existing folder + auto setFilters(const nall::lstring& filters = {"All|*"}) -> type&; + auto setParent(const nall::shared_pointer<mWindow>& parent) -> type&; + auto setPath(const nall::string& path = "") -> type&; + auto setTitle(const nall::string& title = "") -> type&; + +private: + struct State { + nall::string action; + nall::lstring filters = {"*"}; + nall::shared_pointer<mWindow> parent; + nall::string path; + nall::lstring response; + nall::string title; + } state; + + auto _run() -> nall::lstring; + + friend class BrowserDialogWindow; +}; diff --git a/hiro/extension/extension.cpp b/hiro/extension/extension.cpp new file mode 100644 index 00000000..aa46d451 --- /dev/null +++ b/hiro/extension/extension.cpp @@ -0,0 +1,11 @@ +#include "extension.hpp" +using namespace nall; + +namespace hiro { + #include "../resource/resource.cpp" + #include "fixed-layout.cpp" + #include "horizontal-layout.cpp" + #include "vertical-layout.cpp" + #include "browser-dialog.cpp" + #include "message-dialog.cpp" +} diff --git a/hiro/extension/extension.hpp b/hiro/extension/extension.hpp new file mode 100644 index 00000000..f3655abe --- /dev/null +++ b/hiro/extension/extension.hpp @@ -0,0 +1,9 @@ +namespace hiro { + #include "../resource/resource.hpp" + #include "fixed-layout.hpp" + #include "horizontal-layout.hpp" + #include "vertical-layout.hpp" + #include "shared.hpp" + #include "browser-dialog.hpp" + #include "message-dialog.hpp" +} diff --git a/hiro/extension/fixed-layout.cpp b/hiro/extension/fixed-layout.cpp new file mode 100644 index 00000000..bb976269 --- /dev/null +++ b/hiro/extension/fixed-layout.cpp @@ -0,0 +1,51 @@ +auto mFixedLayout::append(shared_pointer<mSizable> sizable, Geometry geometry) -> type& { + properties.append({geometry}); + mLayout::append(sizable); + sizable->setGeometry(geometry); + return *this; +} + +auto mFixedLayout::minimumSize() const -> Size { + signed width = Size::Minimum, height = Size::Minimum; + for(auto n : range(sizables())) { + width = max(width, sizable(n)->minimumSize().width()); + height = max(height, sizable(n)->minimumSize().height()); + } + return {width, height}; +} + +auto mFixedLayout::remove(shared_pointer<mSizable> sizable) -> type& { + properties.remove(sizable->offset()); + mLayout::remove(sizable); + return *this; +} + +auto mFixedLayout::reset() -> type& { + mLayout::reset(); + properties.reset(); + return *this; +} + +auto mFixedLayout::setEnabled(bool enabled) -> type& { + mLayout::setEnabled(enabled); + for(auto n : range(sizables())) { + sizable(n)->setEnabled(sizable(n)->enabled(true)); + } + return *this; +} + +auto mFixedLayout::setFont(const string& font) -> type& { + mLayout::setFont(font); + for(auto n : range(sizables())) { + sizable(n)->setFont(sizable(n)->font(true)); + } + return *this; +} + +auto mFixedLayout::setVisible(bool visible) -> type& { + mLayout::setVisible(visible); + for(auto n : range(sizables())) { + sizable(n)->setVisible(sizable(n)->visible(true)); + } + return *this; +} diff --git a/hiro/extension/fixed-layout.hpp b/hiro/extension/fixed-layout.hpp new file mode 100644 index 00000000..37f50ada --- /dev/null +++ b/hiro/extension/fixed-layout.hpp @@ -0,0 +1,18 @@ +struct mFixedLayout : mLayout { + using type = mFixedLayout; + using mLayout::append; + using mLayout::remove; + + auto append(nall::shared_pointer<mSizable> sizable, Geometry geometry) -> type&; + auto minimumSize() const -> Size override; + auto remove(nall::shared_pointer<mSizable> sizable) -> type& override; + auto reset() -> type& override; + auto setEnabled(bool enabled = true) -> type& override; + auto setFont(const nall::string& font = "") -> type& override; + auto setVisible(bool visible = true) ->type& override; + + struct Properties { + Geometry geometry; + }; + nall::vector<Properties> properties; +}; diff --git a/hiro/extension/horizontal-layout.cpp b/hiro/extension/horizontal-layout.cpp new file mode 100644 index 00000000..4d50d4c5 --- /dev/null +++ b/hiro/extension/horizontal-layout.cpp @@ -0,0 +1,125 @@ +auto mHorizontalLayout::append(shared_pointer<mSizable> sizable, Size size, signed spacing) -> type& { + properties.append({size.width(), size.height(), spacing < 0 ? settings.spacing : spacing}); + mLayout::append(sizable); + return *this; +} + +auto mHorizontalLayout::minimumSize() const -> Size { + signed width = 0, height = 0; + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.width == Size::Minimum || child.width == Size::Maximum) { + width += sizable(n)->minimumSize().width(); + } else { + width += child.width; + } + if(&child != &properties.last()) width += child.spacing; + } + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.height == Size::Minimum || child.height == Size::Maximum) { + height = max(height, sizable(n)->minimumSize().height()); + continue; + } + height = max(height, child.height); + } + + return {settings.margin * 2 + width, settings.margin * 2 + height}; +} + +auto mHorizontalLayout::remove(shared_pointer<mSizable> sizable) -> type& { + properties.remove(sizable->offset()); + mLayout::remove(sizable); + return *this; +} + +auto mHorizontalLayout::reset() -> type& { + mLayout::reset(); + properties.reset(); + return *this; +} + +auto mHorizontalLayout::setAlignment(double alignment) -> type& { + settings.alignment = max(0.0, min(1.0, alignment)); + return *this; +} + +auto mHorizontalLayout::setEnabled(bool enabled) -> type& { + mLayout::setEnabled(enabled); + for(auto n : range(sizables())) { + sizable(n)->setEnabled(sizable(n)->enabled(true)); + } + return *this; +} + +auto mHorizontalLayout::setFont(const string& font) -> type& { + mLayout::setFont(font); + for(auto n : range(sizables())) { + sizable(n)->setFont(sizable(n)->font(true)); + } + return *this; +} + +auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& { + mLayout::setGeometry(containerGeometry); + + auto properties = this->properties; + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width(); + if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height(); + } + + Geometry geometry = containerGeometry; + geometry.setX (geometry.x() + settings.margin ); + geometry.setY (geometry.y() + settings.margin ); + geometry.setWidth (geometry.width() - settings.margin * 2); + geometry.setHeight(geometry.height() - settings.margin * 2); + + signed minimumWidth = 0, maximumWidthCounter = 0; + for(auto& child : properties) { + if(child.width == Size::Maximum) maximumWidthCounter++; + if(child.width != Size::Maximum) minimumWidth += child.width; + if(&child != &properties.last()) minimumWidth += child.spacing; + } + + for(auto& child : properties) { + if(child.width == Size::Maximum) child.width = (geometry.width() - minimumWidth) / maximumWidthCounter; + if(child.height == Size::Maximum) child.height = geometry.height(); + } + + signed maximumHeight = 0; + for(auto& child : properties) maximumHeight = max(maximumHeight, child.height); + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + signed pivot = (maximumHeight - child.height) * settings.alignment; + Geometry childGeometry = {geometry.x(), geometry.y() + pivot, child.width, child.height}; + if(childGeometry.width() < 1) childGeometry.setWidth (1); + if(childGeometry.height() < 1) childGeometry.setHeight(1); + sizable(n)->setGeometry(childGeometry); + + geometry.setX (geometry.x() + child.width + child.spacing); + geometry.setWidth(geometry.width() - child.width + child.spacing); + } +} + +auto mHorizontalLayout::setMargin(signed margin) -> type& { + settings.margin = margin; + return *this; +} + +auto mHorizontalLayout::setSpacing(signed spacing) -> type& { + settings.spacing = spacing; + return *this; +} + +auto mHorizontalLayout::setVisible(bool visible) -> type& { + mLayout::setVisible(visible); + for(auto n : range(sizables())) { + sizable(n)->setVisible(sizable(n)->visible(true)); + } + return *this; +} diff --git a/hiro/extension/horizontal-layout.hpp b/hiro/extension/horizontal-layout.hpp new file mode 100644 index 00000000..9a941dc2 --- /dev/null +++ b/hiro/extension/horizontal-layout.hpp @@ -0,0 +1,30 @@ +struct mHorizontalLayout : mLayout { + using type = mHorizontalLayout; + using mLayout::append; + using mLayout::remove; + + auto append(nall::shared_pointer<mSizable> sizable, Size size, signed spacing = 5) -> type&; + auto minimumSize() const -> Size override; + auto remove(nall::shared_pointer<mSizable> sizable) -> type& override; + auto reset() -> type& override; + auto setAlignment(double alignment = 0.5) -> type&; + auto setEnabled(bool enabled = true) -> type& override; + auto setFont(const nall::string& font = "") -> type& override; + auto setGeometry(Geometry geometry) -> type& override; + auto setMargin(signed margin = 0) -> type&; + auto setSpacing(signed spacing = 5) -> type&; + auto setVisible(bool visible = true) -> type&; + + struct Settings { + double alignment = 0.5; + signed margin = 0; + signed spacing = 5; + } settings; + + struct Property { + signed width; + signed height; + signed spacing; + }; + nall::vector<Property> properties; +}; diff --git a/hiro/extension/message-dialog.cpp b/hiro/extension/message-dialog.cpp new file mode 100644 index 00000000..2745e37a --- /dev/null +++ b/hiro/extension/message-dialog.cpp @@ -0,0 +1,77 @@ +MessageDialog::MessageDialog(const string& text) { + state.text = text; +} + +auto MessageDialog::error(const lstring& buttons) -> signed { + state.buttons = buttons; + state.icon = Icon::Prompt::Error; + return _run(); +} + +auto MessageDialog::information(const lstring& buttons) -> signed { + state.buttons = buttons; + state.icon = Icon::Prompt::Information; + return _run(); +} + +auto MessageDialog::question(const lstring& buttons) -> signed { + state.buttons = buttons; + state.icon = Icon::Prompt::Question; + return _run(); +} + +auto MessageDialog::setParent(shared_pointer<mWindow> parent) -> type& { + state.parent = parent; + return *this; +} + +auto MessageDialog::setText(const string& text) -> type& { + state.text = text; + return *this; +} + +auto MessageDialog::setTitle(const string& title) -> type& { + state.title = title; + return *this; +} + +auto MessageDialog::warning(const lstring& buttons) -> signed { + state.buttons = buttons; + state.icon = Icon::Prompt::Warning; + return _run(); +} + +auto MessageDialog::_run() -> signed { + Window window; + VerticalLayout layout{&window}; + HorizontalLayout messageLayout{&layout, Size{~0, 0}, 8}; + Canvas messageIcon{&messageLayout, Size{16, 16}, 8}; + Label messageText{&messageLayout, Size{~0, 0}}; + HorizontalLayout controlLayout{&layout, Size{~0, 0}}; + Widget controlSpacer{&controlLayout, Size{~0, 0}}; + + layout.setMargin(8); + messageIcon.setIcon(state.icon); + messageText.setText(state.text); + for(auto n : range(state.buttons)) { + Button button{&controlLayout, Size{80, 0}, 8}; + button.onActivate([&, n] { state.response = n; window.setModal(false); }); + button.setText(state.buttons[n]); + button.setFocused(); //the last button will have effective focus + } + + signed widthMessage = 8 + 16 + 8 + Font::size(Font::sans(), state.text).width() + 8; + signed widthButtons = 8 + state.buttons.size() * 88; + signed width = max(320, widthMessage, widthButtons); + + window.onClose([&] { state.response = -1; window.setModal(false); }); + window.setTitle(state.title); + window.setResizable(false); + window.setSize({width, layout.minimumSize().height()}); + window.setCentered(state.parent); + window.setVisible(); + window.setModal(); + window.setVisible(false); + + return state.response; +} diff --git a/hiro/extension/message-dialog.hpp b/hiro/extension/message-dialog.hpp new file mode 100644 index 00000000..0f3627c2 --- /dev/null +++ b/hiro/extension/message-dialog.hpp @@ -0,0 +1,24 @@ +struct MessageDialog { + using type = MessageDialog; + + MessageDialog(const nall::string& text = ""); + auto error(const nall::lstring& buttons = {"Ok"}) -> signed; + auto information(const nall::lstring& buttons = {"Ok"}) -> signed; + auto question(const nall::lstring& buttons = {"Yes", "No"}) -> signed; + auto setParent(nall::shared_pointer<mWindow> parent = {}) -> type&; + auto setText(const nall::string& text = "") -> type&; + auto setTitle(const nall::string& title = "") -> type&; + auto warning(const nall::lstring& buttons = {"Ok"}) -> signed; + +private: + struct State { + nall::lstring buttons; + nall::vector<uint8_t> icon; + nall::shared_pointer<mWindow> parent; + signed response = -1; + nall::string text; + nall::string title; + } state; + + auto _run() -> signed; +}; diff --git a/hiro/extension/shared.hpp b/hiro/extension/shared.hpp new file mode 100644 index 00000000..0572e862 --- /dev/null +++ b/hiro/extension/shared.hpp @@ -0,0 +1,768 @@ +#define Declare(Name) \ + using type = Name; \ + Name() : s##Name(new m##Name, [](m##Name* p) { \ + p->unbind(); \ + delete p; \ + }) { \ + (*this)->bind(*this); \ + } \ + template<typename T, typename... P> Name(T* parent, P&&... p) : Name() { \ + if(parent && *parent) (*parent)->append(*this, std::forward<P>(p)...); \ + } \ + auto self() const -> m##Name& { return (m##Name&)operator*(); } \ + +#define DeclareObject(Name) \ + Declare(Name) \ + auto enabled(bool recursive = false) const -> bool { return self().enabled(recursive); } \ + auto focused() const -> bool { return self().focused(); } \ + auto font(bool recursive = false) const -> string { return self().font(recursive); } \ + auto remove() -> type& { return self().remove(), *this; } \ + auto setEnabled(bool enabled = true) -> type& { return self().setEnabled(enabled), *this; } \ + auto setFocused() -> type& { return self().setFocused(), *this; } \ + auto setFont(const string& font = "") -> type& { return self().setFont(font), *this; } \ + auto setVisible(bool visible = true) -> type& { return self().setVisible(visible), *this; } \ + auto visible(bool recursive = false) const -> bool { return self().visible(recursive); } \ + +#define DeclareAction(Name) \ + DeclareObject(Name) \ + +#define DeclareSizable(Name) \ + DeclareObject(Name) \ + auto geometry() const -> Geometry { return self().geometry(); } \ + auto minimumSize() const -> Size { return self().minimumSize(); } \ + auto setGeometry(Geometry geometry) -> type& { return self().setGeometry(geometry), *this; } \ + +#define DeclareLayout(Name) \ + DeclareSizable(Name) \ + auto append(sSizable sizable) -> type& { return self().append(sizable), *this; } \ + auto remove(sSizable sizable) -> type& { return self().remove(sizable), *this; } \ + auto reset() -> type& { return self().reset(), *this; } \ + auto sizable(unsigned position) -> sSizable { return self().sizable(position); } \ + auto sizables() const -> unsigned { return self().sizables(); } \ + +#define DeclareWidget(Name) \ + DeclareSizable(Name) \ + auto doSize() const -> void { return self().doSize(); } \ + auto onSize(const function<void ()>& function = {}) -> type& { return self().onSize(function), *this; } \ + +struct Object : sObject { + DeclareObject(Object) +}; + +struct Hotkey : sHotkey { + DeclareObject(Hotkey) + + auto doPress() const -> void { return self().doPress(); } + auto doRelease() const -> void { return self().doRelease(); } + auto onPress(const function<void ()>& function = {}) -> type& { return self().onPress(function), *this; } + auto onRelease(const function<void ()>& function = {}) -> type& { return self().onRelease(function), *this; } + auto parent() const -> wObject { return self().parent(); } + auto sequence() const -> string { return self().sequence(); } + auto setParent(sObject object) -> type& { return self().setParent(object), *this; } + auto setSequence(const string& sequence = "") -> type& { return self().setSequence(sequence), *this; } +}; + +struct Timer : sTimer { + DeclareObject(Timer) + + auto doActivate() const -> void { return self().doActivate(); } + auto interval() const -> unsigned { return self().interval(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto setInterval(unsigned interval = 0) -> type& { return self().setInterval(interval), *this; } +}; + +struct Window : sWindow { + DeclareObject(Window) + + auto append(sLayout layout) -> type& { return self().append(layout), *this; } + auto append(sMenuBar menuBar) -> type& { return self().append(menuBar), *this; } + auto append(sStatusBar statusBar) -> type& { return self().append(statusBar), *this; } + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto doClose() const -> void { return self().doClose(); } + auto doDrop(lstring names) const -> void { return self().doDrop(names); } + auto doKeyPress(signed key) const -> void { return self().doKeyPress(key); } + auto doKeyRelease(signed key) const -> void { return self().doKeyRelease(key); } + auto doMove() const -> void { return self().doMove(); } + auto doSize() const -> void { return self().doSize(); } + auto droppable() const -> bool { return self().droppable(); } + auto frameGeometry() const -> Geometry { return self().frameGeometry(); } + auto fullScreen() const -> bool { return self().fullScreen(); } + auto geometry() const -> Geometry { return self().geometry(); } + auto layout() const -> sLayout { return self().layout(); } + auto menuBar() const -> sMenuBar { return self().menuBar(); } + auto modal() const -> bool { return self().modal(); } + auto onClose(const function<void ()>& function = {}) -> type& { return self().onClose(function), *this; } + auto onDrop(const function<void (nall::lstring)>& function = {}) -> type& { return self().onDrop(function), *this; } + auto onKeyPress(const function<void (signed)>& function = {}) -> type& { return self().onKeyPress(function), *this; } + auto onKeyRelease(const function<void (signed)>& function = {}) -> type& { return self().onKeyRelease(function), *this; } + auto onMove(const function<void ()>& function = {}) -> type& { return self().onMove(function), *this; } + auto onSize(const function<void ()>& function = {}) -> type& { return self().onSize(function), *this; } + auto remove(sLayout layout) -> type& { return self().remove(layout), *this; } + auto remove(sMenuBar menuBar) -> type& { return self().remove(menuBar), *this; } + auto remove(sStatusBar statusBar) -> type& { return self().remove(statusBar), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto resizable() const -> bool { return self().resizable(); } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setCentered() -> type& { return self().setCentered(), *this; } + auto setCentered(sWindow parent) -> type& { return self().setCentered(parent), *this; } + auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; } + auto setFrameGeometry(Geometry geometry) -> type& { return self().setFrameGeometry(geometry), *this; } + auto setFramePosition(Position position) -> type& { return self().setFramePosition(position), *this; } + auto setFrameSize(Size size) -> type& { return self().setFrameSize(size), *this; } + auto setFullScreen(bool fullScreen = true) -> type& { return self().setFullScreen(fullScreen), *this; } + auto setGeometry(Geometry geometry) -> type& { return self().setGeometry(geometry), *this; } + auto setModal(bool modal = true) -> type& { return self().setModal(modal), *this; } + auto setPosition(Position position) -> type& { return self().setPosition(position), *this; } + auto setResizable(bool resizable = true) -> type& { return self().setResizable(resizable), *this; } + auto setSize(Size size) -> type& { return self().setSize(size), *this; } + auto setTitle(const string& title = "") -> type& { return self().setTitle(title), *this; } + auto statusBar() const -> sStatusBar { return self().statusBar(); } + auto title() const -> string { return self().title(); } +}; + +struct StatusBar : sStatusBar { + DeclareObject(StatusBar) + + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct MenuBar : sMenuBar { + DeclareObject(MenuBar) + + auto append(sMenu menu) -> type& { return self().append(menu), *this; } + auto menu(unsigned position) const -> sMenu { return self().menu(position); } + auto menus() const -> unsigned { return self().menus(); } + auto remove(sMenu menu) -> type& { return self().remove(menu), *this; } + auto reset() -> type& { return self().reset(), *this; } +}; + +struct PopupMenu : sPopupMenu { + DeclareObject(PopupMenu) + + auto action(unsigned position) const -> sAction { return self().action(position); } + auto actions() const -> unsigned { return self().actions(); } + auto append(sAction action) -> type& { return self().append(action), *this; } + auto remove(sAction action) -> type& { return self().remove(action), *this; } + auto reset() -> type& { return self().reset(), *this; } +}; + +struct Action : sAction { + DeclareAction(Action) +}; + +struct Menu : sMenu { + DeclareAction(Menu) + + auto action(unsigned position) const -> sAction { return self().action(position); } + auto actions() const -> unsigned { return self().actions(); } + auto append(sAction action) -> type& { return self().append(action), *this; } + auto icon() const -> image { return self().icon(); } + auto remove(sAction action) -> type& { return self().remove(action), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct MenuSeparator : sMenuSeparator { + DeclareAction(MenuSeparator) +}; + +struct MenuItem : sMenuItem { + DeclareAction(MenuItem) + + auto doActivate() const -> void { return self().doActivate(); } + auto icon() const -> image { return self().icon(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct MenuCheckItem : sMenuCheckItem { + DeclareAction(MenuCheckItem) + + auto checked() const -> bool { return self().checked(); } + auto doToggle() const -> void { return self().doToggle(); } + auto onToggle(const function<void ()>& function = {}) -> type& { return self().onToggle(function), *this; } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct MenuRadioItem : sMenuRadioItem { + DeclareAction(MenuRadioItem) + + auto checked() const -> bool { return self().checked(); } + auto doActivate() const -> void { return self().doActivate(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto setChecked() -> type& { return self().setChecked(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } + + static auto group(const vector<wMenuRadioItem>& group) -> void { return mMenuRadioItem::group(group); } +}; + +struct Sizable : sSizable { + DeclareSizable(Sizable) +}; + +struct Layout : sLayout { + DeclareLayout(Layout) +}; + +struct Widget : sWidget { + DeclareWidget(Widget) +}; + +struct Button : sButton { + DeclareWidget(Button) + + auto bordered() const -> bool { return self().bordered(); } + auto doActivate() const -> void { return self().doActivate(); } + auto icon() const -> image { return self().icon(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto orientation() const -> Orientation { return self().orientation(); } + auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct Canvas : sCanvas { + DeclareWidget(Canvas) + + auto color() const -> Color { return self().color(); } + auto data() -> uint32_t* { return self().data(); } + auto droppable() const -> bool { return self().droppable(); } + auto doDrop(lstring names) -> void { return self().doDrop(names); } + auto doMouseLeave() const -> void { return self().doMouseLeave(); } + auto doMouseMove(Position position) const -> void { return self().doMouseMove(position); } + auto doMousePress(Mouse::Button button) const -> void { return self().doMousePress(button); } + auto doMouseRelease(Mouse::Button button) const -> void { return self().doMouseRelease(button); } + auto gradient() const -> vector<Color> { return self().gradient(); } + auto icon() const -> image { return self().icon(); } + auto onDrop(const function<void (lstring)>& function = {}) -> type& { return self().onDrop(function), *this; } + auto onMouseLeave(const function<void ()>& function = {}) -> type& { return self().onMouseLeave(function), *this; } + auto onMouseMove(const function<void (Position)>& function = {}) -> type& { return self().onMouseMove(function), *this; } + auto onMousePress(const function<void (Mouse::Button)>& function = {}) -> type& { return self().onMousePress(function), *this; } + auto onMouseRelease(const function<void (Mouse::Button)>& function = {}) -> type& { return self().onMouseRelease(function), *this; } + auto setColor(Color color) -> type& { return self().setColor(color), *this; } + auto setData(Size size) -> type& { return self().setData(size), *this; } + auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; } + auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> type& { return self().setGradient(topLeft, topRight, bottomLeft, bottomRight), *this; } + auto setHorizontalGradient(Color left, Color right) -> type& { return self().setGradient(left, right, left, right), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setVerticalGradient(Color top, Color bottom) -> type& { return self().setGradient(top, top, bottom, bottom), *this; } + auto size() const -> Size { return self().size(); } + auto update() -> type& { return self().update(), *this; } +}; + +struct CheckButton : sCheckButton { + DeclareWidget(CheckButton) + + auto bordered() const -> bool { return self().bordered(); } + auto checked() const -> bool { return self().checked(); } + auto doToggle() const -> void { return self().doToggle(); } + auto icon() const -> image { return self().icon(); } + auto onToggle(const function<void ()>& function = {}) -> type& { return self().onToggle(function), *this; } + auto orientation() const -> Orientation { return self().orientation(); } + auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct CheckLabel : sCheckLabel { + DeclareWidget(CheckLabel) + + auto checked() const -> bool { return self().checked(); } + auto doToggle() const -> void { return self().doToggle(); } + auto onToggle(const function<void ()>& function = {}) -> type& { return self().onToggle(function), *this; } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct ComboButton : sComboButton { + DeclareWidget(ComboButton) + + auto append(sComboButtonItem item) -> type& { return self().append(item), *this; } + auto doChange() const -> void { return self().doChange(); } + auto item(unsigned position) const -> sComboButtonItem { return self().item(position); } + auto items() const -> unsigned { return self().items(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto remove(sComboButtonItem item) -> type& { return self().remove(item), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto selected() const -> sComboButtonItem { return self().selected(); } +}; + +struct ComboButtonItem : sComboButtonItem { + DeclareObject(ComboButtonItem) + + auto icon() const -> image { return self().icon(); } + auto selected() const -> bool { return self().selected(); } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setSelected() -> type& { return self().setSelected(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct Console : sConsole { + DeclareWidget(Console) + + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto doActivate(string command) const -> void { return self().doActivate(command); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto onActivate(const function<void (string)>& function = {}) -> type& { return self().onActivate(function), *this; } + auto print(const string& text) -> type& { return self().print(text), *this; } + auto prompt() const -> string { return self().prompt(); } + auto reset() -> type& { return self().reset(), *this; } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setPrompt(const string& prompt = "") -> type& { return self().setPrompt(prompt), *this; } +}; + +struct Frame : sFrame { + DeclareWidget(Frame) + + auto append(sLayout layout) -> type& { return self().append(layout), *this; } + auto layout() const -> sLayout { return self().layout(); } + auto remove(sLayout layout) -> type& { return self().remove(layout), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct HexEdit : sHexEdit { + DeclareWidget(HexEdit) + + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto columns() const -> unsigned { return self().columns(); } + auto doRead(unsigned offset) const -> uint8_t { return self().doRead(offset); } + auto doWrite(unsigned offset, uint8_t data) const -> void { return self().doWrite(offset, data); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto length() const -> unsigned { return self().length(); } + auto offset() const -> unsigned { return self().offset(); } + auto onRead(const function<uint8_t (unsigned)>& function = {}) -> type& { return self().onRead(function), *this; } + auto onWrite(const function<void (unsigned, uint8_t)>& function = {}) -> type& { return self().onWrite(function), *this; } + auto rows() const -> unsigned { return self().rows(); } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setColumns(unsigned columns = 16) -> type& { return self().setColumns(columns), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setLength(unsigned length) -> type& { return self().setLength(length), *this; } + auto setOffset(unsigned offset) -> type& { return self().setOffset(offset), *this; } + auto setRows(unsigned rows = 16) -> type& { return self().setRows(rows), *this; } + auto update() -> type& { return self().update(), *this; } +}; + +struct HorizontalScroller : sHorizontalScroller { + DeclareWidget(HorizontalScroller) + + auto doChange() const -> void { return self().doChange(); } + auto length() const -> unsigned { return self().length(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto position() const -> unsigned { return self().position(); } + auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; } + auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; } +}; + +struct HorizontalSlider : sHorizontalSlider { + DeclareWidget(HorizontalSlider) + + auto doChange() const -> void { return self().doChange(); } + auto length() const -> unsigned { return self().length(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto position() const -> unsigned { return self().position(); } + auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; } + auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; } +}; + +struct IconView : sIconView { + DeclareWidget(IconView) + + auto append(sIconViewItem item) -> type& { return self().append(item), *this; } + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto doActivate() const -> void { return self().doActivate(); } + auto doChange() const -> void { return self().doChange(); } + auto doContext() const -> void { return self().doContext(); } + auto flow() const -> Orientation { return self().flow(); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto item(unsigned position) const -> sIconViewItem { return self().item(position); } + auto items() const -> unsigned { return self().items(); } + auto multiSelect() const -> bool { return self().multiSelect(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onContext(const function<void ()>& function = {}) -> type& { return self().onContext(function), *this; } + auto orientation() const -> Orientation { return self().orientation(); } + auto remove(sIconViewItem item) -> type& { return self().remove(item), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto selected() const -> maybe<unsigned> { return self().selected(); } + auto selectedItems() const -> vector<unsigned> { return self().selectedItems(); } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setFlow(Orientation orientation = Orientation::Vertical) -> type& { return self().setFlow(orientation), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setMultiSelect(bool multiSelect = true) -> type& { return self().setMultiSelect(multiSelect), *this; } + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; } + auto setSelected(const vector<signed>& selections) -> type& { return self().setSelected(selections), *this; } +}; + +struct IconViewItem : sIconViewItem { + DeclareObject(IconViewItem) + + auto icon() const -> image { return self().icon(); } + auto selected() const -> bool { return self().selected(); } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setSelected(bool selected = true) -> type& { return self().setSelected(selected), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct Label : sLabel { + DeclareWidget(Label) + + auto horizontalAlignment() const -> double { return self().horizontalAlignment(); } + auto setHorizontalAlignment(double alignment = 0.0) -> type& { return self().setHorizontalAlignment(alignment), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto setVerticalAlignment(double alignment = 0.5) -> type& { return self().setVerticalAlignment(alignment), *this; } + auto text() const -> string { return self().text(); } + auto verticalAlignment() const -> double { return self().verticalAlignment(); } +}; + +struct LineEdit : sLineEdit { + DeclareWidget(LineEdit) + + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto doActivate() const -> void { return self().doActivate(); } + auto doChange() const -> void { return self().doChange(); } + auto editable() const -> bool { return self().editable(); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct ListView : sListView { + DeclareWidget(ListView) + + auto append(sListViewColumn column) -> type& { return self().append(column), *this; } + auto append(sListViewItem item) -> type& { return self().append(item), *this; } + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto checkable() const -> bool { return self().checkable(); } + auto checked() const -> vector<sListViewItem> { return self().checked(); } + auto column(unsigned position) -> sListViewColumn { return self().column(position); } + auto columns() const -> unsigned { return self().columns(); } + auto doActivate() const -> void { return self().doActivate(); } + auto doChange() const -> void { return self().doChange(); } + auto doContext() const -> void { return self().doContext(); } + auto doEdit(sListViewItem item, sListViewColumn column) const -> void { return self().doEdit(item, column); } + auto doSort(sListViewColumn column) const -> void { return self().doSort(column); } + auto doToggle(sListViewItem item) const -> void { return self().doToggle(item); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto gridVisible() const -> bool { return self().gridVisible(); } + auto headerVisible() const -> bool { return self().headerVisible(); } + auto item(unsigned position) -> sListViewItem { return self().item(position); } + auto items() const -> unsigned { return self().items(); } + auto multiSelect() const -> bool { return self().multiSelect(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onContext(const function<void ()>& function = {}) -> type& { return self().onContext(function), *this; } + auto onEdit(const function<void (sListViewItem, sListViewColumn)>& function = {}) -> type& { return self().onEdit(function), *this; } + auto onSort(const function<void (sListViewColumn)>& function = {}) -> type& { return self().onSort(function), *this; } + auto onToggle(const function<void (sListViewItem)>& function = {}) -> type& { return self().onToggle(function), *this; } + auto remove(sListViewColumn column) -> type& { return self().remove(column), *this; } + auto remove(sListViewItem item) -> type& { return self().remove(item), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto resizeColumns() -> type& { return self().resizeColumns(), *this; } + auto selected() const -> sListViewItem { return self().selected(); } + auto selectedItems() const -> vector<sListViewItem> { return self().selectedItems(); } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setCheckable(bool checkable = true) -> type& { return self().setCheckable(checkable), *this; } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setGridVisible(bool visible = true) -> type& { return self().setGridVisible(visible), *this; } + auto setHeaderVisible(bool visible = true) -> type& { return self().setHeaderVisible(visible), *this; } + auto setMultiSelect(bool multiSelect = true) -> type& { return self().setMultiSelect(multiSelect), *this; } + auto setSelected(bool selected = true) -> type& { return self().setSelected(selected), *this; } +}; + +struct ListViewColumn : sListViewColumn { + DeclareObject(ListViewColumn) + + auto active() const -> bool { return self().active(); } + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto editable() const -> bool { return self().editable(); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto horizontalAlignment() const -> double { return self().horizontalAlignment(); } + auto icon() const -> image { return self().icon(); } + auto resizable() const -> bool { return self().resizable(); } + auto setActive() -> type& { return self().setActive(), *this; } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setHorizontalAlignment(double alignment = 0.0) -> type& { return self().setHorizontalAlignment(alignment), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setResizable(bool resizable = true) -> type& { return self().setResizable(resizable), *this; } + auto setSortable(bool sortable = true) -> type& { return self().setSortable(sortable), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto setVerticalAlignment(double alignment = 0.5) -> type& { return self().setVerticalAlignment(alignment), *this; } + auto setWidth(signed width = 0) -> type& { return self().setWidth(width), *this; } + auto sortable() const -> bool { return self().sortable(); } + auto text() const -> string { return self().text(); } + auto verticalAlignment() const -> double { return self().verticalAlignment(); } + auto width() const -> signed { return self().width(); } +}; + +struct ListViewItem : sListViewItem { + DeclareObject(ListViewItem) + + auto checked() const -> bool { return self().checked(); } + auto icon(unsigned column = 0) const -> image { return self().icon(column); } + auto selected() const -> bool { return self().selected(); } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setIcon(unsigned column, const image& icon = {}) -> type& { return self().setIcon(column, icon), *this; } + auto setSelected(bool selected = true) -> type& { return self().setSelected(selected), *this; } + auto setText(const lstring& text) -> type& { return self().setText(text), *this; } + auto setText(unsigned column, const string& text = "") -> type& { return self().setText(column, text), *this; } + auto text(unsigned column = 0) const -> string { return self().text(column); } +}; + +struct ProgressBar : sProgressBar { + DeclareWidget(ProgressBar) + + auto position() const -> unsigned { return self().position(); } + auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; } +}; + +struct RadioButton : sRadioButton { + DeclareWidget(RadioButton) + + auto bordered() const -> bool { return self().bordered(); } + auto checked() const -> bool { return self().checked(); } + auto doActivate() const -> void { return self().doActivate(); } + auto icon() const -> image { return self().icon(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto orientation() const -> Orientation { return self().orientation(); } + auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; } + auto setChecked() -> type& { return self().setChecked(), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } + + static auto group(const vector<wRadioButton>& group) -> void { return mRadioButton::group(group); } +}; + +struct RadioLabel : sRadioLabel { + DeclareWidget(RadioLabel) + + auto checked() const -> bool { return self().checked(); } + auto doActivate() const -> void { return self().doActivate(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto setChecked() -> type& { return self().setChecked(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } + + static auto group(const vector<wRadioLabel>& group) -> void { return mRadioLabel::group(group); } +}; + +struct SourceEdit : sSourceEdit { + DeclareWidget(SourceEdit) + + auto doChange() const -> void { return self().doChange(); } + auto doMove() const -> void { return self().doMove(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onMove(const function<void ()>& function = {}) -> type& { return self().onMove(function), *this; } + auto position() const -> unsigned { return self().position(); } + auto setPosition(signed position) -> type& { return self().setPosition(position), *this; } + auto setSelected(Position selected) -> type& { return self().setSelected(selected), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct TabFrame : sTabFrame { + DeclareWidget(TabFrame) + + auto append(sTabFrameItem item) -> type& { return self().append(item), *this; } + auto doChange() const -> void { return self().doChange(); } + auto doClose(sTabFrameItem item) const -> void { return self().doClose(item); } + auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void { return self().doMove(from, to); } + auto edge() const -> Edge; + auto item(unsigned position) const -> sTabFrameItem { return self().item(position); } + auto items() const -> unsigned { return self().items(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onClose(const function<void (sTabFrameItem)>& function = {}) -> type& { return self().onClose(function), *this; } + auto onMove(const function<void (sTabFrameItem, sTabFrameItem)>& function = {}) -> type& { return self().onMove(function), *this; } + auto remove(sTabFrameItem item) -> type& { return self().remove(item), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto selected() const -> sTabFrameItem { return self().selected(); } + auto setEdge(Edge edge = Edge::Top) -> type& { return self().setEdge(edge), *this; } +}; + +struct TabFrameItem : sTabFrameItem { + DeclareObject(TabFrameItem) + + auto append(sLayout layout) -> type& { return self().append(layout), *this; } + auto closable() const -> bool { return self().closable(); } + auto icon() const -> image { return self().icon(); } + auto layout() const -> sLayout { return self().layout(); } + auto movable() const -> bool { return self().movable(); } + auto remove(sLayout layout) -> type& { return self().remove(layout), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto selected() const -> bool { return self().selected(); } + auto setClosable(bool closable = true) -> type& { return self().setClosable(closable), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setMovable(bool movable = true) -> type& { return self().setMovable(movable), *this; } + auto setSelected() -> type& { return self().setSelected(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct TextEdit : sTextEdit { + DeclareWidget(TextEdit) + + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto cursorPosition() const -> unsigned { return self().cursorPosition(); } + auto doChange() const -> void { return self().doChange(); } + auto doMove() const -> void { return self().doMove(); } + auto editable() const -> bool { return self().editable(); } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onMove(const function<void ()>& function = {}) -> type& { return self().onMove(function), *this; } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setCursorPosition(unsigned position) -> type& { return self().setCursorPosition(position), *this; } + auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto setWordWrap(bool wordWrap = true) -> type& { return self().setWordWrap(wordWrap), *this; } + auto text() const -> string { return self().text(); } + auto wordWrap() const -> bool { return self().wordWrap(); } +}; + +struct TreeView : sTreeView { + DeclareWidget(TreeView) + + auto append(sTreeViewItem item) -> type& { return self().append(item), *this; } + auto backgroundColor() const -> Color { return self().backgroundColor(); } + auto checkable() const -> bool { return self().checkable(); } + auto collapse() -> type& { return self().collapse(), *this; } + auto doActivate() const -> void { return self().doActivate(); } + auto doChange() const -> void { return self().doChange(); } + auto doContext() const -> void { return self().doContext(); } + auto doToggle(sTreeViewItem item) const -> void { return self().doToggle(item); } + auto expand() -> type& { return self().expand(), *this; } + auto foregroundColor() const -> Color { return self().foregroundColor(); } + auto item(const string& path) const -> sTreeViewItem { return self().item(path); } + auto items() const -> unsigned { return self().items(); } + auto onActivate(const function<void ()>& function = {}) -> type& { return self().onActivate(function), *this; } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto onContext(const function<void ()>& function = {}) -> type& { return self().onContext(function), *this; } + auto onToggle(const function<void (sTreeViewItem)>& function = {}) -> type& { return self().onToggle(function), *this; } + auto remove(sTreeViewItem item) -> type& { return self().remove(item), *this; } + auto reset() -> type& { return self().reset(), *this; } + auto selected() const -> sTreeViewItem { return self().selected(); } + auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; } + auto setCheckable(bool checkable = true) -> type& { return self().setCheckable(checkable), *this; } + auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; } +}; + +struct TreeViewItem : sTreeViewItem { + DeclareObject(TreeViewItem) + + auto append(sTreeViewItem item) -> type& { return self().append(item), *this; } + auto checked() const -> bool { return self().checked(); } + auto icon() const -> image { return self().icon(); } + auto item(const string& path) const -> sTreeViewItem { return self().item(path); } + auto items() const -> unsigned { return self().items(); } + auto path() const -> string { return self().path(); } + auto remove(sTreeViewItem item) -> type& { return self().remove(item), *this; } + auto selected() const -> bool { return self().selected(); } + auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; } + auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; } + auto setSelected() -> type& { return self().setSelected(), *this; } + auto setText(const string& text = "") -> type& { return self().setText(text), *this; } + auto text() const -> string { return self().text(); } +}; + +struct VerticalScroller : sVerticalScroller { + DeclareWidget(VerticalScroller) + + auto doChange() const -> void { return self().doChange(); } + auto length() const -> unsigned { return self().length(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto position() const -> unsigned { return self().position(); } + auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; } + auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; } +}; + +struct VerticalSlider : sVerticalSlider { + DeclareWidget(VerticalSlider) + + auto doChange() const -> void { return self().doChange(); } + auto length() const -> unsigned { return self().length(); } + auto onChange(const function<void ()>& function = {}) -> type& { return self().onChange(function), *this; } + auto position() const -> unsigned { return self().position(); } + auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; } + auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; } +}; + +struct Viewport : sViewport { + DeclareWidget(Viewport) + + auto doDrop(lstring names) const -> void { return self().doDrop(names); } + auto doMouseLeave() const -> void { return self().doMouseLeave(); } + auto doMouseMove(Position position) const -> void { return self().doMouseMove(position); } + auto doMousePress(Mouse::Button button) const -> void { return self().doMousePress(button); } + auto doMouseRelease(Mouse::Button button) const -> void { return self().doMouseRelease(button); } + auto droppable() const -> bool { return self().droppable(); } + auto handle() const -> uintptr_t { return self().handle(); } + auto onDrop(const function<void (lstring)>& function = {}) -> type& { return self().onDrop(function), *this; } + auto onMouseLeave(const function<void ()>& function = {}) -> type& { return self().onMouseLeave(function), *this; } + auto onMouseMove(const function<void (Position)>& function = {}) -> type& { return self().onMouseMove(function), *this; } + auto onMousePress(const function<void (Mouse::Button)>& function = {}) -> type& { return self().onMousePress(function), *this; } + auto onMouseRelease(const function<void (Mouse::Button)>& function = {}) -> type& { return self().onMouseRelease(function), *this; } + auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; } +}; + +using sFixedLayout = shared_pointer<mFixedLayout>; +using sHorizontalLayout = shared_pointer<mHorizontalLayout>; +using sVerticalLayout = shared_pointer<mVerticalLayout>; + +struct FixedLayout : sFixedLayout { + DeclareLayout(FixedLayout) + + auto append(sSizable sizable, Geometry geometry) -> type& { return self().append(sizable, geometry), *this; } +}; + +struct HorizontalLayout : sHorizontalLayout { + DeclareLayout(HorizontalLayout) + + auto append(sSizable sizable, Size size, signed spacing = 5) -> type& { return self().append(sizable, size, spacing), *this; } + auto setAlignment(double alignment = 0.5) -> type& { return self().setAlignment(alignment), *this; } + auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } + auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } +}; + +struct VerticalLayout : sVerticalLayout { + DeclareLayout(VerticalLayout) + + auto append(sSizable sizable, Size size, signed spacing = 5) -> type& { return self().append(sizable, size, spacing), *this; } + auto setAlignment(double alignment = 0.0) -> type& { return self().setAlignment(alignment), *this; } + auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } + auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } +}; + +#undef Declare +#undef DeclareObject +#undef DeclareAction +#undef DeclareSizable +#undef DeclareLayout +#undef DeclareWidget diff --git a/hiro/extension/vertical-layout.cpp b/hiro/extension/vertical-layout.cpp new file mode 100644 index 00000000..1c2c86d1 --- /dev/null +++ b/hiro/extension/vertical-layout.cpp @@ -0,0 +1,127 @@ +auto mVerticalLayout::append(shared_pointer<mSizable> sizable, Size size, signed spacing) -> type& { + properties.append({size.width(), size.height(), spacing < 0 ? settings.spacing : spacing}); + mLayout::append(sizable); + return *this; +} + +auto mVerticalLayout::minimumSize() const -> Size { + signed width = 0, height = 0; + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.width == Size::Minimum || child.width == Size::Maximum) { + width = max(width, sizable(n)->minimumSize().width()); + continue; + } + width = max(width, child.width); + } + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.height == Size::Minimum || child.height == Size::Maximum) { + height += sizable(n)->minimumSize().height(); + } else { + height += child.height; + } + if(&child != &properties.last()) height += child.spacing; + } + + return {settings.margin * 2 + width, settings.margin * 2 + height}; +} + +auto mVerticalLayout::remove(shared_pointer<mSizable> sizable) -> type& { + properties.remove(sizable->offset()); + mLayout::remove(sizable); + return *this; +} + +auto mVerticalLayout::reset() -> type& { + mLayout::reset(); + properties.reset(); + return *this; +} + +auto mVerticalLayout::setAlignment(double alignment) -> type& { + settings.alignment = max(0.0, min(1.0, alignment)); + return *this; +} + +auto mVerticalLayout::setEnabled(bool enabled) -> type& { + mLayout::setEnabled(enabled); + for(auto n : range(sizables())) { + sizable(n)->setEnabled(sizable(n)->enabled(true)); + } + return *this; +} + +auto mVerticalLayout::setFont(const string& font) -> type& { + mLayout::setFont(font); + for(auto n : range(sizables())) { + sizable(n)->setFont(sizable(n)->font(true)); + } + return *this; +} + +auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& { + mLayout::setGeometry(containerGeometry); + + auto properties = this->properties; + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width(); + if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height(); + } + + Geometry geometry = containerGeometry; + geometry.setX (geometry.x() + settings.margin ); + geometry.setY (geometry.y() + settings.margin ); + geometry.setWidth (geometry.width() - settings.margin * 2); + geometry.setHeight(geometry.height() - settings.margin * 2); + + signed minimumHeight = 0, maximumHeightCounter = 0; + for(auto& child : properties) { + if(child.height == Size::Maximum) maximumHeightCounter++; + if(child.height != Size::Maximum) minimumHeight += child.height; + if(&child != &properties.last()) minimumHeight += child.spacing; + } + + for(auto& child : properties) { + if(child.width == Size::Maximum) child.width = geometry.width(); + if(child.height == Size::Maximum) child.height = (geometry.height() - minimumHeight) / maximumHeightCounter; + } + + signed maximumWidth = 0; + for(auto& child : properties) maximumWidth = max(maximumWidth, child.width); + + for(auto n : range(sizables())) { + auto& child = properties[sizable(n)->offset()]; + signed pivot = (maximumWidth - child.width) * settings.alignment; + Geometry childGeometry = {geometry.x() + pivot, geometry.y(), child.width, child.height}; + if(childGeometry.width() < 1) childGeometry.setWidth (1); + if(childGeometry.height() < 1) childGeometry.setHeight(1); + sizable(n)->setGeometry(childGeometry); + + geometry.setY (geometry.y() + child.height + child.spacing); + geometry.setHeight(geometry.height() - child.height + child.spacing); + } + + return *this; +} + +auto mVerticalLayout::setMargin(signed margin) -> type& { + settings.margin = margin; + return *this; +} + +auto mVerticalLayout::setSpacing(signed spacing) -> type& { + settings.spacing = spacing; + return *this; +} + +auto mVerticalLayout::setVisible(bool visible) -> type& { + mLayout::setVisible(visible); + for(auto n : range(sizables())) { + sizable(n)->setVisible(sizable(n)->visible(true)); + } + return *this; +} diff --git a/hiro/extension/vertical-layout.hpp b/hiro/extension/vertical-layout.hpp new file mode 100644 index 00000000..e3ec666c --- /dev/null +++ b/hiro/extension/vertical-layout.hpp @@ -0,0 +1,30 @@ +struct mVerticalLayout : mLayout { + using type = mVerticalLayout; + using mLayout::append; + using mLayout::remove; + + auto append(nall::shared_pointer<mSizable> sizable, Size size, signed spacing = 5) -> type&; + auto minimumSize() const -> Size override; + auto remove(nall::shared_pointer<mSizable> sizable) -> type& override; + auto reset() -> type& override; + auto setAlignment(double alignment = 0.0) -> type&; + auto setEnabled(bool enabled = true) -> type& override; + auto setFont(const nall::string& font = "") -> type& override; + auto setGeometry(Geometry geometry) -> type& override; + auto setMargin(signed margin = 0) -> type&; + auto setSpacing(signed spacing = 5) -> type&; + auto setVisible(bool visible = true) -> type& override; + + struct Settings { + double alignment = 0.0; + signed margin = 0; + signed spacing = 5; + } settings; + + struct Properties { + signed width; + signed height; + signed spacing; + }; + nall::vector<Properties> properties; +}; diff --git a/phoenix/gtk/action/action.cpp b/hiro/gtk/action/action.cpp similarity index 56% rename from phoenix/gtk/action/action.cpp rename to hiro/gtk/action/action.cpp index 978b9747..f28a97a7 100644 --- a/phoenix/gtk/action/action.cpp +++ b/hiro/gtk/action/action.cpp @@ -1,22 +1,26 @@ -namespace phoenix { +namespace hiro { -void pAction::setEnabled(bool enabled) { +auto pAction::construct() -> void { +} + +auto pAction::destruct() -> void { +} + +auto pAction::setEnabled(bool enabled) -> void { gtk_widget_set_sensitive(widget, enabled); } -void pAction::setVisible(bool visible) { +auto pAction::setFont(const string& font) -> void { + pFont::setFont(widget, font); +} + +auto pAction::setVisible(bool visible) -> void { gtk_widget_set_visible(widget, visible); } -void pAction::constructor() { -} - -void pAction::orphan() { -} - //GTK+ uses _ for mnemonics, __ for _ //transform so that & is used for mnemonics, && for & -string pAction::mnemonic(string text) { +auto pAction::_mnemonic(string text) -> string { text.transform("&_", "\x01\x02"); text.replace("\x01\x01", "&"); text.transform("\x01", "_"); @@ -24,8 +28,4 @@ string pAction::mnemonic(string text) { return text; } -void pAction::setFont(string font) { - pFont::setFont(widget, font); -} - } diff --git a/hiro/gtk/action/action.hpp b/hiro/gtk/action/action.hpp new file mode 100644 index 00000000..2a28d5a3 --- /dev/null +++ b/hiro/gtk/action/action.hpp @@ -0,0 +1,15 @@ +namespace hiro { + +struct pAction : pObject { + Declare(Action, Object) + + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setVisible(bool visible) -> void override; + + auto _mnemonic(string text) -> string; + + GtkWidget* widget = nullptr; +}; + +} diff --git a/hiro/gtk/action/menu-check-item.cpp b/hiro/gtk/action/menu-check-item.cpp new file mode 100644 index 00000000..e262cf8d --- /dev/null +++ b/hiro/gtk/action/menu-check-item.cpp @@ -0,0 +1,34 @@ +namespace hiro { + +static auto MenuCheckItem_toggle(GtkCheckMenuItem* gtkCheckMenuItem, pMenuCheckItem* p) -> void { + p->state().checked = gtk_check_menu_item_get_active(gtkCheckMenuItem); + if(!p->locked()) p->self().doToggle(); +} + +auto pMenuCheckItem::construct() -> void { + widget = gtk_check_menu_item_new_with_mnemonic(""); + setChecked(state().checked); + setText(state().text); + g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(MenuCheckItem_toggle), (gpointer)this); +} + +auto pMenuCheckItem::destruct() -> void { + gtk_widget_destroy(widget); +} + +auto pMenuCheckItem::orphan() -> void { + destruct(); + construct(); +} + +auto pMenuCheckItem::setChecked(bool checked) -> void { + lock(); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), checked); + unlock(); +} + +auto pMenuCheckItem::setText(const string& text) -> void { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _mnemonic(text)); +} + +} diff --git a/hiro/gtk/action/menu-check-item.hpp b/hiro/gtk/action/menu-check-item.hpp new file mode 100644 index 00000000..b342de84 --- /dev/null +++ b/hiro/gtk/action/menu-check-item.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pMenuCheckItem : pAction { + Declare(MenuCheckItem, Action) + auto orphan() -> void; + + auto setChecked(bool checked) -> void; + auto setText(const string& text) -> void; +}; + +} diff --git a/hiro/gtk/action/menu-item.cpp b/hiro/gtk/action/menu-item.cpp new file mode 100644 index 00000000..39d1dba4 --- /dev/null +++ b/hiro/gtk/action/menu-item.cpp @@ -0,0 +1,30 @@ +namespace hiro { + +static auto MenuItem_activate(GtkMenuItem*, pMenuItem* p) -> void { + p->self().doActivate(); +} + +auto pMenuItem::construct() -> void { + widget = gtk_image_menu_item_new_with_mnemonic(""); + g_signal_connect(G_OBJECT(widget), "activate", G_CALLBACK(MenuItem_activate), (gpointer)this); + setText(state().text); +} + +auto pMenuItem::destruct() -> void { + if(widget) gtk_widget_destroy(widget), widget = nullptr; +} + +auto pMenuItem::setIcon(const image& icon) -> void { + if(icon) { + GtkImage* gtkImage = CreateImage(icon, true); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage); + } else { + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr); + } +} + +auto pMenuItem::setText(const string& text) -> void { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _mnemonic(text)); +} + +} diff --git a/hiro/gtk/action/menu-item.hpp b/hiro/gtk/action/menu-item.hpp new file mode 100644 index 00000000..bf2e13db --- /dev/null +++ b/hiro/gtk/action/menu-item.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pMenuItem : pAction { + Declare(MenuItem, Action) + + auto setIcon(const image& icon) -> void; + auto setText(const string& text) -> void; +}; + +} diff --git a/hiro/gtk/action/menu-radio-item.cpp b/hiro/gtk/action/menu-radio-item.cpp new file mode 100644 index 00000000..a3f05076 --- /dev/null +++ b/hiro/gtk/action/menu-radio-item.cpp @@ -0,0 +1,75 @@ +namespace hiro { + +static auto MenuRadioItem_activate(GtkCheckMenuItem* gtkCheckMenuItem, pMenuRadioItem* p) -> void { + p->_doActivate(); +} + +auto pMenuRadioItem::construct() -> void { + widget = gtk_radio_menu_item_new_with_mnemonic(0, ""); + setGroup(state().group); + setText(state().text); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) { + if(item->self()) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->self()->widget), item->checked()); + } + } + g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(MenuRadioItem_activate), (gpointer)this); +} + +auto pMenuRadioItem::destruct() -> void { + if(widget) gtk_widget_destroy(widget), widget = nullptr; +} + +auto pMenuRadioItem::setChecked() -> void { + _parent().lock(); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) { + if(item->self()) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->self()->widget), false); + } + } + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), true); + _parent().unlock(); +} + +auto pMenuRadioItem::setGroup(const vector<shared_pointer_weak<mMenuRadioItem>>& group) -> void { + _parent().lock(); + shared_pointer<mMenuRadioItem> first; + for(auto& weak : group) { + if(!first) { + first = weak.acquire(); + continue; + } + if(auto item = weak.acquire()) { + if(item->self() && first->self()) { + GSList* currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(first->self()->widget)); + if(currentGroup != gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item->self()->widget))) { + gtk_radio_menu_item_set_group(GTK_RADIO_MENU_ITEM(item->self()->widget), currentGroup); + } + } + } + } + _parent().unlock(); +} + +auto pMenuRadioItem::setText(const string& text) -> void { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _mnemonic(text)); +} + +auto pMenuRadioItem::_doActivate() -> void { + if(!_parent().locked()) { + bool wasChecked = state().checked; + self().setChecked(); + if(!wasChecked) self().doActivate(); + } +} + +auto pMenuRadioItem::_parent() -> pMenuRadioItem& { + if(state().group.size()) { + if(auto item = state().group.first().acquire()) { + if(item->self()) return *item->self(); + } + } + return *this; +} + +} diff --git a/hiro/gtk/action/menu-radio-item.hpp b/hiro/gtk/action/menu-radio-item.hpp new file mode 100644 index 00000000..f129c1a6 --- /dev/null +++ b/hiro/gtk/action/menu-radio-item.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pMenuRadioItem : pAction { + Declare(MenuRadioItem, Action) + + auto setChecked() -> void; + auto setGroup(const vector<shared_pointer_weak<mMenuRadioItem>>& group) -> void; + auto setText(const string& text) -> void; + + auto _doActivate() -> void; + auto _parent() -> pMenuRadioItem&; +}; + +} diff --git a/hiro/gtk/action/menu-separator.cpp b/hiro/gtk/action/menu-separator.cpp new file mode 100644 index 00000000..1344e93c --- /dev/null +++ b/hiro/gtk/action/menu-separator.cpp @@ -0,0 +1,11 @@ +namespace hiro { + +auto pMenuSeparator::construct() -> void { + widget = gtk_separator_menu_item_new(); +} + +auto pMenuSeparator::destruct() -> void { + if(widget) gtk_widget_destroy(widget), widget = nullptr; +} + +} diff --git a/hiro/gtk/action/menu-separator.hpp b/hiro/gtk/action/menu-separator.hpp new file mode 100644 index 00000000..5bf18a62 --- /dev/null +++ b/hiro/gtk/action/menu-separator.hpp @@ -0,0 +1,7 @@ +namespace hiro { + +struct pMenuSeparator : pAction { + Declare(MenuSeparator, Action) +}; + +} diff --git a/hiro/gtk/action/menu.cpp b/hiro/gtk/action/menu.cpp new file mode 100644 index 00000000..527a84ff --- /dev/null +++ b/hiro/gtk/action/menu.cpp @@ -0,0 +1,48 @@ +namespace hiro { + +auto pMenu::construct() -> void { + gtkMenu = gtk_menu_new(); + widget = gtk_image_menu_item_new_with_mnemonic(""); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), gtkMenu); + setText(state().text); + + for(auto& action : state().actions) append(*action); +} + +auto pMenu::destruct() -> void { + gtk_widget_destroy(gtkMenu); + gtk_widget_destroy(widget); +} + +auto pMenu::append(sAction action) -> void { + if(action->self()) { + gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), action->self()->widget); + action->self()->setFont(action->font(true)); + action->self()->setVisible(action->visible(true)); + } +} + +auto pMenu::remove(sAction action) -> void { +} + +auto pMenu::setFont(const string& font) -> void { + pAction::setFont(font); + for(auto& action : state().actions) { + if(action->self()) action->self()->setFont(action->font(true)); + } +} + +auto pMenu::setIcon(const image& icon) -> void { + if(icon) { + GtkImage* gtkImage = CreateImage(icon, true); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage); + } else { + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr); + } +} + +auto pMenu::setText(const string& text) -> void { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _mnemonic(text)); +} + +} diff --git a/hiro/gtk/action/menu.hpp b/hiro/gtk/action/menu.hpp new file mode 100644 index 00000000..c0e199a7 --- /dev/null +++ b/hiro/gtk/action/menu.hpp @@ -0,0 +1,15 @@ +namespace hiro { + +struct pMenu : pAction { + Declare(Menu, Action) + + auto append(sAction action) -> void; + auto remove(sAction action) -> void; + auto setFont(const string& font) -> void override; + auto setIcon(const image& icon) -> void; + auto setText(const string& text) -> void; + + GtkWidget* gtkMenu = nullptr; +}; + +} diff --git a/hiro/gtk/application.cpp b/hiro/gtk/application.cpp new file mode 100644 index 00000000..14783989 --- /dev/null +++ b/hiro/gtk/application.cpp @@ -0,0 +1,84 @@ +namespace hiro { + +XlibDisplay* pApplication::display = nullptr; + +void pApplication::run() { + if(Application::state.onMain) { + while(Application::state.quit == false) { + processEvents(); + Application::doMain(); + } + } else { + gtk_main(); + } +} + +bool pApplication::pendingEvents() { + return gtk_events_pending(); +} + +void pApplication::processEvents() { + while(pendingEvents()) gtk_main_iteration_do(false); +} + +void pApplication::quit() { + //if gtk_main() was invoked, call gtk_main_quit() + if(gtk_main_level()) gtk_main_quit(); +} + +void pApplication::initialize() { + display = XOpenDisplay(nullptr); + + settings = new Settings; + settings->load(); + + //set WM_CLASS to Application::name() + if(Application::state.name) gdk_set_program_class(Application::state.name); + + #if 1 + int argc = 1; + char* argv[] = {new char[8], nullptr}; + strcpy(argv[0], "phoenix"); + #else + //--g-fatal-warnings will force a trap on Gtk-CRITICAL errors + //this allows gdb to perform a backtrace to find error origin point + int argc = 2; + char* argv[] = {new char[8], new char[19], nullptr}; + strcpy(argv[0], "phoenix"); + strcpy(argv[1], "--g-fatal-warnings"); + #endif + char** argvp = argv; + gtk_init(&argc, &argvp); + + GtkSettings* gtkSettings = gtk_settings_get_default(); + g_object_set(gtkSettings, "gtk-button-images", true, nullptr); + + gtk_rc_parse_string(R"( + style "PhoenixWindow" + { + GtkWindow::resize-grip-width = 0 + GtkWindow::resize-grip-height = 0 + } + class "GtkWindow" style "PhoenixWindow" + + style "PhoenixTreeView" + { + GtkTreeView::vertical-separator = 0 + } + class "GtkTreeView" style "PhoenixTreeView" + + style "PhoenixTabFrameCloseButton" + { + GtkWidget::focus-line-width = 0 + GtkWidget::focus-padding = 0 + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outer-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 1, 0, 0} + } + widget_class "*.<GtkNotebook>.<GtkHBox>.<GtkButton>" style "PhoenixTabFrameCloseButton" + )"); + + pKeyboard::initialize(); +} + +} diff --git a/hiro/gtk/application.hpp b/hiro/gtk/application.hpp new file mode 100644 index 00000000..4fd5d573 --- /dev/null +++ b/hiro/gtk/application.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pApplication { + static XlibDisplay* display; + + static void run(); + static bool pendingEvents(); + static void processEvents(); + static void quit(); + + static void initialize(); +}; + +} diff --git a/phoenix/gtk/browser-window.cpp b/hiro/gtk/browser-window.cpp similarity index 78% rename from phoenix/gtk/browser-window.cpp rename to hiro/gtk/browser-window.cpp index e2c9b5c5..1ca5ef80 100644 --- a/phoenix/gtk/browser-window.cpp +++ b/hiro/gtk/browser-window.cpp @@ -1,21 +1,21 @@ -namespace phoenix { +namespace hiro { static void BrowserWindow_addFilters(GtkWidget* dialog, lstring filters) { for(auto& filter : filters) { GtkFileFilter* gtkFilter = gtk_file_filter_new(); gtk_file_filter_set_name(gtkFilter, filter); - lstring patterns = filter.split<1>("(")(1).rtrim<1>(")").split(","); - for(auto& pattern : patterns) gtk_file_filter_add_pattern(gtkFilter, pattern.strip()); + lstring patterns = filter.split<1>("(")(1).rtrim(")").split(",").strip(); + for(auto& pattern : patterns) gtk_file_filter_add_pattern(gtkFilter, pattern); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), gtkFilter); } } -string pBrowserWindow::directory(BrowserWindow::State& state) { +auto pBrowserWindow::directory(BrowserWindow::State& state) -> string { string name; GtkWidget* dialog = gtk_file_chooser_dialog_new( state.title ? state.title : "Select Directory", - state.parent ? GTK_WINDOW(state.parent->p.widget) : (GtkWindow*)nullptr, + state.parent && state.parent->self() ? GTK_WINDOW(state.parent->self()->widget) : (GtkWindow*)nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, @@ -35,12 +35,12 @@ string pBrowserWindow::directory(BrowserWindow::State& state) { return name; } -string pBrowserWindow::open(BrowserWindow::State& state) { +auto pBrowserWindow::open(BrowserWindow::State& state) -> string { string name; GtkWidget* dialog = gtk_file_chooser_dialog_new( state.title ? state.title : "Open File", - state.parent ? GTK_WINDOW(state.parent->p.widget) : (GtkWindow*)nullptr, + state.parent && state.parent->self() ? GTK_WINDOW(state.parent->self()->widget) : (GtkWindow*)nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, @@ -60,12 +60,12 @@ string pBrowserWindow::open(BrowserWindow::State& state) { return name; } -string pBrowserWindow::save(BrowserWindow::State& state) { +auto pBrowserWindow::save(BrowserWindow::State& state) -> string { string name; GtkWidget* dialog = gtk_file_chooser_dialog_new( state.title ? state.title : "Save File", - state.parent ? GTK_WINDOW(state.parent->p.widget) : (GtkWindow*)nullptr, + state.parent && state.parent->self() ? GTK_WINDOW(state.parent->self()->widget) : (GtkWindow*)nullptr, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, diff --git a/hiro/gtk/browser-window.hpp b/hiro/gtk/browser-window.hpp new file mode 100644 index 00000000..964acea4 --- /dev/null +++ b/hiro/gtk/browser-window.hpp @@ -0,0 +1,9 @@ +namespace hiro { + +struct pBrowserWindow { + static auto directory(BrowserWindow::State& state) -> string; + static auto open(BrowserWindow::State& state) -> string; + static auto save(BrowserWindow::State& state) -> string; +}; + +} diff --git a/phoenix/gtk/desktop.cpp b/hiro/gtk/desktop.cpp similarity index 88% rename from phoenix/gtk/desktop.cpp rename to hiro/gtk/desktop.cpp index 700d081d..25b03fee 100644 --- a/phoenix/gtk/desktop.cpp +++ b/hiro/gtk/desktop.cpp @@ -1,4 +1,4 @@ -namespace phoenix { +namespace hiro { Size pDesktop::size() { return { @@ -27,7 +27,7 @@ Geometry pDesktop::workspace() { if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) { unsigned long *workarea = (unsigned long*)data; - return {(signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3]}; + return {(signed)workarea[0], (signed)workarea[1], (signed)workarea[2], (signed)workarea[3]}; } return { diff --git a/hiro/gtk/desktop.hpp b/hiro/gtk/desktop.hpp new file mode 100644 index 00000000..d063450a --- /dev/null +++ b/hiro/gtk/desktop.hpp @@ -0,0 +1,8 @@ +namespace hiro { + +struct pDesktop { + static Size size(); + static Geometry workspace(); +}; + +} diff --git a/phoenix/gtk/font.cpp b/hiro/gtk/font.cpp similarity index 95% rename from phoenix/gtk/font.cpp rename to hiro/gtk/font.cpp index 41232cbd..fcd6c23f 100644 --- a/phoenix/gtk/font.cpp +++ b/hiro/gtk/font.cpp @@ -1,4 +1,4 @@ -namespace phoenix { +namespace hiro { string pFont::serif(unsigned size, string style) { if(size == 0) size = 8; @@ -25,9 +25,7 @@ Size pFont::size(string font, string text) { } PangoFontDescription* pFont::create(string description) { - lstring part; - part.split<2>(",", description); - for(auto& item : part) item.trim(" "); + lstring part = description.split<2>(",").strip(); string family = "Sans"; unsigned size = 8u; diff --git a/hiro/gtk/font.hpp b/hiro/gtk/font.hpp new file mode 100644 index 00000000..8dbd17e9 --- /dev/null +++ b/hiro/gtk/font.hpp @@ -0,0 +1,16 @@ +namespace hiro { + +struct pFont { + static string serif(unsigned size, string style); + static string sans(unsigned size, string style); + static string monospace(unsigned size, string style); + static Size size(string font, string text); + + static PangoFontDescription* create(string description); + static void free(PangoFontDescription* font); + static Size size(PangoFontDescription* font, string text); + static void setFont(GtkWidget* widget, string font); + static void setFont(GtkWidget* widget, gpointer font); +}; + +} diff --git a/phoenix/gtk/header.hpp b/hiro/gtk/header.hpp similarity index 56% rename from phoenix/gtk/header.hpp rename to hiro/gtk/header.hpp index 036cabde..8e691ab5 100644 --- a/phoenix/gtk/header.hpp +++ b/hiro/gtk/header.hpp @@ -1,8 +1,11 @@ #include <nall/xorg/guard.hpp> -#include <gtk/gtk.h> #include <gdk/gdk.h> #include <gdk/gdkx.h> #include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> +#include <gtksourceview/gtksourceview.h> +#include <gtksourceview/gtksourcelanguagemanager.h> +#include <gtksourceview/gtksourcestyleschememanager.h> #include <cairo.h> #include <X11/Xatom.h> #include <nall/xorg/guard.hpp> diff --git a/hiro/gtk/hotkey.cpp b/hiro/gtk/hotkey.cpp new file mode 100644 index 00000000..73879ddb --- /dev/null +++ b/hiro/gtk/hotkey.cpp @@ -0,0 +1,9 @@ +namespace hiro { + +auto pHotkey::construct() -> void { +} + +auto pHotkey::destruct() -> void { +} + +} diff --git a/hiro/gtk/hotkey.hpp b/hiro/gtk/hotkey.hpp new file mode 100644 index 00000000..4f476cdc --- /dev/null +++ b/hiro/gtk/hotkey.hpp @@ -0,0 +1,7 @@ +namespace hiro { + +struct pHotkey : pObject { + Declare(Hotkey, Object) +}; + +} diff --git a/hiro/gtk/keyboard.cpp b/hiro/gtk/keyboard.cpp new file mode 100644 index 00000000..0223ccf3 --- /dev/null +++ b/hiro/gtk/keyboard.cpp @@ -0,0 +1,344 @@ +namespace hiro { + +auto pKeyboard::poll() -> vector<bool> { + vector<bool> result; + char state[256]; + XQueryKeymap(pApplication::display, state); + for(auto& code : settings->keycodes) { + result.append(_pressed(state, code)); + } + return result; +} + +auto pKeyboard::pressed(unsigned code) -> bool { + char state[256]; + XQueryKeymap(pApplication::display, state); + return _pressed(state, code); +} + +auto pKeyboard::_pressed(char* state, uint16_t code) -> bool { + uint8_t lo = code >> 0; + uint8_t hi = code >> 8; + if(lo && state[lo >> 3] & (1 << (lo & 7))) return true; + if(hi && state[hi >> 3] & (1 << (hi & 7))) return true; + return false; +} + +auto pKeyboard::_translate(unsigned code) -> signed { + switch(code) { + case GDK_Escape: return 0; + case GDK_F1: return 0; + case GDK_F2: return 0; + case GDK_F3: return 0; + case GDK_F4: return 0; + case GDK_F5: return 0; + case GDK_F6: return 0; + case GDK_F7: return 0; + case GDK_F8: return 0; + case GDK_F9: return 0; + case GDK_F10: return 0; + case GDK_F11: return 0; + case GDK_F12: return 0; + + case GDK_Print: return 0; + case GDK_Scroll_Lock: return 0; + case GDK_Pause: return 0; + + case GDK_Insert: return 0; + case GDK_Delete: return 0; + case GDK_Home: return 0; + case GDK_End: return 0; + case GDK_Prior: return 0; + case GDK_Next: return 0; + + case GDK_Up: return 0; + case GDK_Down: return 0; + case GDK_Left: return 0; + case GDK_Right: return 0; + + case GDK_grave: return '`'; + case GDK_1: return '1'; + case GDK_2: return '2'; + case GDK_3: return '3'; + case GDK_4: return '4'; + case GDK_5: return '5'; + case GDK_6: return '6'; + case GDK_7: return '7'; + case GDK_8: return '8'; + case GDK_9: return '9'; + case GDK_0: return '0'; + case GDK_minus: return '-'; + case GDK_equal: return '='; + case GDK_BackSpace: return '\b'; + + case GDK_asciitilde: return '~'; + case GDK_exclam: return '!'; + case GDK_at: return '@'; + case GDK_numbersign: return '#'; + case GDK_dollar: return '$'; + case GDK_percent: return '%'; + case GDK_asciicircum: return '^'; + case GDK_ampersand: return '&'; + case GDK_asterisk: return '*'; + case GDK_parenleft: return '('; + case GDK_parenright: return ')'; + case GDK_underscore: return '_'; + case GDK_plus: return '+'; + + case GDK_Tab: return '\t'; + case GDK_Caps_Lock: return 0; + case GDK_Return: return '\n'; + case GDK_Shift_L: return 0; + case GDK_Shift_R: return 0; + case GDK_Control_L: return 0; + case GDK_Control_R: return 0; + case GDK_Alt_L: return 0; + case GDK_Alt_R: return 0; + case GDK_Super_L: return 0; + case GDK_Super_R: return 0; + case GDK_Menu: return 0; + case GDK_space: return ' '; + + case GDK_bracketleft: return '['; + case GDK_bracketright: return ']'; + case GDK_backslash: return '\\'; + case GDK_semicolon: return ';'; + case GDK_apostrophe: return '\''; + case GDK_comma: return ','; + case GDK_period: return '.'; + case GDK_slash: return '/'; + + case GDK_braceleft: return '{'; + case GDK_braceright: return '}'; + case GDK_bar: return '|'; + case GDK_colon: return ':'; + case GDK_quotedbl: return '\"'; + case GDK_less: return '<'; + case GDK_greater: return '>'; + case GDK_question: return '?'; + + case GDK_A: return 'A'; + case GDK_B: return 'B'; + case GDK_C: return 'C'; + case GDK_D: return 'D'; + case GDK_E: return 'E'; + case GDK_F: return 'F'; + case GDK_G: return 'G'; + case GDK_H: return 'H'; + case GDK_I: return 'I'; + case GDK_J: return 'J'; + case GDK_K: return 'K'; + case GDK_L: return 'L'; + case GDK_M: return 'M'; + case GDK_N: return 'N'; + case GDK_O: return 'O'; + case GDK_P: return 'P'; + case GDK_Q: return 'Q'; + case GDK_R: return 'R'; + case GDK_S: return 'S'; + case GDK_T: return 'T'; + case GDK_U: return 'U'; + case GDK_V: return 'V'; + case GDK_W: return 'W'; + case GDK_X: return 'X'; + case GDK_Y: return 'Y'; + case GDK_Z: return 'Z'; + + case GDK_a: return 'a'; + case GDK_b: return 'b'; + case GDK_c: return 'c'; + case GDK_d: return 'd'; + case GDK_e: return 'e'; + case GDK_f: return 'f'; + case GDK_g: return 'g'; + case GDK_h: return 'h'; + case GDK_i: return 'i'; + case GDK_j: return 'j'; + case GDK_k: return 'k'; + case GDK_l: return 'l'; + case GDK_m: return 'm'; + case GDK_n: return 'n'; + case GDK_o: return 'o'; + case GDK_p: return 'p'; + case GDK_q: return 'q'; + case GDK_r: return 'r'; + case GDK_s: return 's'; + case GDK_t: return 't'; + case GDK_u: return 'u'; + case GDK_v: return 'v'; + case GDK_w: return 'w'; + case GDK_x: return 'x'; + case GDK_y: return 'y'; + case GDK_z: return 'z'; + + case GDK_Num_Lock: return 0; + case GDK_KP_Divide: return '/'; + case GDK_KP_Multiply: return '*'; + case GDK_KP_Subtract: return '-'; + case GDK_KP_Add: return '+'; + case GDK_KP_Enter: return '\n'; + case GDK_KP_Decimal: return '.'; + + case GDK_KP_1: return '1'; + case GDK_KP_2: return '2'; + case GDK_KP_3: return '3'; + case GDK_KP_4: return '4'; + case GDK_KP_5: return '5'; + case GDK_KP_6: return '6'; + case GDK_KP_7: return '7'; + case GDK_KP_8: return '8'; + case GDK_KP_9: return '9'; + case GDK_KP_0: return '0'; + + case GDK_KP_Home: return 0; + case GDK_KP_End: return 0; + case GDK_KP_Page_Up: return 0; + case GDK_KP_Page_Down: return 0; + case GDK_KP_Up: return 0; + case GDK_KP_Down: return 0; + case GDK_KP_Left: return 0; + case GDK_KP_Right: return 0; + case GDK_KP_Begin: return 0; + case GDK_KP_Insert: return 0; + case GDK_KP_Delete: return 0; + } + + return 0; +} + +auto pKeyboard::initialize() -> void { + auto append = [](unsigned lo, unsigned hi = 0) { + lo = lo ? (uint8_t)XKeysymToKeycode(pApplication::display, lo) : 0; + hi = hi ? (uint8_t)XKeysymToKeycode(pApplication::display, hi) : 0; + settings->keycodes.append(lo | (hi << 8)); + }; + + #define map(name, ...) if(key == name) { append(__VA_ARGS__); continue; } + for(auto& key : Keyboard::keys) { + map("Escape", XK_Escape); + map("F1", XK_F1); + map("F2", XK_F2); + map("F3", XK_F3); + map("F4", XK_F4); + map("F5", XK_F5); + map("F6", XK_F6); + map("F7", XK_F7); + map("F8", XK_F8); + map("F9", XK_F9); + map("F10", XK_F10); + map("F11", XK_F11); + map("F12", XK_F12); + + map("PrintScreen", XK_Print); + map("ScrollLock", XK_Scroll_Lock); + map("Pause", XK_Pause); + + map("Insert", XK_Insert); + map("Delete", XK_Delete); + map("Home", XK_Home); + map("End", XK_End); + map("PageUp", XK_Prior); + map("PageDown", XK_Next); + + map("Up", XK_Up); + map("Down", XK_Down); + map("Left", XK_Left); + map("Right", XK_Right); + + map("Grave", XK_asciitilde); + map("1", XK_1); + map("2", XK_2); + map("3", XK_3); + map("4", XK_4); + map("5", XK_5); + map("6", XK_6); + map("7", XK_7); + map("8", XK_8); + map("9", XK_9); + map("0", XK_0); + map("Dash", XK_minus); + map("Equal", XK_equal); + map("Backspace", XK_BackSpace); + + map("Tab", XK_Tab); + map("CapsLock", XK_Caps_Lock); + map("LeftEnter", XK_Return); + map("LeftShift", XK_Shift_L); + map("RightShift", XK_Shift_R); + map("LeftControl", XK_Control_L); + map("RightControl", XK_Control_R); + map("LeftAlt", XK_Alt_L); + map("RightAlt", XK_Alt_R); + map("LeftSuper", XK_Super_L); + map("RightSuper", XK_Super_R); + map("Menu", XK_Menu); + map("Space", XK_space); + + map("OpenBracket", XK_bracketleft); + map("CloseBracket", XK_bracketright); + map("Backslash", XK_backslash); + map("Semicolon", XK_semicolon); + map("Apostrophe", XK_apostrophe); + map("Comma", XK_comma); + map("Period", XK_period); + map("Slash", XK_slash); + + map("A", XK_A); + map("B", XK_B); + map("C", XK_C); + map("D", XK_D); + map("E", XK_E); + map("F", XK_F); + map("G", XK_G); + map("H", XK_H); + map("I", XK_I); + map("J", XK_J); + map("K", XK_K); + map("L", XK_L); + map("M", XK_M); + map("N", XK_N); + map("O", XK_O); + map("P", XK_P); + map("Q", XK_Q); + map("R", XK_R); + map("S", XK_S); + map("T", XK_T); + map("U", XK_U); + map("V", XK_V); + map("W", XK_W); + map("X", XK_X); + map("Y", XK_Y); + map("Z", XK_Z); + + map("NumLock", XK_Num_Lock); + map("Divide", XK_KP_Divide); + map("Multiply", XK_KP_Multiply); + map("Subtract", XK_KP_Subtract); + map("Add", XK_KP_Add); + map("RightEnter", XK_KP_Enter); + map("Point", XK_KP_Decimal); + + map("One", XK_KP_1); + map("Two", XK_KP_2); + map("Three", XK_KP_3); + map("Four", XK_KP_4); + map("Five", XK_KP_5); + map("Six", XK_KP_6); + map("Seven", XK_KP_7); + map("Eight", XK_KP_8); + map("Nine", XK_KP_9); + map("Zero", XK_KP_0); + + map("Shift", XK_Shift_L, XK_Shift_R); + map("Control", XK_Control_L, XK_Control_R); + map("Alt", XK_Alt_L, XK_Alt_R); + map("Super", XK_Super_L, XK_Super_R); + map("Enter", XK_Return, XK_KP_Enter); + + print("[phoenix/gtk] error: unhandled key: ", key, "\n"); + append(0); + } + #undef map +} + +} diff --git a/hiro/gtk/keyboard.hpp b/hiro/gtk/keyboard.hpp new file mode 100644 index 00000000..06e5387c --- /dev/null +++ b/hiro/gtk/keyboard.hpp @@ -0,0 +1,13 @@ +namespace hiro { + +struct pKeyboard { + static auto poll() -> vector<bool>; + static auto pressed(unsigned code) -> bool; + + static auto _pressed(char* state, uint16_t code) -> bool; + static auto _translate(unsigned code) -> signed; + + static auto initialize() -> void; +}; + +} diff --git a/hiro/gtk/layout.cpp b/hiro/gtk/layout.cpp new file mode 100644 index 00000000..607b0cf2 --- /dev/null +++ b/hiro/gtk/layout.cpp @@ -0,0 +1,29 @@ +namespace hiro { + +auto pLayout::construct() -> void { + for(auto& sizable : state().sizables) sizable->construct(); +} + +auto pLayout::destruct() -> void { + for(auto& sizable : state().sizables) sizable->destruct(); +} + +auto pLayout::setEnabled(bool enabled) -> void { + for(auto& sizable : state().sizables) { + if(sizable->self()) sizable->self()->setEnabled(sizable->enabled(true)); + } +} + +auto pLayout::setFont(const string& font) -> void { + for(auto& sizable : state().sizables) { + if(sizable->self()) sizable->self()->setFont(sizable->font(true)); + } +} + +auto pLayout::setVisible(bool visible) -> void { + for(auto& sizable : state().sizables) { + if(sizable->self()) sizable->self()->setVisible(sizable->visible(true)); + } +} + +} diff --git a/hiro/gtk/layout.hpp b/hiro/gtk/layout.hpp new file mode 100644 index 00000000..f77bfc84 --- /dev/null +++ b/hiro/gtk/layout.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pLayout : pSizable { + Declare(Layout, Sizable) + + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setVisible(bool visible) -> void override; +}; + +} diff --git a/hiro/gtk/menu-bar.cpp b/hiro/gtk/menu-bar.cpp new file mode 100644 index 00000000..94127d2d --- /dev/null +++ b/hiro/gtk/menu-bar.cpp @@ -0,0 +1,45 @@ +namespace hiro { + +auto pMenuBar::construct() -> void { +} + +auto pMenuBar::destruct() -> void { +} + +auto pMenuBar::append(shared_pointer<mMenu> menu) -> void { + if(auto parent = _parent()) { + parent->_append(*menu); + if(menu->self()) { + menu->self()->setFont(menu->font(true)); + menu->self()->setVisible(menu->visible(true)); + } + } +} + +auto pMenuBar::remove(shared_pointer<mMenu> menu) -> void { +} + +auto pMenuBar::setEnabled(bool enabled) -> void { + if(auto parent = _parent()) { + parent->_setMenuEnabled(enabled); + } +} + +auto pMenuBar::setFont(const string& font) -> void { + if(auto parent = _parent()) { + parent->_setMenuFont(font); + } +} + +auto pMenuBar::setVisible(bool visible) -> void { + if(auto parent = _parent()) { + parent->_setMenuVisible(visible); + } +} + +auto pMenuBar::_parent() -> pWindow* { + if(auto parent = self().parentWindow()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/menu-bar.hpp b/hiro/gtk/menu-bar.hpp new file mode 100644 index 00000000..7c1897cf --- /dev/null +++ b/hiro/gtk/menu-bar.hpp @@ -0,0 +1,15 @@ +namespace hiro { + +struct pMenuBar : pObject { + Declare(MenuBar, Object) + + auto append(shared_pointer<mMenu> menu) -> void; + auto remove(shared_pointer<mMenu> menu) -> void; + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setVisible(bool visible) -> void override; + + auto _parent() -> pWindow*; +}; + +} diff --git a/phoenix/gtk/message-window.cpp b/hiro/gtk/message-window.cpp similarity index 73% rename from phoenix/gtk/message-window.cpp rename to hiro/gtk/message-window.cpp index 2b542a19..88e3874c 100644 --- a/phoenix/gtk/message-window.cpp +++ b/hiro/gtk/message-window.cpp @@ -1,13 +1,13 @@ -namespace phoenix { +namespace hiro { -static MessageWindow::Response Message(MessageWindow::State& state, GtkMessageType messageStyle) { +static auto Message(MessageWindow::State& state, GtkMessageType messageStyle) -> MessageWindow::Response { GtkWidget* dialog = gtk_message_dialog_new( - state.parent ? GTK_WINDOW(state.parent->p.widget) : (GtkWindow*)nullptr, + state.parent && state.parent->self() ? GTK_WINDOW(state.parent->self()->widget) : (GtkWindow*)nullptr, GTK_DIALOG_MODAL, messageStyle, GTK_BUTTONS_NONE, "%s", (const char*)state.text ); if(state.title) gtk_window_set_title(GTK_WINDOW(dialog), state.title); - else if(applicationState.name) gtk_window_set_title(GTK_WINDOW(dialog), applicationState.name); + else if(Application::state.name) gtk_window_set_title(GTK_WINDOW(dialog), Application::state.name); switch(state.buttons) { case MessageWindow::Buttons::Ok: @@ -41,19 +41,19 @@ static MessageWindow::Response Message(MessageWindow::State& state, GtkMessageTy throw; } -MessageWindow::Response pMessageWindow::error(MessageWindow::State& state) { +auto pMessageWindow::error(MessageWindow::State& state) -> MessageWindow::Response { return Message(state, GTK_MESSAGE_ERROR); } -MessageWindow::Response pMessageWindow::information(MessageWindow::State& state) { +auto pMessageWindow::information(MessageWindow::State& state) -> MessageWindow::Response { return Message(state, GTK_MESSAGE_INFO); } -MessageWindow::Response pMessageWindow::question(MessageWindow::State& state) { +auto pMessageWindow::question(MessageWindow::State& state) -> MessageWindow::Response { return Message(state, GTK_MESSAGE_QUESTION); } -MessageWindow::Response pMessageWindow::warning(MessageWindow::State& state) { +auto pMessageWindow::warning(MessageWindow::State& state) -> MessageWindow::Response { return Message(state, GTK_MESSAGE_WARNING); } diff --git a/hiro/gtk/message-window.hpp b/hiro/gtk/message-window.hpp new file mode 100644 index 00000000..4daadc3d --- /dev/null +++ b/hiro/gtk/message-window.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pMessageWindow { + static auto error(MessageWindow::State& state) -> MessageWindow::Response; + static auto information(MessageWindow::State& state) -> MessageWindow::Response; + static auto question(MessageWindow::State& state) -> MessageWindow::Response; + static auto warning(MessageWindow::State& state) -> MessageWindow::Response; +}; + +} diff --git a/phoenix/gtk/monitor.cpp b/hiro/gtk/monitor.cpp similarity index 95% rename from phoenix/gtk/monitor.cpp rename to hiro/gtk/monitor.cpp index ccea2ebf..649c0823 100644 --- a/phoenix/gtk/monitor.cpp +++ b/hiro/gtk/monitor.cpp @@ -1,4 +1,4 @@ -namespace phoenix { +namespace hiro { unsigned pMonitor::count() { return gdk_screen_get_n_monitors(gdk_screen_get_default()); diff --git a/hiro/gtk/monitor.hpp b/hiro/gtk/monitor.hpp new file mode 100644 index 00000000..c616d6a8 --- /dev/null +++ b/hiro/gtk/monitor.hpp @@ -0,0 +1,9 @@ +namespace hiro { + +struct pMonitor { + static unsigned count(); + static Geometry geometry(unsigned monitor); + static unsigned primary(); +}; + +} diff --git a/phoenix/gtk/mouse.cpp b/hiro/gtk/mouse.cpp similarity index 86% rename from phoenix/gtk/mouse.cpp rename to hiro/gtk/mouse.cpp index 2e2a4021..0e6a6c94 100644 --- a/phoenix/gtk/mouse.cpp +++ b/hiro/gtk/mouse.cpp @@ -1,6 +1,6 @@ -namespace phoenix { +namespace hiro { -Position pMouse::position() { +auto pMouse::position() -> Position { XlibWindow root, child; int rootx, rooty, winx, winy; unsigned int mask; @@ -8,7 +8,7 @@ Position pMouse::position() { return {rootx, rooty}; } -bool pMouse::pressed(Mouse::Button button) { +auto pMouse::pressed(Mouse::Button button) -> bool { XlibWindow root, child; int rootx, rooty, winx, winy; unsigned int mask; diff --git a/hiro/gtk/mouse.hpp b/hiro/gtk/mouse.hpp new file mode 100644 index 00000000..805671fa --- /dev/null +++ b/hiro/gtk/mouse.hpp @@ -0,0 +1,8 @@ +namespace hiro { + +struct pMouse { + static auto position() -> Position; + static auto pressed(Mouse::Button button) -> bool; +}; + +} diff --git a/hiro/gtk/object.cpp b/hiro/gtk/object.cpp new file mode 100644 index 00000000..0eb9c64a --- /dev/null +++ b/hiro/gtk/object.cpp @@ -0,0 +1,31 @@ +namespace hiro { + +auto pObject::construct() -> void { +} + +auto pObject::destruct() -> void { +} + +auto pObject::focused() const -> bool { + return false; +} + +auto pObject::remove() -> void { +} + +auto pObject::reset() -> void { +} + +auto pObject::setEnabled(bool enabled) -> void { +} + +auto pObject::setFocused() -> void { +} + +auto pObject::setFont(const string& font) -> void { +} + +auto pObject::setVisible(bool visible) -> void { +} + +} diff --git a/hiro/gtk/object.hpp b/hiro/gtk/object.hpp new file mode 100644 index 00000000..45cfe490 --- /dev/null +++ b/hiro/gtk/object.hpp @@ -0,0 +1,27 @@ +namespace hiro { + +struct pObject { + pObject(mObject& reference) : reference(reference) {} + virtual ~pObject() {} + auto self() const -> mObject& { return (mObject&)reference; } + auto state() const -> mObject::State& { return self().state; } + virtual auto construct() -> void; + virtual auto destruct() -> void; + + virtual auto focused() const -> bool; + virtual auto remove() -> void; + virtual auto reset() -> void; + virtual auto setEnabled(bool enabled) -> void; + virtual auto setFocused() -> void; + virtual auto setFont(const string& font) -> void; + virtual auto setVisible(bool visible) -> void; + + auto locked() const -> bool { return locks != 0; } + auto lock() -> void { ++locks; } + auto unlock() -> void { --locks; } + + mObject& reference; + signed locks = 0; +}; + +} diff --git a/phoenix/gtk/platform.cpp b/hiro/gtk/platform.cpp similarity index 63% rename from phoenix/gtk/platform.cpp rename to hiro/gtk/platform.cpp index 9d6cdf70..63868a21 100644 --- a/phoenix/gtk/platform.cpp +++ b/hiro/gtk/platform.cpp @@ -1,24 +1,30 @@ #include "platform.hpp" - #include "utility.cpp" -#include "settings.cpp" +#include "font.cpp" #include "desktop.cpp" #include "monitor.cpp" #include "keyboard.cpp" #include "mouse.cpp" #include "browser-window.cpp" #include "message-window.cpp" -#include "font.cpp" +#include "object.cpp" +#include "hotkey.cpp" #include "timer.cpp" #include "window.cpp" +#include "status-bar.cpp" +#include "menu-bar.cpp" +#include "popup-menu.cpp" #include "action/action.cpp" #include "action/menu.cpp" -#include "action/separator.cpp" -#include "action/item.cpp" -#include "action/check-item.cpp" -#include "action/radio-item.cpp" +#include "action/menu-separator.cpp" +#include "action/menu-item.cpp" +#include "action/menu-check-item.cpp" +#include "action/menu-radio-item.cpp" + +#include "sizable.cpp" +#include "layout.cpp" #include "widget/widget.cpp" #include "widget/button.cpp" @@ -26,21 +32,31 @@ #include "widget/check-button.cpp" #include "widget/check-label.cpp" #include "widget/combo-button.cpp" +#include "widget/combo-button-item.cpp" #include "widget/console.cpp" #include "widget/frame.cpp" #include "widget/hex-edit.cpp" #include "widget/horizontal-scroller.cpp" #include "widget/horizontal-slider.cpp" +#include "widget/icon-view.cpp" +#include "widget/icon-view-item.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" #include "widget/list-view.cpp" +#include "widget/list-view-column.cpp" +#include "widget/list-view-item.cpp" #include "widget/progress-bar.cpp" #include "widget/radio-button.cpp" #include "widget/radio-label.cpp" +#include "widget/source-edit.cpp" #include "widget/tab-frame.cpp" +#include "widget/tab-frame-item.cpp" #include "widget/text-edit.cpp" +#include "widget/tree-view.cpp" +#include "widget/tree-view-item.cpp" #include "widget/vertical-scroller.cpp" #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" #include "application.cpp" +#include "settings.cpp" diff --git a/hiro/gtk/platform.hpp b/hiro/gtk/platform.hpp new file mode 100644 index 00000000..06b3f5ea --- /dev/null +++ b/hiro/gtk/platform.hpp @@ -0,0 +1,75 @@ +namespace hiro { + struct pWindow; + struct pMenu; + struct pLayout; + struct pWidget; +}; + +#define Declare(Name, Base) \ + p##Name(m##Name& reference) : p##Base(reference) {} \ + auto self() const -> m##Name& { return (m##Name&)reference; } \ + auto state() const -> m##Name::State& { return self().state; } \ + auto construct() -> void override; \ + auto destruct() -> void override; \ + +#include "font.hpp" +#include "desktop.hpp" +#include "monitor.hpp" +#include "keyboard.hpp" +#include "mouse.hpp" +#include "browser-window.hpp" +#include "message-window.hpp" +#include "object.hpp" +#include "hotkey.hpp" +#include "timer.hpp" +#include "window.hpp" +#include "status-bar.hpp" +#include "menu-bar.hpp" +#include "popup-menu.hpp" + +#include "action/action.hpp" +#include "action/menu.hpp" +#include "action/menu-separator.hpp" +#include "action/menu-item.hpp" +#include "action/menu-check-item.hpp" +#include "action/menu-radio-item.hpp" + +#include "sizable.hpp" +#include "layout.hpp" + +#include "widget/widget.hpp" +#include "widget/button.hpp" +#include "widget/canvas.hpp" +#include "widget/check-button.hpp" +#include "widget/check-label.hpp" +#include "widget/combo-button.hpp" +#include "widget/combo-button-item.hpp" +#include "widget/console.hpp" +#include "widget/frame.hpp" +#include "widget/hex-edit.hpp" +#include "widget/horizontal-scroller.hpp" +#include "widget/horizontal-slider.hpp" +#include "widget/icon-view.hpp" +#include "widget/icon-view-item.hpp" +#include "widget/label.hpp" +#include "widget/line-edit.hpp" +#include "widget/list-view.hpp" +#include "widget/list-view-column.hpp" +#include "widget/list-view-item.hpp" +#include "widget/progress-bar.hpp" +#include "widget/radio-button.hpp" +#include "widget/radio-label.hpp" +#include "widget/source-edit.hpp" +#include "widget/tab-frame.hpp" +#include "widget/tab-frame-item.hpp" +#include "widget/text-edit.hpp" +#include "widget/tree-view.hpp" +#include "widget/tree-view-item.hpp" +#include "widget/vertical-scroller.hpp" +#include "widget/vertical-slider.hpp" +#include "widget/viewport.hpp" + +#undef Declare + +#include "application.hpp" +#include "settings.hpp" diff --git a/hiro/gtk/popup-menu.cpp b/hiro/gtk/popup-menu.cpp new file mode 100644 index 00000000..752d0877 --- /dev/null +++ b/hiro/gtk/popup-menu.cpp @@ -0,0 +1,32 @@ +namespace hiro { + +auto pPopupMenu::construct() -> void { + gtkMenu = gtk_menu_new(); +} + +auto pPopupMenu::destruct() -> void { + gtk_widget_destroy(gtkMenu); +} + +auto pPopupMenu::append(sAction action) -> void { + if(action->self()) { + gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), action->self()->widget); + action->self()->setFont(action->font(true)); + action->self()->setVisible(action->visible(true)); + } +} + +auto pPopupMenu::remove(sAction action) -> void { +} + +auto pPopupMenu::setFont(const string& font) -> void { + for(auto& action : state().actions) { + if(action->self()) action->self()->setFont(action->font(true)); + } +} + +auto pPopupMenu::setVisible(bool visible) -> void { + if(visible) gtk_menu_popup(GTK_MENU(gtkMenu), nullptr, nullptr, nullptr, nullptr, 0, gtk_get_current_event_time()); +} + +} diff --git a/hiro/gtk/popup-menu.hpp b/hiro/gtk/popup-menu.hpp new file mode 100644 index 00000000..03548cfb --- /dev/null +++ b/hiro/gtk/popup-menu.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pPopupMenu : pObject { + Declare(PopupMenu, Object) + + auto append(sAction action) -> void; + auto remove(sAction action) -> void; + auto setFont(const string& font) -> void override; + auto setVisible(bool visible) -> void; + + GtkWidget* gtkMenu = nullptr; +}; + +} diff --git a/phoenix/gtk/settings.cpp b/hiro/gtk/settings.cpp similarity index 93% rename from phoenix/gtk/settings.cpp rename to hiro/gtk/settings.cpp index 6c411c36..c1754dae 100644 --- a/phoenix/gtk/settings.cpp +++ b/hiro/gtk/settings.cpp @@ -1,6 +1,4 @@ -namespace phoenix { - -static Settings* settings = nullptr; +namespace hiro { void Settings::load() { string path = {userpath(), ".config/phoenix/"}; diff --git a/hiro/gtk/settings.hpp b/hiro/gtk/settings.hpp new file mode 100644 index 00000000..df69ac2d --- /dev/null +++ b/hiro/gtk/settings.hpp @@ -0,0 +1,26 @@ +namespace hiro { + +struct Settings : Configuration::Document { + vector<uint16_t> keycodes; + + struct Geometry : Configuration::Node { + signed frameX; + signed frameY; + signed frameWidth; + signed frameHeight; + signed menuHeight; + signed statusHeight; + } geometry; + + struct Window : Configuration::Node { + unsigned backgroundColor; + } window; + + void load(); + void save(); + Settings(); +}; + +static Settings* settings = nullptr; + +} diff --git a/hiro/gtk/sizable.cpp b/hiro/gtk/sizable.cpp new file mode 100644 index 00000000..c882be2b --- /dev/null +++ b/hiro/gtk/sizable.cpp @@ -0,0 +1,16 @@ +namespace hiro { + +auto pSizable::construct() -> void { +} + +auto pSizable::destruct() -> void { +} + +auto pSizable::minimumSize() const -> Size { + return {0, 0}; +} + +auto pSizable::setGeometry(Geometry geometry) -> void { +} + +} diff --git a/hiro/gtk/sizable.hpp b/hiro/gtk/sizable.hpp new file mode 100644 index 00000000..12dfc9f0 --- /dev/null +++ b/hiro/gtk/sizable.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pSizable : pObject { + Declare(Sizable, Object) + + virtual auto minimumSize() const -> Size; + virtual auto setGeometry(Geometry geometry) -> void; +}; + +} diff --git a/hiro/gtk/status-bar.cpp b/hiro/gtk/status-bar.cpp new file mode 100644 index 00000000..02ffafbf --- /dev/null +++ b/hiro/gtk/status-bar.cpp @@ -0,0 +1,38 @@ +namespace hiro { + +auto pStatusBar::construct() -> void { +} + +auto pStatusBar::destruct() -> void { +} + +auto pStatusBar::setEnabled(bool enabled) -> void { + if(auto parent = _parent()) { + parent->_setStatusEnabled(enabled); + } +} + +auto pStatusBar::setFont(const string& font) -> void { + if(auto parent = _parent()) { + parent->_setStatusFont(font); + } +} + +auto pStatusBar::setText(const string& text) -> void { + if(auto parent = _parent()) { + parent->_setStatusText(text); + } +} + +auto pStatusBar::setVisible(bool visible) -> void { + if(auto parent = _parent()) { + parent->_setStatusVisible(visible); + } +} + +auto pStatusBar::_parent() -> pWindow* { + if(auto parent = self().parentWindow()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/status-bar.hpp b/hiro/gtk/status-bar.hpp new file mode 100644 index 00000000..7f178dc5 --- /dev/null +++ b/hiro/gtk/status-bar.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pStatusBar : pObject { + Declare(StatusBar, Object) + + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setText(const string& text) -> void; + auto setVisible(bool visible) -> void override; + + auto _parent() -> pWindow*; +}; + +} diff --git a/hiro/gtk/timer.cpp b/hiro/gtk/timer.cpp new file mode 100644 index 00000000..49dee689 --- /dev/null +++ b/hiro/gtk/timer.cpp @@ -0,0 +1,31 @@ +namespace hiro { + +static auto Timer_trigger(pTimer* p) -> signed { + //timer may have been disabled prior to triggering, so check state + if(p->self().enabled(true)) p->self().doActivate(); + + //callback may have disabled timer, so check state again + if(p->self().enabled(true)) { + g_timeout_add(p->state().interval, (GSourceFunc)Timer_trigger, (gpointer)p); + } + + //kill this timer instance (it is spawned above if needed again) + return false; +} + +auto pTimer::construct() -> void { +} + +auto pTimer::destruct() -> void { +} + +auto pTimer::setEnabled(bool enabled) -> void { + if(enabled) { + g_timeout_add(state().interval, (GSourceFunc)Timer_trigger, (gpointer)this); + } +} + +auto pTimer::setInterval(unsigned interval) -> void { +} + +} diff --git a/hiro/gtk/timer.hpp b/hiro/gtk/timer.hpp new file mode 100644 index 00000000..d09565e0 --- /dev/null +++ b/hiro/gtk/timer.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pTimer : pObject { + Declare(Timer, Object) + + auto setEnabled(bool enabled) -> void; + auto setInterval(unsigned interval) -> void; +}; + +} diff --git a/hiro/gtk/utility.cpp b/hiro/gtk/utility.cpp new file mode 100644 index 00000000..1fbdbd36 --- /dev/null +++ b/hiro/gtk/utility.cpp @@ -0,0 +1,49 @@ +namespace hiro { + +static auto CreateColor(const Color& color) -> GdkColor { + GdkColor gdkColor; + gdkColor.pixel = (color.red() << 16) | (color.green() << 8) | (color.blue() << 0); + gdkColor.red = (color.red() << 8) | (color.red() << 0); + gdkColor.green = (color.green() << 8) | (color.green() << 0); + gdkColor.blue = (color.blue() << 8) | (color.blue() << 0); + return gdkColor; +} + +static auto CreatePixbuf(const nall::image& image, bool scale = false) -> GdkPixbuf* { + nall::image gdkImage = image; + gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); + if(scale) gdkImage.scale(15, 15); + + GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height); + memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4); + + return pixbuf; +} + +static auto CreateImage(const nall::image& image, bool scale = false) -> GtkImage* { + GdkPixbuf* pixbuf = CreatePixbuf(image, scale); + GtkImage* gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf); + g_object_unref(pixbuf); + return gtkImage; +} + +static auto DropPaths(GtkSelectionData* data) -> lstring { + gchar** uris = gtk_selection_data_get_uris(data); + if(uris == nullptr) return {}; + + lstring paths; + for(unsigned n = 0; uris[n] != nullptr; n++) { + gchar* pathname = g_filename_from_uri(uris[n], nullptr, nullptr); + if(pathname == nullptr) continue; + + string path = pathname; + g_free(pathname); + if(directory::exists(path) && !path.endsWith("/")) path.append("/"); + paths.append(path); + } + + g_strfreev(uris); + return paths; +} + +} diff --git a/hiro/gtk/widget/button.cpp b/hiro/gtk/widget/button.cpp new file mode 100644 index 00000000..7c1e5872 --- /dev/null +++ b/hiro/gtk/widget/button.cpp @@ -0,0 +1,68 @@ +namespace hiro { + +static auto Button_activate(GtkButton* gtkButton, pButton* p) -> void { p->_doActivate(); } + +auto pButton::construct() -> void { + gtkWidget = gtk_button_new(); + gtkButton = GTK_BUTTON(gtkWidget); + + setBordered(state().bordered); + setIcon(state().icon); + setOrientation(state().orientation); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkButton), "clicked", G_CALLBACK(Button_activate), (gpointer)this); + + pWidget::construct(); +} + +auto pButton::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pButton::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + + if(state().orientation == Orientation::Horizontal) { + size.setWidth(size.width() + state().icon.width); + size.setHeight(max(size.height(), state().icon.height)); + } + + if(state().orientation == Orientation::Vertical) { + size.setWidth(max(size.width(), state().icon.width)); + size.setHeight(size.height() + state().icon.height); + } + + return {size.width() + (state().text ? 24 : 12), size.height() + 12}; +} + +auto pButton::setBordered(bool bordered) -> void { + gtk_button_set_relief(gtkButton, bordered ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE); +} + +auto pButton::setIcon(const image& icon) -> void { + if(icon) { + auto gtkImage = CreateImage(icon); + gtk_button_set_image(gtkButton, (GtkWidget*)gtkImage); + } else { + gtk_button_set_image(gtkButton, nullptr); + } +} + +auto pButton::setOrientation(Orientation orientation) -> void { + switch(orientation) { + case Orientation::Horizontal: gtk_button_set_image_position(gtkButton, GTK_POS_LEFT); break; + case Orientation::Vertical: gtk_button_set_image_position(gtkButton, GTK_POS_TOP); break; + } +} + +auto pButton::setText(const string& text) -> void { + gtk_button_set_label(gtkButton, text); + setFont(self().font(true)); //gtk_button_set_label() recreates label, which destroys currently assigned font +} + +auto pButton::_doActivate() -> void { + self().doActivate(); +} + +} diff --git a/hiro/gtk/widget/button.hpp b/hiro/gtk/widget/button.hpp new file mode 100644 index 00000000..9cabea5d --- /dev/null +++ b/hiro/gtk/widget/button.hpp @@ -0,0 +1,17 @@ +namespace hiro { + +struct pButton : pWidget { + Declare(Button, Widget) + + auto minimumSize() const -> Size override; + auto setBordered(bool bordered) -> void; + auto setIcon(const image& icon) -> void; + auto setOrientation(Orientation orientation) -> void; + auto setText(const string& text) -> void; + + auto _doActivate() -> void; + + GtkButton* gtkButton = nullptr; +}; + +} diff --git a/hiro/gtk/widget/canvas.cpp b/hiro/gtk/widget/canvas.cpp new file mode 100644 index 00000000..e40c3baf --- /dev/null +++ b/hiro/gtk/widget/canvas.cpp @@ -0,0 +1,212 @@ +namespace hiro { + +static auto Canvas_drop(GtkWidget* widget, GdkDragContext* context, signed x, signed y, +GtkSelectionData* data, unsigned type, unsigned timestamp, pCanvas* p) -> void { + if(!p->state().droppable) return; + lstring paths = DropPaths(data); + if(paths.empty()) return; + p->self().doDrop(paths); +} + +static auto Canvas_expose(GtkWidget* widget, GdkEventExpose* event, pCanvas* p) -> signed { + p->_onExpose(event); + return true; +} + +static auto Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, pCanvas* p) -> signed { + p->self().doMouseLeave(); + return true; +} + +static auto Canvas_mouseMove(GtkWidget* widget, GdkEventButton* event, pCanvas* p) -> signed { + p->self().doMouseMove({(signed)event->x, (signed)event->y}); + return true; +} + +static auto Canvas_mousePress(GtkWidget* widget, GdkEventButton* event, pCanvas* p) -> signed { + switch(event->button) { + case 1: p->self().doMousePress(Mouse::Button::Left); break; + case 2: p->self().doMousePress(Mouse::Button::Middle); break; + case 3: p->self().doMousePress(Mouse::Button::Right); break; + } + return true; +} + +static auto Canvas_mouseRelease(GtkWidget* widget, GdkEventButton* event, pCanvas* p) -> signed { + switch(event->button) { + case 1: p->self().doMouseRelease(Mouse::Button::Left); break; + case 2: p->self().doMouseRelease(Mouse::Button::Middle); break; + case 3: p->self().doMouseRelease(Mouse::Button::Right); break; + } + return true; +} + +auto pCanvas::construct() -> void { + gtkWidget = gtk_drawing_area_new(); + gtk_widget_add_events(gtkWidget, + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); + + setDroppable(state().droppable); + _rasterize(); + _redraw(); + + //todo: need to work around GTK+ library bug: + //after calling destruct(), construct() with state.droppable == true; + //GTK+ will throw SIGBUS inside g_signal_connect_data() on one of the below connections + + g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Canvas_mousePress), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_drop), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "expose-event", G_CALLBACK(Canvas_expose), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Canvas_mouseLeave), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Canvas_mouseMove), (gpointer)this); + + pWidget::construct(); +} + +auto pCanvas::destruct() -> void { + _release(); + if(gtkWidget) gtk_widget_destroy(gtkWidget), gtkWidget = nullptr; + gtkParent = nullptr; +} + +auto pCanvas::minimumSize() const -> Size { + return {max(0, state().size.width()), max(0, state().size.height())}; +} + +auto pCanvas::setColor(Color color) -> void { + mode = Mode::Color; + update(); +} + +auto pCanvas::setData(Size size) -> void { + mode = Mode::Data; + update(); +} + +auto pCanvas::setDroppable(bool droppable) -> void { + if(droppable) { + gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_uri_targets(gtkWidget); + } +} + +auto pCanvas::setGeometry(Geometry geometry) -> void { + update(); + pWidget::setGeometry(geometry); +} + +auto pCanvas::setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> void { + mode = Mode::Gradient; + update(); +} + +auto pCanvas::setIcon(const image& icon) -> void { + mode = Mode::Icon; + update(); +} + +auto pCanvas::update() -> void { + _rasterize(); + _redraw(); +} + +auto pCanvas::_onExpose(GdkEventExpose* expose) -> void { + if(surface == nullptr) return; + + signed sx = 0, sy = 0, dx = 0, dy = 0; + signed width = surfaceWidth; + signed height = surfaceHeight; + auto geometry = pSizable::state().geometry; + + if(width <= geometry.width()) { + sx = 0; + dx = (geometry.width() - width) / 2; + } else { + sx = (width - geometry.width()) / 2; + dx = 0; + width = geometry.width(); + } + + if(height <= geometry.height()) { + sy = 0; + dy = (geometry.height() - height) / 2; + } else { + sy = (height - geometry.height()) / 2; + dy = 0; + height = geometry.height(); + } + + gdk_draw_pixbuf(gtk_widget_get_window(gtkWidget), nullptr, surface, sx, sy, dx, dy, width, height, GDK_RGB_DITHER_NONE, 0, 0); +} + +auto pCanvas::_rasterize() -> void { + signed width = 0; + signed height = 0; + + if(mode == Mode::Color || mode == Mode::Gradient) { + width = pSizable::state().geometry.width(); + height = pSizable::state().geometry.height(); + } else { + width = state().size.width(); + height = state().size.height(); + } + + if(width <= 0 || height <= 0) return; + + if(width != surfaceWidth || height != surfaceHeight) _release(); + surfaceWidth = width; + surfaceHeight = height; + + if(!surface) surface = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height); + uint32_t* buffer = (uint32_t*)gdk_pixbuf_get_pixels(surface); + + if(mode == Mode::Color) { + uint32_t color = state().color.value(); + for(auto n : range(width * height)) buffer[n] = color; + } + + if(mode == Mode::Gradient) { + image fill; + fill.allocate(width, height); + fill.gradient( + state().gradient[0].value(), state().gradient[1].value(), state().gradient[2].value(), state().gradient[3].value() + ); + memory::copy(buffer, fill.data, fill.size); + } + + if(mode == Mode::Icon) { + auto icon = state().icon; + icon.scale(width, height); + icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); + memory::copy(buffer, icon.data, icon.size); + } + + if(mode == Mode::Data) { + memory::copy(buffer, state().data.data(), state().data.size() * sizeof(uint32_t)); + } + + //ARGB -> ABGR conversion + for(auto n : range(width * height)) { + uint32_t color = *buffer; + color = (color & 0xff00ff00) | ((color & 0xff0000) >> 16) | ((color & 0x0000ff) << 16); + *buffer++ = color; + } +} + +auto pCanvas::_redraw() -> void { + if(gtk_widget_get_realized(gtkWidget)) { + gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), nullptr, true); + } +} + +auto pCanvas::_release() -> void { + if(surface) { + g_object_unref(surface); + surface = nullptr; + } + surfaceWidth = 0; + surfaceHeight = 0; +} + +} diff --git a/hiro/gtk/widget/canvas.hpp b/hiro/gtk/widget/canvas.hpp new file mode 100644 index 00000000..99e9b03d --- /dev/null +++ b/hiro/gtk/widget/canvas.hpp @@ -0,0 +1,28 @@ +namespace hiro { + +struct pCanvas : pWidget { + Declare(Canvas, Widget) + + auto minimumSize() const -> Size; + auto setColor(Color color) -> void; + auto setData(Size size) -> void; + auto setDroppable(bool droppable) -> void; + auto setGeometry(Geometry geometry) -> void override; + auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> void; + auto setIcon(const image& icon) -> void; + auto update() -> void; + + enum class Mode : unsigned { Color, Data, Gradient, Icon }; + + auto _onExpose(GdkEventExpose* event) -> void; + auto _rasterize() -> void; + auto _redraw() -> void; + auto _release() -> void; + + GdkPixbuf* surface = nullptr; + unsigned surfaceWidth = 0; + unsigned surfaceHeight = 0; + Mode mode = Mode::Color; +}; + +} diff --git a/hiro/gtk/widget/check-button.cpp b/hiro/gtk/widget/check-button.cpp new file mode 100644 index 00000000..41c7a51f --- /dev/null +++ b/hiro/gtk/widget/check-button.cpp @@ -0,0 +1,73 @@ +namespace hiro { + +static auto CheckButton_toggle(GtkToggleButton* toggleButton, pCheckButton* p) -> void { + p->state().checked = gtk_toggle_button_get_active(toggleButton); + if(!p->locked()) p->self().doToggle(); +} + +auto pCheckButton::construct() -> void { + gtkWidget = gtk_toggle_button_new(); + + setBordered(state().bordered); + setChecked(state().checked); + setIcon(state().icon); + setOrientation(state().orientation); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckButton_toggle), (gpointer)this); + + pWidget::construct(); +} + +auto pCheckButton::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pCheckButton::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + + if(state().orientation == Orientation::Horizontal) { + size.setWidth(size.width() + state().icon.width); + size.setHeight(max(size.height(), state().icon.height)); + } + + if(state().orientation == Orientation::Vertical) { + size.setWidth(max(size.width(), state().icon.width)); + size.setHeight(size.height() + state().icon.height); + } + + return {size.width() + 24, size.height() + 12}; +} + +auto pCheckButton::setBordered(bool bordered) -> void { + gtk_button_set_relief(GTK_BUTTON(gtkWidget), bordered ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE); +} + +auto pCheckButton::setChecked(bool checked) -> void { + lock(); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked); + unlock(); +} + +auto pCheckButton::setIcon(const image& icon) -> void { + if(icon) { + GtkImage* gtkImage = CreateImage(icon); + gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage); + } else { + gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr); + } +} + +auto pCheckButton::setOrientation(Orientation orientation) -> void { + switch(orientation) { + case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break; + case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break; + } +} + +auto pCheckButton::setText(const string& text) -> void { + gtk_button_set_label(GTK_BUTTON(gtkWidget), text); + setFont(self().font(true)); //gtk_button_set_label() recreates label, which destroys currently assigned font +} + +} diff --git a/hiro/gtk/widget/check-button.hpp b/hiro/gtk/widget/check-button.hpp new file mode 100644 index 00000000..3b31d917 --- /dev/null +++ b/hiro/gtk/widget/check-button.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pCheckButton : pWidget { + Declare(CheckButton, Widget) + + auto minimumSize() const -> Size override; + auto setBordered(bool bordered) -> void; + auto setChecked(bool checked) -> void; + auto setIcon(const image& icon) -> void; + auto setOrientation(Orientation orientation) -> void; + auto setText(const string& text) -> void; +}; + +} diff --git a/hiro/gtk/widget/check-label.cpp b/hiro/gtk/widget/check-label.cpp new file mode 100644 index 00000000..c9dbd0a7 --- /dev/null +++ b/hiro/gtk/widget/check-label.cpp @@ -0,0 +1,39 @@ +namespace hiro { + +static auto CheckLabel_toggle(GtkToggleButton* toggleButton, pCheckLabel* p) -> void { + p->state().checked = gtk_toggle_button_get_active(toggleButton); + if(!p->locked()) p->self().doToggle(); +} + +auto pCheckLabel::construct() -> void { + gtkWidget = gtk_check_button_new_with_label(""); + + setChecked(state().checked); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckLabel_toggle), (gpointer)this); + + pWidget::construct(); +} + +auto pCheckLabel::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pCheckLabel::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + return {size.width() + 28, size.height() + 4}; +} + +auto pCheckLabel::setChecked(bool checked) -> void { + lock(); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked); + unlock(); +} + +auto pCheckLabel::setText(const string& text) -> void { + gtk_button_set_label(GTK_BUTTON(gtkWidget), text); + setFont(self().font(true)); //gtk_button_set_label() recreates label, which destroys currently assigned font +} + +} diff --git a/hiro/gtk/widget/check-label.hpp b/hiro/gtk/widget/check-label.hpp new file mode 100644 index 00000000..c84195f1 --- /dev/null +++ b/hiro/gtk/widget/check-label.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pCheckLabel : pWidget { + Declare(CheckLabel, Widget) + + auto minimumSize() const -> Size; + auto setChecked(bool checked) -> void; + auto setText(const string& text) -> void; +}; + +} diff --git a/hiro/gtk/widget/combo-button-item.cpp b/hiro/gtk/widget/combo-button-item.cpp new file mode 100644 index 00000000..2f6e79bc --- /dev/null +++ b/hiro/gtk/widget/combo-button-item.cpp @@ -0,0 +1,42 @@ +namespace hiro { + +auto pComboButtonItem::construct() -> void { +} + +auto pComboButtonItem::destruct() -> void { +} + +auto pComboButtonItem::setIcon(const image& icon) -> void { + if(auto parent = _parent()) { + if(icon) { + auto copy = icon; + auto size = pFont::size(self().font(true), " ").height(); + copy.scale(size, size); + auto pixbuf = CreatePixbuf(copy); + gtk_list_store_set(parent->gtkListStore, >kIter, 0, pixbuf, -1); + } else { + gtk_list_store_set(parent->gtkListStore, >kIter, 0, nullptr, -1); + } + } +} + +auto pComboButtonItem::setSelected() -> void { + if(auto parent = _parent()) { + parent->lock(); + gtk_combo_box_set_active(parent->gtkComboBox, self().offset()); + parent->unlock(); + } +} + +auto pComboButtonItem::setText(const string& text) -> void { + if(auto parent = _parent()) { + gtk_list_store_set(parent->gtkListStore, >kIter, 1, text.data(), -1); + } +} + +auto pComboButtonItem::_parent() -> pComboButton* { + if(auto parent = self().parentComboButton()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/combo-button-item.hpp b/hiro/gtk/widget/combo-button-item.hpp new file mode 100644 index 00000000..d823b746 --- /dev/null +++ b/hiro/gtk/widget/combo-button-item.hpp @@ -0,0 +1,15 @@ +namespace hiro { + +struct pComboButtonItem : pObject { + Declare(ComboButtonItem, Object) + + auto setIcon(const image& icon) -> void; + auto setSelected() -> void; + auto setText(const string& text) -> void; + + auto _parent() -> pComboButton*; + + GtkTreeIter gtkIter; +}; + +} diff --git a/hiro/gtk/widget/combo-button.cpp b/hiro/gtk/widget/combo-button.cpp new file mode 100644 index 00000000..9b2ea147 --- /dev/null +++ b/hiro/gtk/widget/combo-button.cpp @@ -0,0 +1,91 @@ +namespace hiro { + +static auto ComboButton_change(GtkComboBox* comboBox, pComboButton* p) -> void { p->_updateSelected(); } + +auto pComboButton::construct() -> void { + gtkListStore = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); + gtkTreeModel = GTK_TREE_MODEL(gtkListStore); + gtkWidget = gtk_combo_box_new_with_model(gtkTreeModel); + gtkComboBox = GTK_COMBO_BOX(gtkWidget); + + gtkCellIcon = gtk_cell_renderer_pixbuf_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkWidget), gtkCellIcon, false); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkWidget), gtkCellIcon, "pixbuf", 0, nullptr); + gtkCellText = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkWidget), gtkCellText, true); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkWidget), gtkCellText, "text", 1, nullptr); + + for(auto& item : state().items) { + append(item); + if(item->selected()) item->setSelected(); + } + + g_signal_connect(G_OBJECT(gtkWidget), "changed", G_CALLBACK(ComboButton_change), (gpointer)this); + + pWidget::construct(); +} + +auto pComboButton::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pComboButton::append(sComboButtonItem item) -> void { + lock(); + if(auto delegate = item->self()) { + gtk_list_store_append(gtkListStore, &delegate->gtkIter); + item->setIcon(item->state.icon); + item->setText(item->state.text); + } + unlock(); +} + +auto pComboButton::minimumSize() const -> Size { + string font = self().font(true); + signed maximumWidth = 0; + for(auto& item : state().items) { + maximumWidth = max(maximumWidth, + (item->state.icon ? 2 + pFont::size(font, " ").height() : 0) + + pFont::size(font, item->state.text).width() + ); + } + Size size = pFont::size(font, " "); + return {maximumWidth + 40, size.height() + 12}; +} + +auto pComboButton::remove(sComboButtonItem item) -> void { + lock(); + if(auto delegate = item->self()) { + gtk_list_store_remove(gtkListStore, &delegate->gtkIter); + //if the currently selected item is removed; GTK+ deselects everything + //detect this behavior and select the first item instead of nothing + if(gtk_combo_box_get_active(GTK_COMBO_BOX(gtkWidget)) < 0) { + if(gtk_tree_model_iter_n_children(gtkTreeModel, nullptr) > 0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), 0); + state().selected = 0; + } + } + } + unlock(); +} + +auto pComboButton::reset() -> void { + lock(); + gtk_list_store_clear(gtkListStore); + unlock(); +} + +auto pComboButton::setFont(const string& font) -> void { + pWidget::setFont(font); + auto fontDescription = pFont::create(font); + g_object_set(G_OBJECT(gtkCellText), "font-desc", fontDescription, nullptr); +} + +auto pComboButton::_updateSelected() -> void { + signed selected = gtk_combo_box_get_active(gtkComboBox); + if(selected >= 0) { + state().selected = selected; + if(!locked()) self().doChange(); + } +} + +} diff --git a/hiro/gtk/widget/combo-button.hpp b/hiro/gtk/widget/combo-button.hpp new file mode 100644 index 00000000..ff66df28 --- /dev/null +++ b/hiro/gtk/widget/combo-button.hpp @@ -0,0 +1,21 @@ +namespace hiro { + +struct pComboButton : pWidget { + Declare(ComboButton, Widget) + + auto append(sComboButtonItem item) -> void; + auto minimumSize() const -> Size override; + auto remove(sComboButtonItem item) -> void; + auto reset() -> void; + auto setFont(const string& font) -> void override; + + auto _updateSelected() -> void; + + GtkListStore* gtkListStore = nullptr; + GtkTreeModel* gtkTreeModel = nullptr; + GtkComboBox* gtkComboBox = nullptr; + GtkCellRenderer* gtkCellIcon = nullptr; + GtkCellRenderer* gtkCellText = nullptr; +}; + +} diff --git a/phoenix/gtk/widget/console.cpp b/hiro/gtk/widget/console.cpp similarity index 76% rename from phoenix/gtk/widget/console.cpp rename to hiro/gtk/widget/console.cpp index 722f1387..a72cd629 100644 --- a/phoenix/gtk/widget/console.cpp +++ b/hiro/gtk/widget/console.cpp @@ -1,34 +1,60 @@ -namespace phoenix { +namespace hiro { -static bool Console_keyPress(GtkWidget* widget, GdkEventKey* event, Console* self) { - return self->p.keyPress(event->keyval, event->state); +static auto Console_keyPress(GtkWidget*, GdkEventKey* event, pConsole* p) -> signed { + return p->_keyPress(event->keyval, event->state); } -void pConsole::print(string text) { +auto pConsole::construct() -> void { + gtkWidget = gtk_scrolled_window_new(0, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); + + subWidget = gtk_text_view_new(); + gtk_widget_show(subWidget); + gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), false); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_NONE); + gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); + + textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); + + setBackgroundColor(state().backgroundColor); + setForegroundColor(state().foregroundColor); + + g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(Console_keyPress), (gpointer)this); + + pWidget::construct(); +} + +auto pConsole::destruct() -> void { + gtk_widget_destroy(subWidget); + gtk_widget_destroy(gtkWidget); +} + +auto pConsole::print(const string& text) -> void { //insert text before prompt and command GtkTextIter iter; gtk_text_buffer_get_iter_at_line_offset(textBuffer, &iter, gtk_text_buffer_get_line_count(textBuffer), 0); gtk_text_buffer_insert(textBuffer, &iter, text, -1); - seekToEnd(); + _seekToEnd(); } -void pConsole::reset() { +auto pConsole::reset() -> void { //flush history and redraw prompt - gtk_text_buffer_set_text(textBuffer, console.prompt(), -1); - seekToEnd(); + gtk_text_buffer_set_text(textBuffer, state().prompt, -1); + _seekToEnd(); } -void pConsole::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &gdkColor); +auto pConsole::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); } -void pConsole::setForegroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &gdkColor); +auto pConsole::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); } -void pConsole::setPrompt(string prompt) { +auto pConsole::setPrompt(const string& prompt) -> void { //erase previous prompt and replace it with new prompt GtkTextIter lhs, rhs; gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0); @@ -36,42 +62,15 @@ void pConsole::setPrompt(string prompt) { gtk_text_buffer_delete(textBuffer, &lhs, &rhs); gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0); gtk_text_buffer_insert(textBuffer, &lhs, previousPrompt = prompt, -1); - seekToEnd(); + _seekToEnd(); } -void pConsole::constructor() { - gtkWidget = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); - - subWidget = gtk_text_view_new(); - gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), false); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_NONE); - gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); - - textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); - - g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(Console_keyPress), (gpointer)&console); - - gtk_widget_show(subWidget); -} - -void pConsole::destructor() { - gtk_widget_destroy(subWidget); - gtk_widget_destroy(gtkWidget); -} - -void pConsole::orphan() { - destructor(); - constructor(); -} - -bool pConsole::keyPress(unsigned scancode, unsigned mask) { +auto pConsole::_keyPress(unsigned scancode, unsigned mask) -> bool { if(mask & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK)) return false; //allow actions such as Ctrl+C (copy) GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); GtkTextIter start, cursor, end; - gtk_text_buffer_get_iter_at_line_offset(textBuffer, &start, gtk_text_buffer_get_line_count(textBuffer), console.prompt().size()); + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &start, gtk_text_buffer_get_line_count(textBuffer), state().prompt.size()); gtk_text_buffer_get_iter_at_mark(textBuffer, &cursor, mark); gtk_text_buffer_get_end_iter(textBuffer, &end); @@ -79,12 +78,12 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { char* temp = gtk_text_buffer_get_text(textBuffer, &start, &end, true); string s = temp; g_free(temp); - gtk_text_buffer_insert(textBuffer, &end, string{"\n", console.prompt()}, -1); - if(console.onActivate) console.onActivate(s); + gtk_text_buffer_insert(textBuffer, &end, string{"\n", state().prompt}, -1); + self().doActivate(s); if(s) history.prepend(s); if(history.size() > 128) history.removeLast(); historyOffset = 0; - seekToEnd(); + _seekToEnd(); return true; } @@ -94,7 +93,7 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { if(historyOffset < history.size()) { gtk_text_buffer_insert(textBuffer, &end, history[historyOffset++], -1); } - seekToEnd(); + _seekToEnd(); return true; } @@ -104,7 +103,7 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { if(historyOffset > 0) { gtk_text_buffer_insert(textBuffer, &end, history[--historyOffset], -1); } - seekToEnd(); + _seekToEnd(); return true; } @@ -115,7 +114,7 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) - 1); gtk_text_buffer_place_cursor(textBuffer, &cursor); } - seekToMark(); + _seekToMark(); return true; } @@ -126,19 +125,19 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) + 1); gtk_text_buffer_place_cursor(textBuffer, &cursor); } - seekToMark(); + _seekToMark(); return true; } if(scancode == GDK_KEY_Home) { gtk_text_buffer_place_cursor(textBuffer, &start); - seekToMark(); + _seekToMark(); return true; } if(scancode == GDK_KEY_End) { gtk_text_buffer_place_cursor(textBuffer, &end); - seekToMark(); + _seekToMark(); return true; } @@ -147,7 +146,7 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { GtkTextIter lhs = cursor; gtk_text_iter_set_offset(&lhs, gtk_text_iter_get_offset(&cursor) - 1); gtk_text_buffer_delete(textBuffer, &lhs, &cursor); - seekToMark(); + _seekToMark(); return true; } @@ -157,28 +156,28 @@ bool pConsole::keyPress(unsigned scancode, unsigned mask) { GtkTextIter rhs = cursor; gtk_text_iter_set_offset(&rhs, gtk_text_iter_get_offset(&cursor) + 1); gtk_text_buffer_delete(textBuffer, &cursor, &rhs); - seekToMark(); + _seekToMark(); return true; } if(scancode >= 0x20 && scancode <= 0x7e) { if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) return true; gtk_text_buffer_insert(textBuffer, &cursor, string{(char)scancode}, -1); - seekToMark(); + _seekToMark(); return true; } return false; } -void pConsole::seekToEnd() { +auto pConsole::_seekToEnd() -> void { GtkTextIter iter; gtk_text_buffer_get_end_iter(textBuffer, &iter); gtk_text_buffer_place_cursor(textBuffer, &iter); - seekToMark(); + _seekToMark(); } -void pConsole::seekToMark() { +auto pConsole::_seekToMark() -> void { GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark); } diff --git a/hiro/gtk/widget/console.hpp b/hiro/gtk/widget/console.hpp new file mode 100644 index 00000000..0d32a476 --- /dev/null +++ b/hiro/gtk/widget/console.hpp @@ -0,0 +1,23 @@ +namespace hiro { + +struct pConsole : pWidget { + Declare(Console, Widget) + + auto print(const string& text) -> void; + auto reset() -> void; + auto setBackgroundColor(Color color) -> void; + auto setForegroundColor(Color color) -> void; + auto setPrompt(const string& prompt) -> void; + + auto _keyPress(unsigned scancode, unsigned mask) -> bool; + auto _seekToEnd() -> void; + auto _seekToMark() -> void; + + GtkWidget* subWidget = nullptr; + GtkTextBuffer* textBuffer = nullptr; + string previousPrompt; + lstring history; + unsigned historyOffset = 0; +}; + +} diff --git a/hiro/gtk/widget/frame.cpp b/hiro/gtk/widget/frame.cpp new file mode 100644 index 00000000..30a1b180 --- /dev/null +++ b/hiro/gtk/widget/frame.cpp @@ -0,0 +1,66 @@ +namespace hiro { + +auto pFrame::construct() -> void { + gtkWidget = gtk_frame_new(nullptr); + gtkLabel = gtk_label_new(""); + gtk_frame_set_label_widget(GTK_FRAME(gtkWidget), gtkLabel); + gtk_widget_show(gtkLabel); + + setText(state().text); + + pWidget::construct(); +} + +auto pFrame::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pFrame::append(shared_pointer<mLayout> layout) -> void { + if(auto layout = _layout()) layout->setFont(layout->self().font(true)); +} + +auto pFrame::container(mWidget& widget) -> GtkWidget* { + return gtk_widget_get_parent(gtkWidget); +} + +auto pFrame::remove(shared_pointer<mLayout> layout) -> void { +} + +auto pFrame::setEnabled(bool enabled) -> void { + if(auto layout = _layout()) layout->setEnabled(layout->self().enabled(true)); + pWidget::setEnabled(enabled); +} + +auto pFrame::setFont(const string& font) -> void { + if(auto layout = _layout()) layout->setFont(layout->self().font(true)); + pFont::setFont(gtkLabel, font); +} + +auto pFrame::setGeometry(Geometry geometry) -> void { + pWidget::setGeometry(geometry); + if(auto layout = state().layout) { + Size size = pFont::size(self().font(true), state().text); + if(!state().text) size.setHeight(10); + geometry.setX(geometry.x() + 2); + geometry.setY(geometry.y() + (size.height() - 1)); + geometry.setWidth(geometry.width() - 5); + geometry.setHeight(geometry.height() - (size.height() + 2)); + layout->setGeometry(geometry); + } +} + +auto pFrame::setText(const string& text) -> void { + gtk_label_set_text(GTK_LABEL(gtkLabel), text); +} + +auto pFrame::setVisible(bool visible) -> void { + if(auto layout = _layout()) layout->setVisible(layout->self().visible(true)); + pWidget::setVisible(visible); +} + +auto pFrame::_layout() -> pLayout* { + if(auto layout = state().layout) return layout->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/frame.hpp b/hiro/gtk/widget/frame.hpp new file mode 100644 index 00000000..5d09750e --- /dev/null +++ b/hiro/gtk/widget/frame.hpp @@ -0,0 +1,20 @@ +namespace hiro { + +struct pFrame : pWidget { + Declare(Frame, Widget) + + auto append(shared_pointer<mLayout> layout) -> void; + auto container(mWidget& widget) -> GtkWidget* override; + auto remove(shared_pointer<mLayout> layout) -> void; + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setGeometry(Geometry geometry) -> void override; + auto setText(const string& text) -> void; + auto setVisible(bool visible) -> void override; + + auto _layout() -> pLayout*; + + GtkWidget* gtkLabel = nullptr; +}; + +} diff --git a/phoenix/gtk/widget/hex-edit.cpp b/hiro/gtk/widget/hex-edit.cpp similarity index 57% rename from phoenix/gtk/widget/hex-edit.cpp rename to hiro/gtk/widget/hex-edit.cpp index 08c10a78..03805517 100644 --- a/phoenix/gtk/widget/hex-edit.cpp +++ b/hiro/gtk/widget/hex-edit.cpp @@ -1,103 +1,29 @@ -namespace phoenix { +namespace hiro { -static bool HexEdit_keyPress(GtkWidget* widget, GdkEventKey* event, HexEdit* self) { - return self->p.keyPress(event->keyval, event->state); +static auto HexEdit_keyPress(GtkWidget* widget, GdkEventKey* event, pHexEdit* p) -> signed { + return p->keyPress(event->keyval, event->state); } -static bool HexEdit_mouseScroll(GtkWidget* widget, GdkEventScroll* event, HexEdit* self) { - double position = gtk_range_get_value(GTK_RANGE(self->p.scrollBar)); +static auto HexEdit_mouseScroll(GtkWidget* widget, GdkEventScroll* event, pHexEdit* p) -> signed { + double position = gtk_range_get_value(GTK_RANGE(p->scrollBar)); if(event->direction == GDK_SCROLL_UP) { - self->p.scroll(position - 1); + p->scroll(position - 1); } if(event->direction == GDK_SCROLL_DOWN) { - self->p.scroll(position + 1); + p->scroll(position + 1); } return true; //do not propagate event further } -static bool HexEdit_scroll(GtkRange* range, GtkScrollType scroll, double value, HexEdit* self) { - self->p.scroll((signed)value); +static auto HexEdit_scroll(GtkRange* range, GtkScrollType scroll, double value, pHexEdit* p) -> signed { + p->scroll((signed)value); return true; //do not propagate event further } -bool pHexEdit::focused() { - return GTK_WIDGET_HAS_FOCUS(subWidget) || GTK_WIDGET_HAS_FOCUS(scrollBar); -} - -void pHexEdit::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pHexEdit::setColumns(unsigned columns) { - setScroll(); - update(); -} - -void pHexEdit::setForegroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pHexEdit::setLength(unsigned length) { - setScroll(); - update(); -} - -void pHexEdit::setOffset(unsigned offset) { - setScroll(); - updateScroll(); - update(); -} - -void pHexEdit::setRows(unsigned rows) { - setScroll(); - update(); -} - -void pHexEdit::update() { - if(!hexEdit.onRead) { - gtk_text_buffer_set_text(textBuffer, "", -1); - return; - } - - unsigned position = cursorPosition(); - - string output; - unsigned offset = hexEdit.state.offset; - for(unsigned row = 0; row < hexEdit.state.rows; row++) { - output.append(hex<8>(offset)); - output.append(" "); - - string hexdata; - string ansidata = " "; - for(unsigned column = 0; column < hexEdit.state.columns; column++) { - if(offset < hexEdit.state.length) { - uint8_t data = hexEdit.onRead(offset++); - hexdata.append(hex<2>(data)); - hexdata.append(" "); - ansidata.append(data >= 0x20 && data <= 0x7e ? (char)data : '.'); - } else { - hexdata.append(" "); - ansidata.append(" "); - } - } - - output.append(hexdata); - output.append(ansidata); - if(offset >= hexEdit.state.length) break; - if(row != hexEdit.state.rows - 1) output.append("\n"); - } - - gtk_text_buffer_set_text(textBuffer, output, -1); - if(position == 0) position = 10; //start at first position where hex values can be entered - setCursorPosition(position); -} - -void pHexEdit::constructor() { +auto pHexEdit::construct() -> void { gtkWidget = gtk_hbox_new(false, 0); container = gtk_scrolled_window_new(0, 0); @@ -108,15 +34,11 @@ void pHexEdit::constructor() { gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), false); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_NONE); gtk_container_add(GTK_CONTAINER(container), subWidget); - g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(HexEdit_keyPress), (gpointer)&hexEdit); - g_signal_connect(G_OBJECT(subWidget), "scroll-event", G_CALLBACK(HexEdit_mouseScroll), (gpointer)&hexEdit); scrollBar = gtk_vscrollbar_new((GtkAdjustment*)nullptr); gtk_range_set_range(GTK_RANGE(scrollBar), 0, 255); gtk_range_set_increments(GTK_RANGE(scrollBar), 1, 16); gtk_widget_set_sensitive(scrollBar, false); - g_signal_connect(G_OBJECT(scrollBar), "change-value", G_CALLBACK(HexEdit_scroll), (gpointer)&hexEdit); - g_signal_connect(G_OBJECT(scrollBar), "scroll-event", G_CALLBACK(HexEdit_mouseScroll), (gpointer)&hexEdit); gtk_box_pack_start(GTK_BOX(gtkWidget), container, true, true, 0); gtk_box_pack_start(GTK_BOX(gtkWidget), scrollBar, false, false, 1); @@ -128,38 +50,117 @@ void pHexEdit::constructor() { gtk_widget_show(subWidget); gtk_widget_show(container); - setColumns(hexEdit.state.columns); - setRows(hexEdit.state.rows); - setLength(hexEdit.state.length); - setOffset(hexEdit.state.offset); + setBackgroundColor(state().backgroundColor); + setColumns(state().columns); + setForegroundColor(state().foregroundColor); + setRows(state().rows); + setLength(state().length); + setOffset(state().offset); update(); + + g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(HexEdit_keyPress), (gpointer)this); + g_signal_connect(G_OBJECT(subWidget), "scroll-event", G_CALLBACK(HexEdit_mouseScroll), (gpointer)this); + + g_signal_connect(G_OBJECT(scrollBar), "change-value", G_CALLBACK(HexEdit_scroll), (gpointer)this); + g_signal_connect(G_OBJECT(scrollBar), "scroll-event", G_CALLBACK(HexEdit_mouseScroll), (gpointer)this); + + pWidget::construct(); } -void pHexEdit::destructor() { +auto pHexEdit::destruct() -> void { gtk_widget_destroy(scrollBar); gtk_widget_destroy(subWidget); gtk_widget_destroy(container); gtk_widget_destroy(gtkWidget); } -void pHexEdit::orphan() { - destructor(); - constructor(); +auto pHexEdit::focused() const -> bool { + return GTK_WIDGET_HAS_FOCUS(subWidget) || GTK_WIDGET_HAS_FOCUS(scrollBar); } -unsigned pHexEdit::cursorPosition() { +auto pHexEdit::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pHexEdit::setColumns(unsigned columns) -> void { + setScroll(); + update(); +} + +auto pHexEdit::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pHexEdit::setLength(unsigned length) -> void { + setScroll(); + update(); +} + +auto pHexEdit::setOffset(unsigned offset) -> void { + setScroll(); + updateScroll(); + update(); +} + +auto pHexEdit::setRows(unsigned rows) -> void { + setScroll(); + update(); +} + +auto pHexEdit::update() -> void { + if(!state().onRead) { + gtk_text_buffer_set_text(textBuffer, "", -1); + return; + } + + unsigned position = cursorPosition(); + + string output; + unsigned offset = state().offset; + for(auto row : range(state().rows)) { + output.append(hex<8>(offset)); + output.append(" "); + + string hexdata; + string ansidata = " "; + for(auto column : range(state().columns)) { + if(offset < state().length) { + uint8_t data = self().doRead(offset++); + hexdata.append(hex<2>(data)); + hexdata.append(" "); + ansidata.append(data >= 0x20 && data <= 0x7e ? (char)data : '.'); + } else { + hexdata.append(" "); + ansidata.append(" "); + } + } + + output.append(hexdata); + output.append(ansidata); + if(offset >= state().length) break; + if(row != state().rows - 1) output.append("\n"); + } + + gtk_text_buffer_set_text(textBuffer, output, -1); + if(position == 0) position = 10; //start at first position where hex values can be entered + setCursorPosition(position); +} + +auto pHexEdit::cursorPosition() -> unsigned { GtkTextIter iter; gtk_text_buffer_get_iter_at_mark(textBuffer, &iter, textCursor); return gtk_text_iter_get_offset(&iter); } -bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { - if(!hexEdit.onRead) return false; +auto pHexEdit::keyPress(unsigned scancode, unsigned mask) -> bool { + if(!state().onRead) return false; if(mask & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK)) return false; //allow actions such as Ctrl+C (copy) signed position = cursorPosition(); - signed lineWidth = 10 + (hexEdit.state.columns * 3) + 1 + hexEdit.state.columns + 1; + signed lineWidth = 10 + (state().columns * 3) + 1 + state().columns + 1; signed cursorY = position / lineWidth; signed cursorX = position % lineWidth; @@ -169,16 +170,16 @@ bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { } if(scancode == GDK_End) { - setCursorPosition(cursorY * lineWidth + 10 + (hexEdit.state.columns * 3 - 1)); + setCursorPosition(cursorY * lineWidth + 10 + (state().columns * 3 - 1)); return true; } if(scancode == GDK_Up) { if(cursorY != 0) return false; - signed newOffset = hexEdit.state.offset - hexEdit.state.columns; + signed newOffset = state().offset - state().columns; if(newOffset >= 0) { - hexEdit.setOffset(newOffset); + self().setOffset(newOffset); update(); } return true; @@ -186,36 +187,36 @@ bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { if(scancode == GDK_Down) { if(cursorY >= rows() - 1) return true; - if(cursorY != hexEdit.state.rows - 1) return false; + if(cursorY != state().rows - 1) return false; - signed newOffset = hexEdit.state.offset + hexEdit.state.columns; - if(newOffset + hexEdit.state.columns * hexEdit.state.rows - (hexEdit.state.columns - 1) <= hexEdit.state.length) { - hexEdit.setOffset(newOffset); + signed newOffset = state().offset + state().columns; + if(newOffset + state().columns * state().rows - (state().columns - 1) <= state().length) { + self().setOffset(newOffset); update(); } return true; } if(scancode == GDK_Page_Up) { - signed newOffset = hexEdit.state.offset - hexEdit.state.columns * hexEdit.state.rows; + signed newOffset = state().offset - state().columns * state().rows; if(newOffset >= 0) { - hexEdit.setOffset(newOffset); + self().setOffset(newOffset); } else { - hexEdit.setOffset(0); + self().setOffset(0); } update(); return true; } if(scancode == GDK_Page_Down) { - signed newOffset = hexEdit.state.offset + hexEdit.state.columns * hexEdit.state.rows; - for(unsigned n = 0; n < hexEdit.state.rows; n++) { - if(newOffset + hexEdit.state.columns * hexEdit.state.rows - (hexEdit.state.columns - 1) <= hexEdit.state.length) { - hexEdit.setOffset(newOffset); + signed newOffset = state().offset + state().columns * state().rows; + for(auto n : range(state().rows)) { + if(newOffset + state().columns * state().rows - (state().columns - 1) <= state().length) { + self().setOffset(newOffset); update(); break; } - newOffset -= hexEdit.state.columns; + newOffset -= state().columns; } return true; } @@ -233,12 +234,12 @@ bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { //not on a space bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low cursorX /= 3; - if(cursorX < hexEdit.state.columns) { + if(cursorX < state().columns) { //not in ANSI region - unsigned offset = hexEdit.state.offset + (cursorY * hexEdit.state.columns + cursorX); + unsigned offset = state().offset + (cursorY * state().columns + cursorX); - if(offset >= hexEdit.state.length) return false; //do not edit past end of data - uint8_t data = hexEdit.onRead(offset); + if(offset >= state().length) return false; //do not edit past end of data + uint8_t data = self().doRead(offset); //write modified value if(cursorNibble == 1) { @@ -246,11 +247,11 @@ bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { } else { data = (data & 0x0f) | (scancode << 4); } - if(hexEdit.onWrite) hexEdit.onWrite(offset, data); + self().doWrite(offset, data); //auto-advance cursor to next nibble/byte position++; - if(cursorNibble && cursorX != hexEdit.state.columns - 1) position++; + if(cursorNibble && cursorX != state().columns - 1) position++; setCursorPosition(position); //refresh output to reflect modified data @@ -263,22 +264,22 @@ bool pHexEdit::keyPress(unsigned scancode, unsigned mask) { } //number of actual rows -signed pHexEdit::rows() { - return (max(1u, hexEdit.state.length) + hexEdit.state.columns - 1) / hexEdit.state.columns; +auto pHexEdit::rows() -> signed { + return (max(1u, state().length) + state().columns - 1) / state().columns; } //number of scrollable row positions -signed pHexEdit::rowsScrollable() { - return max(0u, rows() - hexEdit.state.rows); +auto pHexEdit::rowsScrollable() -> signed { + return max(0u, rows() - state().rows); } -void pHexEdit::scroll(signed position) { +auto pHexEdit::scroll(signed position) -> void { if(position > rowsScrollable()) position = rowsScrollable(); if(position < 0) position = 0; - hexEdit.setOffset(position * hexEdit.state.columns); + self().setOffset(position * state().columns); } -void pHexEdit::setCursorPosition(unsigned position) { +auto pHexEdit::setCursorPosition(unsigned position) -> void { GtkTextIter iter; gtk_text_buffer_get_iter_at_mark(textBuffer, &iter, textCursor); @@ -291,7 +292,7 @@ void pHexEdit::setCursorPosition(unsigned position) { gtk_text_buffer_place_cursor(textBuffer, &iter); } -void pHexEdit::setScroll() { +auto pHexEdit::setScroll() -> void { if(rowsScrollable() > 0) { gtk_range_set_range(GTK_RANGE(scrollBar), 0, rowsScrollable()); gtk_widget_set_sensitive(scrollBar, true); @@ -300,8 +301,8 @@ void pHexEdit::setScroll() { } } -void pHexEdit::updateScroll() { - unsigned row = hexEdit.state.offset / hexEdit.state.columns; +auto pHexEdit::updateScroll() -> void { + unsigned row = state().offset / state().columns; gtk_range_set_value(GTK_RANGE(scrollBar), row); } diff --git a/hiro/gtk/widget/hex-edit.hpp b/hiro/gtk/widget/hex-edit.hpp new file mode 100644 index 00000000..685d7d28 --- /dev/null +++ b/hiro/gtk/widget/hex-edit.hpp @@ -0,0 +1,31 @@ +namespace hiro { + +struct pHexEdit : pWidget { + Declare(HexEdit, Widget) + + auto focused() const -> bool override; + auto setBackgroundColor(Color color) -> void; + auto setColumns(unsigned columns) -> void; + auto setForegroundColor(Color color) -> void; + auto setLength(unsigned length) -> void; + auto setOffset(unsigned offset) -> void; + auto setRows(unsigned rows) -> void; + auto update() -> void; + + auto cursorPosition() -> unsigned; + auto keyPress(unsigned scancode, unsigned mask) -> bool; + auto rows() -> signed; + auto rowsScrollable() -> signed; + auto scroll(signed position) -> void; + auto setCursorPosition(unsigned position) -> void; + auto setScroll() -> void; + auto updateScroll() -> void; + + GtkWidget* container = nullptr; + GtkWidget* subWidget = nullptr; + GtkWidget* scrollBar = nullptr; + GtkTextBuffer* textBuffer = nullptr; + GtkTextMark* textCursor = nullptr; +}; + +} diff --git a/hiro/gtk/widget/horizontal-scroller.cpp b/hiro/gtk/widget/horizontal-scroller.cpp new file mode 100644 index 00000000..d8dc7ede --- /dev/null +++ b/hiro/gtk/widget/horizontal-scroller.cpp @@ -0,0 +1,41 @@ +namespace hiro { + +static auto HorizontalScroller_change(GtkRange* gtkRange, pHorizontalScroller* p) -> void { + auto position = (unsigned)gtk_range_get_value(gtkRange); + if(p->state().position == position) return; + p->state().position = position; + if(!p->locked()) p->self().doChange(); +} + +auto pHorizontalScroller::construct() -> void { + gtkWidget = gtk_hscrollbar_new(0); + + setLength(state().length); + setPosition(state().position); + + g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScroller_change), (gpointer)this); + + pWidget::construct(); +} + +auto pHorizontalScroller::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pHorizontalScroller::minimumSize() const -> Size { + return {0, 20}; +} + +auto pHorizontalScroller::setLength(unsigned length) -> void { + lock(); + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); + unlock(); +} + +auto pHorizontalScroller::setPosition(unsigned position) -> void { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +} diff --git a/hiro/gtk/widget/horizontal-scroller.hpp b/hiro/gtk/widget/horizontal-scroller.hpp new file mode 100644 index 00000000..a522f0bb --- /dev/null +++ b/hiro/gtk/widget/horizontal-scroller.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pHorizontalScroller : pWidget { + Declare(HorizontalScroller, Widget) + + auto minimumSize() const -> Size; + auto setLength(unsigned length) -> void; + auto setPosition(unsigned position) -> void; +}; + +} diff --git a/hiro/gtk/widget/horizontal-slider.cpp b/hiro/gtk/widget/horizontal-slider.cpp new file mode 100644 index 00000000..dbd2c379 --- /dev/null +++ b/hiro/gtk/widget/horizontal-slider.cpp @@ -0,0 +1,40 @@ +namespace hiro { + +static auto HorizontalSlider_change(GtkRange* gtkRange, pHorizontalSlider* p) -> void { + auto position = (unsigned)gtk_range_get_value(gtkRange); + if(p->state().position == position) return; + p->state().position = position; + if(!p->locked()) p->self().doChange(); +} + +auto pHorizontalSlider::construct() -> void { + gtkWidget = gtk_hscale_new_with_range(0, 100, 1); + gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); + + setLength(state().length); + setPosition(state().position); + + g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)this); + + pWidget::construct(); +} + +auto pHorizontalSlider::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pHorizontalSlider::minimumSize() const -> Size { + return {0, 20}; +} + +auto pHorizontalSlider::setLength(unsigned length) -> void { + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); +} + +auto pHorizontalSlider::setPosition(unsigned position) -> void { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +} diff --git a/hiro/gtk/widget/horizontal-slider.hpp b/hiro/gtk/widget/horizontal-slider.hpp new file mode 100644 index 00000000..c24fc004 --- /dev/null +++ b/hiro/gtk/widget/horizontal-slider.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pHorizontalSlider : pWidget { + Declare(HorizontalSlider, Widget) + + auto minimumSize() const -> Size; + auto setLength(unsigned length) -> void; + auto setPosition(unsigned position) -> void; +}; + +} diff --git a/hiro/gtk/widget/icon-view-item.cpp b/hiro/gtk/widget/icon-view-item.cpp new file mode 100644 index 00000000..fa985855 --- /dev/null +++ b/hiro/gtk/widget/icon-view-item.cpp @@ -0,0 +1,32 @@ +namespace hiro { + +auto pIconViewItem::construct() -> void { +} + +auto pIconViewItem::destruct() -> void { +} + +auto pIconViewItem::setIcon(const image& icon) -> void { + if(auto parent = _parent()) { + parent->setItemIcon(self().offset(), icon); + } +} + +auto pIconViewItem::setSelected(bool selected) -> void { + if(auto parent = _parent()) { + parent->setItemSelected(self().offset(), selected); + } +} + +auto pIconViewItem::setText(const string& text) -> void { + if(auto parent = _parent()) { + parent->setItemText(self().offset(), text); + } +} + +auto pIconViewItem::_parent() -> pIconView* { + if(auto parent = self().parentIconView()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/icon-view-item.hpp b/hiro/gtk/widget/icon-view-item.hpp new file mode 100644 index 00000000..4e8fad46 --- /dev/null +++ b/hiro/gtk/widget/icon-view-item.hpp @@ -0,0 +1,13 @@ +namespace hiro { + +struct pIconViewItem : pObject { + Declare(IconViewItem, Object) + + auto setIcon(const image& icon) -> void; + auto setSelected(bool selected) -> void; + auto setText(const string& text) -> void; + + auto _parent() -> pIconView*; +}; + +} diff --git a/hiro/gtk/widget/icon-view.cpp b/hiro/gtk/widget/icon-view.cpp new file mode 100644 index 00000000..73f242eb --- /dev/null +++ b/hiro/gtk/widget/icon-view.cpp @@ -0,0 +1,224 @@ +namespace hiro { + +static auto IconView_activate(GtkIconView* iconView, GtkTreePath* path, pIconView* p) -> void { + if(!p->locked()) p->self().doActivate(); +} + +static auto IconView_buttonEvent(GtkTreeView* treeView, GdkEventButton* event, pIconView* p) -> signed { + if(event->type == GDK_BUTTON_RELEASE && event->button == 3) { + if(!p->locked()) p->self().doContext(); + return false; + } + + return false; +} + +static auto IconView_change(GtkIconView* iconView, pIconView* p) -> void { + p->_updateSelected(); +} + +auto pIconView::construct() -> void { + gtkWidget = gtk_scrolled_window_new(0, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); + + store = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); + subWidget = gtk_icon_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(subWidget), 0); + gtk_icon_view_set_text_column(GTK_ICON_VIEW(subWidget), 1); + gtk_icon_view_set_reorderable(GTK_ICON_VIEW(subWidget), false); + gtk_icon_view_set_margin(GTK_ICON_VIEW(subWidget), 0); + gtk_icon_view_set_spacing(GTK_ICON_VIEW(subWidget), 0); + gtk_icon_view_set_column_spacing(GTK_ICON_VIEW(subWidget), 0); + gtk_icon_view_set_row_spacing(GTK_ICON_VIEW(subWidget), 0); + gtk_icon_view_set_item_padding(GTK_ICON_VIEW(subWidget), 0); + gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); + + gtk_widget_show(subWidget); + + setBackgroundColor(state().backgroundColor); + setFlow(state().flow); + setForegroundColor(state().foregroundColor); + setMultiSelect(state().multiSelect); + setOrientation(state().orientation); + for(auto position : range(self().items())) { + auto& item = state().items[position]; + append(item); + } + _updateSelected(); + + g_signal_connect(G_OBJECT(subWidget), "button-press-event", G_CALLBACK(IconView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(subWidget), "button-release-event", G_CALLBACK(IconView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(subWidget), "item-activated", G_CALLBACK(IconView_activate), (gpointer)this); + g_signal_connect(G_OBJECT(subWidget), "selection-changed", G_CALLBACK(IconView_change), (gpointer)this); + + pWidget::construct(); +} + +auto pIconView::destruct() -> void { + gtk_widget_destroy(subWidget); + gtk_widget_destroy(gtkWidget); +} + +auto pIconView::append(sIconViewItem item) -> void { + GtkTreeIter iter; + gtk_list_store_append(store, &iter); + setItemIcon(item->offset(), item->state.icon); + setItemSelected(item->offset(), item->state.selected); + setItemText(item->offset(), item->state.text); +} + +auto pIconView::remove(sIconViewItem item) -> void { + lock(); + GtkTreeIter iter; + if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{item->offset()})) { + gtk_list_store_remove(store, &iter); + } + _updateSelected(); + unlock(); +} + +auto pIconView::reset() -> void { + lock(); + gtk_list_store_clear(store); + _updateSelected(); + unlock(); +} + +auto pIconView::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pIconView::setFlow(Orientation flow) -> void { + //GTK+ does not support vertical flow ... the closest we can get is a horizontal flow with only one column + if(flow == Orientation::Horizontal) { + gtk_icon_view_set_columns(GTK_ICON_VIEW(subWidget), -1); + gtk_icon_view_set_item_width(GTK_ICON_VIEW(subWidget), -1); + } else { + gtk_icon_view_set_columns(GTK_ICON_VIEW(subWidget), 1); + gtk_icon_view_set_item_width(GTK_ICON_VIEW(subWidget), max(128, pSizable::state().geometry.width() - 64)); + } +} + +auto pIconView::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pIconView::setGeometry(Geometry geometry) -> void { + pWidget::setGeometry(geometry); + if(state().flow == Orientation::Vertical) { + gtk_icon_view_set_item_width(GTK_ICON_VIEW(subWidget), max(128, pSizable::state().geometry.width() - 64)); + } +} + +auto pIconView::setItemIcon(unsigned position, const image& icon) -> void { + if(position >= self().items()) return; + GtkTreeIter iter; + if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{position})) { + if(icon) { + GdkPixbuf* pixbuf = CreatePixbuf(icon); + gtk_list_store_set(store, &iter, 0, pixbuf, -1); + } else { + gtk_list_store_set(store, &iter, 0, nullptr, -1); + } + } +} + +auto pIconView::setItemSelected(unsigned position, bool selected) -> void { + if(position >= self().items()) return; + lock(); + GtkTreePath* path = gtk_tree_path_new_from_string(string{position}); + if(selected) { + gtk_icon_view_select_path(GTK_ICON_VIEW(subWidget), path); + } else { + gtk_icon_view_unselect_path(GTK_ICON_VIEW(subWidget), path); + } + gtk_tree_path_free(path); + _updateSelected(); + unlock(); +} + +auto pIconView::setItemSelected(const vector<signed>& selections) -> void { + lock(); + setItemSelectedNone(); + for(auto& position : selections) setItemSelected(position, true); + _updateSelected(); + unlock(); +} + +auto pIconView::setItemSelectedAll() -> void { + lock(); + gtk_icon_view_select_all(GTK_ICON_VIEW(subWidget)); + _updateSelected(); + unlock(); +} + +auto pIconView::setItemSelectedNone() -> void { + lock(); + gtk_icon_view_unselect_all(GTK_ICON_VIEW(subWidget)); + _updateSelected(); + unlock(); +} + +auto pIconView::setItemText(unsigned position, const string& text) -> void { + if(position >= self().items()) return; + GtkTreeIter iter; + if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{position})) { + gtk_list_store_set(store, &iter, 1, (const char*)text, -1); + } +} + +auto pIconView::setMultiSelect(bool multiSelect) -> void { + gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(subWidget), + multiSelect ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE + ); +} + +auto pIconView::setOrientation(Orientation orientation) -> void { + gtk_icon_view_set_item_orientation(GTK_ICON_VIEW(subWidget), + orientation == Orientation::Horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL + ); +} + +auto pIconView::_updateSelected() -> void { + vector<unsigned> selected; + + GList* list = gtk_icon_view_get_selected_items(GTK_ICON_VIEW(subWidget)); + GList* p = list; + + while(p) { + auto path = (GtkTreePath*)p->data; + char* pathString = gtk_tree_path_to_string(path); + unsigned position = decimal(pathString); + g_free(pathString); + selected.append(position); + p = p->next; + } + + g_list_foreach(list, (GFunc)gtk_tree_path_free, nullptr); + g_list_free(list); + + bool identical = selected.size() == currentSelection.size(); + if(identical) { + for(unsigned n = 0; n < selected.size(); n++) { + if(selected[n] != currentSelection[n]) { + identical = false; + break; + } + } + } + if(identical) return; + + currentSelection = selected; + for(auto& item : state().items) item->state.selected = false; + for(auto& position : currentSelection) { + if(position >= self().items()) continue; + state().items[position]->state.selected = true; + } + + if(!locked()) self().doChange(); +} + +} diff --git a/hiro/gtk/widget/icon-view.hpp b/hiro/gtk/widget/icon-view.hpp new file mode 100644 index 00000000..41447b6b --- /dev/null +++ b/hiro/gtk/widget/icon-view.hpp @@ -0,0 +1,29 @@ +namespace hiro { + +struct pIconView : pWidget { + Declare(IconView, Widget) + + auto append(sIconViewItem item) -> void; + auto remove(sIconViewItem item) -> void; + auto reset() -> void; + auto setBackgroundColor(Color color) -> void; + auto setFlow(Orientation flow) -> void; + auto setForegroundColor(Color color) -> void; + auto setGeometry(Geometry geometry) -> void; + auto setItemIcon(unsigned position, const image& icon) -> void; + auto setItemSelected(unsigned position, bool selected) -> void; + auto setItemSelected(const vector<signed>& selections) -> void; + auto setItemSelectedAll() -> void; + auto setItemSelectedNone() -> void; + auto setItemText(unsigned position, const string& text) -> void; + auto setMultiSelect(bool multiSelect) -> void; + auto setOrientation(Orientation orientation) -> void; + + auto _updateSelected() -> void; + + GtkWidget* subWidget = nullptr; + GtkListStore* store = nullptr; + vector<unsigned> currentSelection; +}; + +} diff --git a/hiro/gtk/widget/label.cpp b/hiro/gtk/widget/label.cpp new file mode 100644 index 00000000..69766178 --- /dev/null +++ b/hiro/gtk/widget/label.cpp @@ -0,0 +1,41 @@ +namespace hiro { + +auto pLabel::construct() -> void { + gtkWidget = gtk_label_new(""); + + _setAlignment(); + setText(state().text); + + pWidget::construct(); +} + +auto pLabel::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pLabel::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + return {size.width(), size.height()}; +} + +auto pLabel::setHorizontalAlignment(double alignment) -> void { + _setAlignment(); +} + +auto pLabel::setText(const string& text) -> void { + gtk_label_set_text(GTK_LABEL(gtkWidget), text); +} + +auto pLabel::setVerticalAlignment(double alignment) -> void { + _setAlignment(); +} + +auto pLabel::_setAlignment() -> void { + gtk_misc_set_alignment(GTK_MISC(gtkWidget), state().horizontalAlignment, state().verticalAlignment); + auto justify = GTK_JUSTIFY_CENTER; + if(state().horizontalAlignment < 0.333) justify = GTK_JUSTIFY_LEFT; + if(state().horizontalAlignment > 0.666) justify = GTK_JUSTIFY_RIGHT; + gtk_label_set_justify(GTK_LABEL(gtkWidget), justify); +} + +} diff --git a/hiro/gtk/widget/label.hpp b/hiro/gtk/widget/label.hpp new file mode 100644 index 00000000..6a79bb14 --- /dev/null +++ b/hiro/gtk/widget/label.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pLabel : pWidget { + Declare(Label, Widget) + + auto minimumSize() const -> Size override; + auto setHorizontalAlignment(double alignment) -> void; + auto setText(const string& text) -> void; + auto setVerticalAlignment(double alignment) -> void; + + auto _setAlignment() -> void; +}; + +} diff --git a/hiro/gtk/widget/line-edit.cpp b/hiro/gtk/widget/line-edit.cpp new file mode 100644 index 00000000..0fb689b5 --- /dev/null +++ b/hiro/gtk/widget/line-edit.cpp @@ -0,0 +1,55 @@ +namespace hiro { + +static auto LineEdit_activate(GtkEntry*, pLineEdit* p) -> void { + p->self().doActivate(); +} + +static auto LineEdit_change(GtkEditable*, pLineEdit* p) -> void { + p->state().text = gtk_entry_get_text(GTK_ENTRY(p->gtkWidget)); + if(!p->locked()) p->self().doChange(); +} + +auto pLineEdit::construct() -> void { + gtkWidget = gtk_entry_new(); + + setBackgroundColor(state().backgroundColor); + setEditable(state().editable); + setForegroundColor(state().foregroundColor); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkWidget), "activate", G_CALLBACK(LineEdit_activate), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "changed", G_CALLBACK(LineEdit_change), (gpointer)this); + + pWidget::construct(); +} + +auto pLineEdit::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pLineEdit::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + return {size.width() + 10, size.height() + 10}; +} + +auto pLineEdit::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(gtkWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pLineEdit::setEditable(bool editable) -> void { + gtk_editable_set_editable(GTK_EDITABLE(gtkWidget), editable); +} + +auto pLineEdit::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(gtkWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pLineEdit::setText(const string& text) -> void { + lock(); + gtk_entry_set_text(GTK_ENTRY(gtkWidget), text); + unlock(); +} + +} diff --git a/hiro/gtk/widget/line-edit.hpp b/hiro/gtk/widget/line-edit.hpp new file mode 100644 index 00000000..243278d6 --- /dev/null +++ b/hiro/gtk/widget/line-edit.hpp @@ -0,0 +1,13 @@ +namespace hiro { + +struct pLineEdit : pWidget { + Declare(LineEdit, Widget) + + auto minimumSize() const -> Size; + auto setBackgroundColor(Color color) -> void; + auto setEditable(bool editable) -> void; + auto setForegroundColor(Color color) -> void; + auto setText(const string& text) -> void; +}; + +} diff --git a/hiro/gtk/widget/list-view-column.cpp b/hiro/gtk/widget/list-view-column.cpp new file mode 100644 index 00000000..ffe9ae24 --- /dev/null +++ b/hiro/gtk/widget/list-view-column.cpp @@ -0,0 +1,133 @@ +namespace hiro { + +auto pListViewColumn::construct() -> void { + unsigned offset = self().offset(); + + gtkHeader = gtk_hbox_new(false, 0); + + gtkHeaderIcon = gtk_image_new(); + gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderIcon, false, false, 0); + + gtkHeaderText = gtk_label_new(state().text); + gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderText, true, false, 2); + + gtkColumn = gtk_tree_view_column_new(); + gtk_tree_view_column_set_sizing(gtkColumn, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_title(gtkColumn, ""); + gtk_tree_view_column_set_widget(gtkColumn, gtkHeader); + + if(offset == 0) { + gtkCellToggle = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(gtkColumn, gtkCellToggle, false); + gtk_tree_view_column_set_attributes(gtkColumn, gtkCellToggle, "active", 0, nullptr); + } + + gtkCellIcon = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(gtkColumn, gtkCellIcon, false); + gtk_tree_view_column_set_attributes(gtkColumn, gtkCellIcon, "pixbuf", 1 + offset * 2 + 0, nullptr); + + gtkCellText = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(gtkColumn, gtkCellText, false); + gtk_tree_view_column_set_attributes(gtkColumn, gtkCellText, "text", 1 + offset * 2 + 1, nullptr); + + g_signal_connect(G_OBJECT(gtkColumn), "clicked", G_CALLBACK(ListView_headerActivate), (gpointer)_parent()); + g_signal_connect(G_OBJECT(gtkCellText), "edited", G_CALLBACK(ListView_edit), (gpointer)_parent()); + if(gtkCellToggle) g_signal_connect(G_OBJECT(gtkCellToggle), "toggled", G_CALLBACK(ListView_toggle), (gpointer)_parent()); +} + +auto pListViewColumn::destruct() -> void { +} + +auto pListViewColumn::setActive() -> void { + if(auto parent = _parent()) { + gtk_tree_view_set_search_column(parent->gtkTreeView, 1 + self().offset() * 2 + 1); + } +} + +auto pListViewColumn::setBackgroundColor(Color color) -> void { + if(color) { + GdkColor gdkColor = CreateColor(color); + if(gtkCellToggle) g_object_set(G_OBJECT(gtkCellToggle), "cell-background-gdk", &gdkColor, nullptr); + g_object_set(G_OBJECT(gtkCellIcon), "cell-background-gdk", &gdkColor, nullptr); + g_object_set(G_OBJECT(gtkCellText), "cell-background-gdk", &gdkColor, nullptr); + } else { + if(gtkCellToggle) g_object_set(G_OBJECT(gtkCellToggle), "cell-background-set", FALSE, nullptr); + g_object_set(G_OBJECT(gtkCellIcon), "cell-background-set", FALSE, nullptr); + g_object_set(G_OBJECT(gtkCellText), "cell-background-set", FALSE, nullptr); + } +} + +auto pListViewColumn::setEditable(bool editable) -> void { + g_object_set(G_OBJECT(gtkCellText), "editable", editable ? TRUE : FALSE, nullptr); +} + +auto pListViewColumn::setFont(const string& font) -> void { + pFont::setFont(gtkHeaderText, font); + auto fontDescription = pFont::create(font); + g_object_set(G_OBJECT(gtkCellText), "font-desc", fontDescription, nullptr); + pango_font_description_free(fontDescription); +} + +auto pListViewColumn::setForegroundColor(Color color) -> void { + if(color) { + GdkColor gdkColor = CreateColor(color); + g_object_set(G_OBJECT(gtkCellText), "foreground-gdk", &gdkColor, nullptr); + } else { + g_object_set(G_OBJECT(gtkCellText), "foreground-set", FALSE, nullptr); + } +} + +auto pListViewColumn::setHorizontalAlignment(double alignment) -> void { + _setAlignment(); +} + +auto pListViewColumn::setIcon(const image& icon) -> void { + if(icon) { + gtk_image_set_from_pixbuf(GTK_IMAGE(gtkHeaderIcon), CreatePixbuf(icon)); + } else { + gtk_image_clear(GTK_IMAGE(gtkHeaderIcon)); + } +} + +auto pListViewColumn::setResizable(bool resizable) -> void { + gtk_tree_view_column_set_resizable(gtkColumn, resizable); +} + +auto pListViewColumn::setSortable(bool sortable) -> void { + gtk_tree_view_column_set_clickable(gtkColumn, sortable); +} + +auto pListViewColumn::setText(const string& text) -> void { + gtk_label_set_text(GTK_LABEL(gtkHeaderText), text); +} + +auto pListViewColumn::setVerticalAlignment(double alignment) -> void { + _setAlignment(); +} + +auto pListViewColumn::setVisible(bool visible) -> void { + gtk_tree_view_column_set_visible(gtkColumn, visible); +} + +auto pListViewColumn::setWidth(signed width) -> void { + if(auto parent = _parent()) { + parent->resizeColumns(); + } +} + +auto pListViewColumn::_parent() -> pListView* { + if(auto parent = self().parentListView()) return parent->self(); + return nullptr; +} + +auto pListViewColumn::_setAlignment() -> void { + gtk_tree_view_column_set_alignment(gtkColumn, state().horizontalAlignment); + gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(gtkCellText), state().horizontalAlignment, state().verticalAlignment); + //set multi-line text alignment + auto pangoAlignment = PANGO_ALIGN_CENTER; + if(state().horizontalAlignment < 0.333) pangoAlignment = PANGO_ALIGN_LEFT; + if(state().horizontalAlignment > 0.666) pangoAlignment = PANGO_ALIGN_RIGHT; + g_object_set(G_OBJECT(gtkCellText), "alignment", pangoAlignment, nullptr); +} + +} diff --git a/hiro/gtk/widget/list-view-column.hpp b/hiro/gtk/widget/list-view-column.hpp new file mode 100644 index 00000000..42394ad1 --- /dev/null +++ b/hiro/gtk/widget/list-view-column.hpp @@ -0,0 +1,32 @@ +namespace hiro { + +struct pListViewColumn : pObject { + Declare(ListViewColumn, Object) + + auto setActive() -> void; + auto setBackgroundColor(Color color) -> void; + auto setEditable(bool editable) -> void; + auto setFont(const string& font) -> void override; + auto setForegroundColor(Color color) -> void; + auto setHorizontalAlignment(double alignment) -> void; + auto setIcon(const image& icon) -> void; + auto setResizable(bool resizable) -> void; + auto setSortable(bool sortable) -> void; + auto setText(const string& text) -> void; + auto setVerticalAlignment(double alignment) -> void; + auto setVisible(bool visible) -> void override; + auto setWidth(signed width) -> void; + + auto _parent() -> pListView*; + auto _setAlignment() -> void; + + GtkTreeViewColumn* gtkColumn = nullptr; + GtkWidget* gtkHeader = nullptr; + GtkWidget* gtkHeaderIcon = nullptr; + GtkWidget* gtkHeaderText = nullptr; + GtkCellRenderer* gtkCellToggle = nullptr; + GtkCellRenderer* gtkCellIcon = nullptr; + GtkCellRenderer* gtkCellText = nullptr; +}; + +} diff --git a/hiro/gtk/widget/list-view-item.cpp b/hiro/gtk/widget/list-view-item.cpp new file mode 100644 index 00000000..3e7617dd --- /dev/null +++ b/hiro/gtk/widget/list-view-item.cpp @@ -0,0 +1,59 @@ +namespace hiro { + +auto pListViewItem::construct() -> void { +} + +auto pListViewItem::destruct() -> void { +} + +auto pListViewItem::setChecked(bool checked) -> void { + if(auto parent = _parent()) { + gtk_list_store_set(parent->gtkListStore, >kIter, 0, checked, -1); + } +} + +auto pListViewItem::setFocused() -> void { + if(auto parent = _parent()) { + GtkTreePath* path = gtk_tree_path_new_from_string(string{self().offset()}); + gtk_tree_view_set_cursor(parent->gtkTreeView, path, nullptr, false); + gtk_tree_view_scroll_to_cell(parent->gtkTreeView, path, nullptr, true, 0.5, 0.0); + gtk_tree_path_free(path); + } +} + +auto pListViewItem::setIcon(unsigned column, const image& icon) -> void { + if(auto parent = _parent()) { + if(icon) { + auto pixbuf = CreatePixbuf(icon, true); + gtk_list_store_set(parent->gtkListStore, >kIter, 1 + column * 2, pixbuf, -1); + } else { + gtk_list_store_set(parent->gtkListStore, >kIter, 1 + column * 2, nullptr, -1); + } + } +} + +auto pListViewItem::setSelected(bool selected) -> void { + if(auto parent = _parent()) { + parent->lock(); + if(selected) { + gtk_tree_selection_select_iter(parent->gtkTreeSelection, >kIter); + } else { + gtk_tree_selection_unselect_iter(parent->gtkTreeSelection, >kIter); + } + parent->_updateSelected(); + parent->unlock(); + } +} + +auto pListViewItem::setText(unsigned column, const string& text) -> void { + if(auto parent = _parent()) { + gtk_list_store_set(parent->gtkListStore, >kIter, 1 + column * 2 + 1, text.data(), -1); + } +} + +auto pListViewItem::_parent() -> pListView* { + if(auto parent = self().parentListView()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/list-view-item.hpp b/hiro/gtk/widget/list-view-item.hpp new file mode 100644 index 00000000..fd584e3b --- /dev/null +++ b/hiro/gtk/widget/list-view-item.hpp @@ -0,0 +1,17 @@ +namespace hiro { + +struct pListViewItem : pObject { + Declare(ListViewItem, Object) + + auto setChecked(bool checked) -> void; + auto setFocused() -> void; + auto setIcon(unsigned column, const image& icon) -> void; + auto setSelected(bool selected) -> void; + auto setText(unsigned column, const string& text) -> void; + + auto _parent() -> pListView*; + + GtkTreeIter gtkIter; +}; + +} diff --git a/hiro/gtk/widget/list-view.cpp b/hiro/gtk/widget/list-view.cpp new file mode 100644 index 00000000..79b75943 --- /dev/null +++ b/hiro/gtk/widget/list-view.cpp @@ -0,0 +1,369 @@ +namespace hiro { + +static auto ListView_activate(GtkTreeView*, GtkTreePath*, GtkTreeViewColumn*, pListView* p) -> void { return p->_doActivate(); } +static auto ListView_buttonEvent(GtkTreeView* treeView, GdkEventButton* event, pListView* p) -> signed { return p->_doEvent(event); } +static auto ListView_change(GtkTreeSelection*, pListView* p) -> void { return p->_doChange(); } +static auto ListView_edit(GtkCellRendererText* renderer, const char* path, const char* text, pListView* p) -> void { return p->_doEdit(renderer, path, text); } +static auto ListView_headerActivate(GtkTreeViewColumn* column, pListView* p) -> void { return p->_doHeaderActivate(column); } +static auto ListView_mouseMoveEvent(GtkWidget*, GdkEvent*, pListView* p) -> signed { return p->_doMouseMove(); } +static auto ListView_popup(GtkTreeView*, pListView* p) -> void { return p->_doContext(); } +static auto ListView_toggle(GtkCellRendererToggle*, const char* path, pListView* p) -> void { return p->_doToggle(path); } + +auto pListView::construct() -> void { + gtkWidget = gtk_scrolled_window_new(0, 0); + gtkScrolledWindow = GTK_SCROLLED_WINDOW(gtkWidget); + gtk_scrolled_window_set_policy(gtkScrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(gtkScrolledWindow, GTK_SHADOW_ETCHED_IN); + + gtkWidgetChild = gtk_tree_view_new(); + gtkTreeView = GTK_TREE_VIEW(gtkWidgetChild); + gtkTreeSelection = gtk_tree_view_get_selection(gtkTreeView); + gtk_container_add(GTK_CONTAINER(gtkWidget), gtkWidgetChild); + gtk_tree_view_set_rubber_banding(gtkTreeView, true); + + gtk_widget_show(gtkWidgetChild); + + setBackgroundColor(state().backgroundColor); + setCheckable(state().checkable); + setFont(self().font(true)); + setForegroundColor(state().foregroundColor); + setGridVisible(state().gridVisible); + setHeaderVisible(state().headerVisible); + setMultiSelect(state().multiSelect); + + g_signal_connect(G_OBJECT(gtkTreeView), "button-press-event", G_CALLBACK(ListView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeView), "button-release-event", G_CALLBACK(ListView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeView), "motion-notify-event", G_CALLBACK(ListView_mouseMoveEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeView), "popup-menu", G_CALLBACK(ListView_popup), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeView), "row-activated", G_CALLBACK(ListView_activate), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeSelection), "changed", G_CALLBACK(ListView_change), (gpointer)this); + + pWidget::construct(); +} + +auto pListView::destruct() -> void { + gtk_widget_destroy(gtkWidgetChild); + gtk_widget_destroy(gtkWidget); +} + +auto pListView::append(sListViewColumn column) -> void { + gtk_tree_view_append_column(gtkTreeView, column->self()->gtkColumn); + gtk_widget_show_all(column->self()->gtkHeader); + column->setFont(column->font()); + setCheckable(state().checkable); + _createModel(); + gtk_tree_view_set_rules_hint(gtkTreeView, self().columns() >= 2); //two or more columns + checkbutton column +} + +auto pListView::append(sListViewItem item) -> void { + gtk_list_store_append(gtkListStore, &item->self()->gtkIter); + + item->setChecked(item->checked()); + item->setSelected(item->selected()); + for(auto column : range(self().columns())) { + item->setIcon(column, item->state.icon(column, {})); + item->setText(column, item->state.text(column, "")); + } +} + +auto pListView::focused() -> bool { + return GTK_WIDGET_HAS_FOCUS(gtkTreeView); +} + +auto pListView::remove(sListViewColumn column) -> void { + if(auto delegate = column->self()) { + gtk_tree_view_remove_column(gtkTreeView, delegate->gtkColumn); + delegate->gtkColumn = nullptr; + } + _createModel(); + gtk_tree_view_set_rules_hint(gtkTreeView, self().columns() >= 2); //two or more columns + checkbutton column +} + +auto pListView::remove(sListViewItem item) -> void { + lock(); + if(auto delegate = item->self()) { + gtk_list_store_remove(gtkListStore, &delegate->gtkIter); + _updateSelected(); + } + unlock(); +} + +auto pListView::reset() -> void { + GList* list = gtk_tree_view_get_columns(gtkTreeView), *p = list; + while(p && p->data) { + gtk_tree_view_remove_column(gtkTreeView, (GtkTreeViewColumn*)p->data); + p = p->next; + } + g_list_free(list); + _createModel(); + gtk_tree_view_set_rules_hint(gtkTreeView, false); +} + +//column widths: +//< 0 = expanding (consume all remaining space) +// 0 = auto (resize to contents +//> 0 = fixed width +auto pListView::resizeColumns() -> void { + lock(); + + //compute the minimum width required for each column based upon the contents of all rows + vector<signed> minimumWidths; + for(auto column : range(self().columns())) { + signed maximumWidth = 1; + if(self().headerVisible()) { + maximumWidth = max(maximumWidth, 8 //margin + + state().columns[column]->state.icon.width + + Font::size(state().columns[column]->font(true), state().columns[column]->state.text).width() + ); + } + for(auto row : range(self().items())) { + maximumWidth = max(maximumWidth, 8 //margin + + (row == 0 && state().checkable ? 24 : 0) //check box + + state().items[row]->state.icon(column, {}).width + + Font::size(state().columns[column]->font(true), state().items[row]->state.text(column, "")).width() + ); + } + if(!state().columns[column]->visible()) maximumWidth = 1; + minimumWidths.append(maximumWidth); + } + + //subtract the widths of all non-expanding columns from the available widget space + signed expansions = 0; //count the number of expanded columns + signed emptyWidth = pSizable::state().geometry.width() - 5; //margin + for(auto column : range(self().columns())) { + signed width = state().columns[column]->width(); + if(!state().columns[column]->visible()) width = 1; + if(width < 0) { expansions++; continue; } + if(width == 0) width = minimumWidths[column]; + emptyWidth -= width; + } + + //the vertical scroll bar consumes header space when visible; subtract it from available space if needed + auto scrollBar = gtk_scrolled_window_get_vscrollbar(gtkScrolledWindow); + if(scrollBar && gtk_widget_get_visible(scrollBar)) { + emptyWidth -= scrollBar->allocation.width; + } + + //divide remaining space among all expanded columns + if(expansions && emptyWidth >= expansions) emptyWidth /= expansions; + else emptyWidth = 1; + + for(auto column : range(self().columns())) { + signed width = state().columns[column]->width(); + if(!state().columns[column]->visible()) width = 1; + if(width < 0) width = emptyWidth; + if(width == 0) width = minimumWidths[column]; + gtk_tree_view_column_set_fixed_width(_column(column)->gtkColumn, width); + } + + unlock(); +} + +auto pListView::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pListView::setCheckable(bool checkable) -> void { + if(auto delegate = _column(0)) { + gtk_cell_renderer_set_visible(delegate->gtkCellToggle, checkable); + } +} + +auto pListView::setChecked(bool checked) -> void { + for(auto& item : state().items) { + if(auto delegate = item->self()) delegate->setChecked(checked); + } +} + +auto pListView::setFocused() -> void { + gtk_widget_grab_focus(gtkWidgetChild); +} + +auto pListView::setFont(const string& font) -> void { + for(auto& column : state().columns) { + if(auto delegate = column->self()) delegate->setFont(column->font(true)); + } +} + +auto pListView::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pListView::setGridVisible(bool visible) -> void { + gtk_tree_view_set_grid_lines(gtkTreeView, visible ? GTK_TREE_VIEW_GRID_LINES_BOTH : GTK_TREE_VIEW_GRID_LINES_NONE); +} + +auto pListView::setHeaderVisible(bool visible) -> void { + gtk_tree_view_set_headers_visible(gtkTreeView, visible); +} + +auto pListView::setMultiSelect(bool multiSelect) -> void { + gtk_tree_selection_set_mode(gtkTreeSelection, multiSelect ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE); +} + +auto pListView::setSelected(bool selected) -> void { + for(auto& item : state().items) { + if(auto delegate = item->self()) delegate->setSelected(selected); + } +} + +auto pListView::_column(unsigned column) -> pListViewColumn* { + if(auto delegate = self().column(column)) return delegate->self(); + return nullptr; +} + +auto pListView::_createModel() -> void { + gtk_tree_view_set_model(gtkTreeView, nullptr); + gtkListStore = nullptr; + gtkTreeModel = nullptr; + + vector<GType> types; + unsigned position = 0; + for(auto column : state().columns) { + if(!column->self()->gtkColumn) continue; //column is being removed + if(position++ == 0) types.append(G_TYPE_BOOLEAN); + types.append(GDK_TYPE_PIXBUF); + types.append(G_TYPE_STRING); + } + if(!types) return; //no columns available + + gtkListStore = gtk_list_store_newv(types.size(), types.data()); + gtkTreeModel = GTK_TREE_MODEL(gtkListStore); + gtk_tree_view_set_model(gtkTreeView, gtkTreeModel); +} + +auto pListView::_doActivate() -> void { + if(!locked()) self().doActivate(); +} + +auto pListView::_doChange() -> void { + if(!locked()) _updateSelected(); +} + +auto pListView::_doContext() -> void { + if(!locked()) self().doContext(); +} + +auto pListView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* path, const char* text) -> void { + for(auto& column : state().columns) { + if(auto delegate = column->self()) { + if(gtkCellRendererText = GTK_CELL_RENDERER_TEXT(delegate->gtkCellText)) { + if(auto item = self().item(decimal(path))) { + if(string{text} != item->text(column->offset())) { + item->setText(column->offset(), text); + if(!locked()) self().doEdit(item, column); + } + return; + } + } + } + } +} + +auto pListView::_doEvent(GdkEventButton* event) -> signed { + GtkTreePath* path = nullptr; + gtk_tree_view_get_path_at_pos(gtkTreeView, event->x, event->y, &path, nullptr, nullptr, nullptr); + + if(event->type == GDK_BUTTON_PRESS) { + //when clicking in empty space below the last list view item; GTK+ does not deselect all items; + //below code enables this functionality, to match behavior with all other UI toolkits (and because it's very convenient to have) + if(path == nullptr && gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) { + self().setSelected({}); + self().doChange(); + return true; + } + } + + if(event->type == GDK_BUTTON_PRESS && event->button == 3) { + //this check prevents the loss of selection on other items if the item under the mouse cursor is currently selected + if(path && gtk_tree_selection_path_is_selected(gtkTreeSelection, path)) return true; + } + + if(event->type == GDK_BUTTON_RELEASE && event->button == 3) { + //handle action during right-click release; as button-press-event is sent prior to selection update + //without this, the callback handler would see the previous selection state instead + self().doContext(); + return false; + } + + return false; +} + +auto pListView::_doHeaderActivate(GtkTreeViewColumn* gtkTreeViewColumn) -> void { + for(auto& column : state().columns) { + if(auto delegate = column->self()) { + if(gtkTreeViewColumn == delegate->gtkColumn) { + if(!locked()) self().doSort(column); + return; + } + } + } +} + +//GtkTreeView::cursor-changed and GtkTreeSelection::changed do not send signals for changes during rubber-banding selection +//so here we capture motion-notify-event, and if the selections have changed, invoke ListView::onChange +auto pListView::_doMouseMove() -> signed { + if(gtk_tree_view_is_rubber_banding_active(gtkTreeView)) { + if(!locked()) _updateSelected(); + } + return false; +} + +auto pListView::_doToggle(const char* path) -> void { + if(auto item = self().item(decimal(path))) { + if(auto delegate = item->self()) { + item->state.checked = !item->state.checked; + delegate->setChecked(item->state.checked); + if(!locked()) self().doToggle(item); + } + } +} + +//compare currently selected items to previously selected items +//if different, invoke the onChange callback unless locked, and cache current selection +//this prevents firing an onChange event when the actual selection has not changed +//this is particularly important for the motion-notify-event binding +auto pListView::_updateSelected() -> void { + vector<unsigned> selected; + + GList* list = gtk_tree_selection_get_selected_rows(gtkTreeSelection, >kTreeModel); + GList* p = list; + + while(p) { + GtkTreeIter iter; + if(gtk_tree_model_get_iter(gtkTreeModel, &iter, (GtkTreePath*)p->data)) { + char* pathname = gtk_tree_model_get_string_from_iter(gtkTreeModel, &iter); + unsigned selection = decimal(pathname); + g_free(pathname); + selected.append(selection); + } + p = p->next; + } + + g_list_foreach(list, (GFunc)gtk_tree_path_free, nullptr); + g_list_free(list); + + bool identical = selected.size() == currentSelection.size(); + if(identical) { + for(auto n : range(selected)) { + if(selected[n] != currentSelection[n]) { + identical = false; + break; + } + } + } + if(identical) return; + + currentSelection = selected; + for(auto& item : state().items) item->state.selected = false; + for(auto& position : currentSelection) { + if(position >= self().items()) continue; + self().item(position)->state.selected = true; + } + + if(!locked()) self().doChange(); +} + +} diff --git a/hiro/gtk/widget/list-view.hpp b/hiro/gtk/widget/list-view.hpp new file mode 100644 index 00000000..576cde40 --- /dev/null +++ b/hiro/gtk/widget/list-view.hpp @@ -0,0 +1,45 @@ +namespace hiro { + +struct pListView : pWidget { + Declare(ListView, Widget) + + auto append(sListViewColumn column) -> void; + auto append(sListViewItem item) -> void; + auto focused() -> bool; + auto remove(sListViewColumn column) -> void; + auto remove(sListViewItem item) -> void; + auto reset() -> void; + auto resizeColumns() -> void; + auto setBackgroundColor(Color color) -> void; + auto setCheckable(bool checkable) -> void; + auto setChecked(bool checked) -> void; + auto setFocused() -> void override; + auto setFont(const string& font) -> void override; + auto setForegroundColor(Color color) -> void; + auto setGridVisible(bool visible) -> void; + auto setHeaderVisible(bool visible) -> void; + auto setMultiSelect(bool multiSelect) -> void; + auto setSelected(bool selected) -> void; + + auto _column(unsigned column) -> pListViewColumn*; + auto _createModel() -> void; + auto _doActivate() -> void; + auto _doChange() -> void; + auto _doContext() -> void; + auto _doEdit(GtkCellRendererText* renderer, const char* path, const char* text) -> void; + auto _doEvent(GdkEventButton* event) -> signed; + auto _doHeaderActivate(GtkTreeViewColumn* column) -> void; + auto _doMouseMove() -> signed; + auto _doToggle(const char* path) -> void; + auto _updateSelected() -> void; + + GtkScrolledWindow* gtkScrolledWindow = nullptr; + GtkWidget* gtkWidgetChild = nullptr; + GtkTreeView* gtkTreeView = nullptr; + GtkTreeSelection* gtkTreeSelection = nullptr; + GtkListStore* gtkListStore = nullptr; + GtkTreeModel* gtkTreeModel = nullptr; + vector<unsigned> currentSelection; +}; + +} diff --git a/hiro/gtk/widget/progress-bar.cpp b/hiro/gtk/widget/progress-bar.cpp new file mode 100644 index 00000000..8e888d88 --- /dev/null +++ b/hiro/gtk/widget/progress-bar.cpp @@ -0,0 +1,24 @@ +namespace hiro { + +auto pProgressBar::construct() -> void { + gtkWidget = gtk_progress_bar_new(); + + setPosition(state().position); + + pWidget::construct(); +} + +auto pProgressBar::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pProgressBar::minimumSize() const -> Size { + return {0, 25}; +} + +auto pProgressBar::setPosition(unsigned position) -> void { + position = position <= 100 ? position : 0; + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkWidget), (double)position / 100.0); +} + +} diff --git a/hiro/gtk/widget/progress-bar.hpp b/hiro/gtk/widget/progress-bar.hpp new file mode 100644 index 00000000..14e677c1 --- /dev/null +++ b/hiro/gtk/widget/progress-bar.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pProgressBar : pWidget { + Declare(ProgressBar, Widget) + + auto minimumSize() const -> Size; + auto setPosition(unsigned position) -> void; +}; + +} diff --git a/hiro/gtk/widget/radio-button.cpp b/hiro/gtk/widget/radio-button.cpp new file mode 100644 index 00000000..97b5dd85 --- /dev/null +++ b/hiro/gtk/widget/radio-button.cpp @@ -0,0 +1,101 @@ +namespace hiro { + +static auto RadioButton_activate(GtkToggleButton*, pRadioButton* p) -> void { + if(p->_parent().locked()) return; + bool wasChecked = p->state().checked; + p->setChecked(); + if(!wasChecked) p->self().doActivate(); +} + +auto pRadioButton::construct() -> void { + gtkWidget = gtk_toggle_button_new(); + + setGroup(state().group); + setBordered(state().bordered); + setIcon(state().icon); + setOrientation(state().orientation); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioButton_activate), (gpointer)this); + + pWidget::construct(); +} + +auto pRadioButton::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pRadioButton::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + + if(state().orientation == Orientation::Horizontal) { + size.setWidth(size.width() + state().icon.width); + size.setHeight(max(size.height(), state().icon.height)); + } + + if(state().orientation == Orientation::Vertical) { + size.setWidth(max(size.width(), state().icon.width)); + size.setHeight(size.height() + state().icon.height); + } + + return {size.width() + 24, size.height() + 12}; +} + +auto pRadioButton::setBordered(bool bordered) -> void { + gtk_button_set_relief(GTK_BUTTON(gtkWidget), bordered ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE); +} + +auto pRadioButton::setChecked() -> void { + _parent().lock(); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) { + if(item->self()) { + bool checked = item->self() == this; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item->self()->gtkWidget), item->state.checked = checked); + } + } + } + _parent().unlock(); +} + +auto pRadioButton::setGroup(const vector<wRadioButton>& group) -> void { + _parent().lock(); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) { + if(item->self()) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item->self()->gtkWidget), item->checked()); + } + } + _parent().unlock(); +} + +auto pRadioButton::setIcon(const image& icon) -> void { + if(icon) { + GtkImage* gtkImage = CreateImage(icon); + gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage); + } else { + gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr); + } +} + +auto pRadioButton::setOrientation(Orientation orientation) -> void { + switch(orientation) { + case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break; + case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break; + } +} + +auto pRadioButton::setText(const string& text) -> void { + gtk_button_set_label(GTK_BUTTON(gtkWidget), text); + setFont(self().font(true)); //gtk_button_set_label() recreates label, which destroys currently assigned font +} + +auto pRadioButton::_parent() -> pRadioButton& { + if(state().group.size()) { + if(auto item = state().group.first().acquire()) { + if(item->self()) return *item->self(); + } + } + return *this; +} + +} diff --git a/hiro/gtk/widget/radio-button.hpp b/hiro/gtk/widget/radio-button.hpp new file mode 100644 index 00000000..f74ac141 --- /dev/null +++ b/hiro/gtk/widget/radio-button.hpp @@ -0,0 +1,17 @@ +namespace hiro { + +struct pRadioButton : pWidget { + Declare(RadioButton, Widget) + + auto minimumSize() const -> Size; + auto setBordered(bool bordered) -> void; + auto setChecked() -> void; + auto setGroup(const vector<wRadioButton>& group) -> void; + auto setIcon(const image& icon) -> void; + auto setOrientation(Orientation orientation) -> void; + auto setText(const string& text) -> void; + + auto _parent() -> pRadioButton&; +}; + +} diff --git a/hiro/gtk/widget/radio-label.cpp b/hiro/gtk/widget/radio-label.cpp new file mode 100644 index 00000000..b3ec8c61 --- /dev/null +++ b/hiro/gtk/widget/radio-label.cpp @@ -0,0 +1,71 @@ +namespace hiro { + +static auto RadioLabel_activate(GtkToggleButton*, pRadioLabel* p) -> void { + if(p->_parent().locked()) return; + bool wasChecked = p->state().checked; + p->setChecked(); + if(!wasChecked) p->self().doActivate(); +} + +auto pRadioLabel::construct() -> void { + gtkWidget = gtk_radio_button_new_with_label(nullptr, ""); + + setGroup(state().group); + setText(state().text); + + g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioLabel_activate), (gpointer)this); + + pWidget::construct(); +} + +auto pRadioLabel::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pRadioLabel::minimumSize() const -> Size { + Size size = pFont::size(self().font(true), state().text); + return {size.width() + 28, size.height() + 4}; +} + +auto pRadioLabel::setChecked() -> void { + _parent().lock(); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) item->state.checked = false; + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), state().checked = true); + _parent().unlock(); +} + +auto pRadioLabel::setGroup(const vector<shared_pointer_weak<mRadioLabel>>& group) -> void { + if(&_parent() == this) return; + _parent().lock(); + gtk_radio_button_set_group( + GTK_RADIO_BUTTON(gtkWidget), + gtk_radio_button_get_group(GTK_RADIO_BUTTON(_parent().gtkWidget)) + ); + for(auto& weak : state().group) { + if(auto item = weak.acquire()) { + if(item->self() && item->checked()) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item->self()->gtkWidget), true); + break; + } + } + } + _parent().unlock(); +} + +auto pRadioLabel::setText(const string& text) -> void { + gtk_button_set_label(GTK_BUTTON(gtkWidget), text); + setFont(self().font(true)); //gtk_button_set_label() recreates label, which destroys currently assigned font +} + +auto pRadioLabel::_parent() -> pRadioLabel& { + if(state().group.size()) { + if(auto item = state().group.first().acquire()) { + if(item->self()) return *item->self(); + } + } + return *this; +} + +} diff --git a/hiro/gtk/widget/radio-label.hpp b/hiro/gtk/widget/radio-label.hpp new file mode 100644 index 00000000..758980ba --- /dev/null +++ b/hiro/gtk/widget/radio-label.hpp @@ -0,0 +1,14 @@ +namespace hiro { + +struct pRadioLabel : pWidget { + Declare(RadioLabel, Widget) + + auto minimumSize() const -> Size; + auto setChecked() -> void; + auto setGroup(const vector<shared_pointer_weak<mRadioLabel>>& group) -> void; + auto setText(const string& text) -> void; + + auto _parent() -> pRadioLabel&; +}; + +} diff --git a/hiro/gtk/widget/source-edit.cpp b/hiro/gtk/widget/source-edit.cpp new file mode 100644 index 00000000..aacb9264 --- /dev/null +++ b/hiro/gtk/widget/source-edit.cpp @@ -0,0 +1,126 @@ +namespace hiro { + +static auto SourceEdit_change(GtkTextBuffer*, pSourceEdit* p) -> void { + if(!p->locked()) p->self().doChange(); +} + +static auto SourceEdit_move(GObject*, GParamSpec*, pSourceEdit* p) -> void { + signed position = 0; + g_object_get(G_OBJECT(p->gtkSourceBuffer), "cursor-position", &position, nullptr); + + if(p->state().position != position) { + p->state().position = position; + if(!p->locked()) p->self().doMove(); + } +} + +auto pSourceEdit::construct() -> void { + gtkScrolledWindow = (GtkScrolledWindow*)gtk_scrolled_window_new(0, 0); + gtkContainer = GTK_CONTAINER(gtkScrolledWindow); + gtkWidget = GTK_WIDGET(gtkScrolledWindow); + gtk_scrolled_window_set_policy(gtkScrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(gtkScrolledWindow, GTK_SHADOW_ETCHED_IN); + + gtkSourceLanguageManager = gtk_source_language_manager_get_default(); + gtkSourceLanguage = gtk_source_language_manager_get_language(gtkSourceLanguageManager, "cpp"); + + gtkSourceStyleSchemeManager = gtk_source_style_scheme_manager_get_default(); + gtkSourceStyleScheme = gtk_source_style_scheme_manager_get_scheme(gtkSourceStyleSchemeManager, "oblivion"); + + gtkSourceBuffer = gtk_source_buffer_new(nullptr); + gtkTextBuffer = GTK_TEXT_BUFFER(gtkSourceBuffer); + gtk_source_buffer_set_highlight_matching_brackets(gtkSourceBuffer, true); + gtk_source_buffer_set_highlight_syntax(gtkSourceBuffer, true); +//gtk_source_buffer_set_language(gtkSourceBuffer, gtkSourceLanguage); + gtk_source_buffer_set_style_scheme(gtkSourceBuffer, gtkSourceStyleScheme); + + gtkSourceView = (GtkSourceView*)gtk_source_view_new_with_buffer(gtkSourceBuffer); + gtkTextView = GTK_TEXT_VIEW(gtkSourceView); + gtkWidgetSourceView = GTK_WIDGET(gtkSourceView); + gtk_source_view_set_auto_indent(gtkSourceView, false); + gtk_source_view_set_draw_spaces(gtkSourceView, (GtkSourceDrawSpacesFlags)0); + gtk_source_view_set_highlight_current_line(gtkSourceView, true); + gtk_source_view_set_indent_on_tab(gtkSourceView, false); + gtk_source_view_set_indent_width(gtkSourceView, 4); + gtk_source_view_set_insert_spaces_instead_of_tabs(gtkSourceView, false); + gtk_source_view_set_right_margin_position(gtkSourceView, 80); + gtk_source_view_set_show_line_marks(gtkSourceView, false); + gtk_source_view_set_show_line_numbers(gtkSourceView, true); + gtk_source_view_set_show_right_margin(gtkSourceView, true); + gtk_source_view_set_smart_home_end(gtkSourceView, GTK_SOURCE_SMART_HOME_END_DISABLED); + gtk_source_view_set_tab_width(gtkSourceView, 4); + gtk_container_add(gtkContainer, gtkWidgetSourceView); + gtk_widget_show(gtkWidgetSourceView); + + setText(state().text); + + g_signal_connect(G_OBJECT(gtkSourceBuffer), "changed", G_CALLBACK(SourceEdit_change), (gpointer)this); + g_signal_connect(G_OBJECT(gtkSourceBuffer), "notify::cursor-position", G_CALLBACK(SourceEdit_move), (gpointer)this); + + pWidget::construct(); +} + +auto pSourceEdit::destruct() -> void { + state().text = text(); + gtk_widget_destroy(gtkWidgetSourceView); + gtk_widget_destroy(gtkWidget); +} + +auto pSourceEdit::setFocused() -> void { + gtk_widget_grab_focus(gtkWidgetSourceView); +} + +auto pSourceEdit::setPosition(signed position) -> void { + lock(); + GtkTextIter iter; + //note: iterators must be initialized via get_iter() before calling set_offset() + gtk_text_buffer_get_end_iter(gtkTextBuffer, &iter); + if(position >= 0) { + gtk_text_iter_set_offset(&iter, position); + } else { + state().position = gtk_text_iter_get_offset(&iter); + } + gtk_text_buffer_place_cursor(gtkTextBuffer, &iter); + auto mark = gtk_text_buffer_get_mark(gtkTextBuffer, "insert"); + gtk_text_view_scroll_mark_onscreen(gtkTextView, mark); + unlock(); +} + +auto pSourceEdit::setSelected(Position selected) -> void { + lock(); + GtkTextIter iter; + gtk_text_buffer_get_end_iter(gtkTextBuffer, &iter); + signed offset = gtk_text_iter_get_offset(&iter); + if(selected.x() < 0 || selected.x() > offset) selected.setX(offset); + if(selected.y() < 0 || selected.y() > offset) selected.setY(offset); + state().selected = selected; + GtkTextIter startIter; + gtk_text_buffer_get_start_iter(gtkTextBuffer, &startIter); + gtk_text_iter_set_offset(&startIter, selected.x()); + GtkTextIter endIter; + gtk_text_buffer_get_end_iter(gtkTextBuffer, &endIter); + gtk_text_iter_set_offset(&endIter, selected.y()); + gtk_text_buffer_select_range(gtkTextBuffer, &startIter, &endIter); + unlock(); +} + +auto pSourceEdit::setText(const string& text) -> void { + lock(); + gtk_text_buffer_set_text(gtkTextBuffer, text, -1); + unlock(); +} + +auto pSourceEdit::text() const -> string { + GtkTextIter startIter; + gtk_text_buffer_get_start_iter(gtkTextBuffer, &startIter); + + GtkTextIter endIter; + gtk_text_buffer_get_end_iter(gtkTextBuffer, &endIter); + + char* textBuffer = gtk_text_buffer_get_text(gtkTextBuffer, &startIter, &endIter, true); + string text = textBuffer; + g_free(textBuffer); + return text; +} + +} diff --git a/hiro/gtk/widget/source-edit.hpp b/hiro/gtk/widget/source-edit.hpp new file mode 100644 index 00000000..7c9c07e5 --- /dev/null +++ b/hiro/gtk/widget/source-edit.hpp @@ -0,0 +1,25 @@ +namespace hiro { + +struct pSourceEdit : pWidget { + Declare(SourceEdit, Widget) + + auto setFocused() -> void override; + auto setPosition(signed position) -> void; + auto setSelected(Position selected) -> void; + auto setText(const string& text) -> void; + auto text() const -> string; + + GtkScrolledWindow* gtkScrolledWindow = nullptr; + GtkContainer* gtkContainer = nullptr; + GtkSourceBuffer* gtkSourceBuffer = nullptr; + GtkTextBuffer* gtkTextBuffer = nullptr; + GtkSourceLanguageManager* gtkSourceLanguageManager = nullptr; + GtkSourceLanguage* gtkSourceLanguage = nullptr; + GtkSourceStyleSchemeManager* gtkSourceStyleSchemeManager = nullptr; + GtkSourceStyleScheme* gtkSourceStyleScheme = nullptr; + GtkSourceView* gtkSourceView = nullptr; + GtkTextView* gtkTextView = nullptr; + GtkWidget* gtkWidgetSourceView = nullptr; +}; + +} diff --git a/hiro/gtk/widget/tab-frame-item.cpp b/hiro/gtk/widget/tab-frame-item.cpp new file mode 100644 index 00000000..b202e4bb --- /dev/null +++ b/hiro/gtk/widget/tab-frame-item.cpp @@ -0,0 +1,46 @@ +namespace hiro { + +auto pTabFrameItem::construct() -> void { + if(auto layout = state().layout) layout->construct(); +} + +auto pTabFrameItem::destruct() -> void { + if(auto layout = state().layout) layout->destruct(); +} + +auto pTabFrameItem::setClosable(bool closable) -> void { + if(auto parent = _parent()) { + parent->setItemClosable(self().offset(), closable); + } +} + +auto pTabFrameItem::setIcon(const image& icon) -> void { + if(auto parent = _parent()) { + parent->setItemIcon(self().offset(), icon); + } +} + +auto pTabFrameItem::setMovable(bool movable) -> void { + if(auto parent = _parent()) { + parent->setItemMovable(self().offset(), movable); + } +} + +auto pTabFrameItem::setSelected() -> void { + if(auto parent = _parent()) { + parent->setItemSelected(self().offset()); + } +} + +auto pTabFrameItem::setText(const string& text) -> void { + if(auto parent = _parent()) { + parent->setItemText(self().offset(), text); + } +} + +auto pTabFrameItem::_parent() -> pTabFrame* { + if(auto parent = self().parentTabFrame()) return parent->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/tab-frame-item.hpp b/hiro/gtk/widget/tab-frame-item.hpp new file mode 100644 index 00000000..2f3ddd30 --- /dev/null +++ b/hiro/gtk/widget/tab-frame-item.hpp @@ -0,0 +1,15 @@ +namespace hiro { + +struct pTabFrameItem : pObject { + Declare(TabFrameItem, Object) + + auto setClosable(bool closable) -> void; + auto setIcon(const image& icon) -> void; + auto setMovable(bool movable) -> void; + auto setSelected() -> void; + auto setText(const string& text) -> void; + + auto _parent() -> pTabFrame*; +}; + +} diff --git a/hiro/gtk/widget/tab-frame.cpp b/hiro/gtk/widget/tab-frame.cpp new file mode 100644 index 00000000..0ffa1243 --- /dev/null +++ b/hiro/gtk/widget/tab-frame.cpp @@ -0,0 +1,265 @@ +namespace hiro { + +static auto TabFrame_change(GtkNotebook* notebook, GtkWidget* page, unsigned position, pTabFrame* p) -> void { + p->state().selected = position; + p->_synchronizeLayout(); + if(!p->locked()) p->self().doChange(); +} + +static auto TabFrame_close(GtkButton* button, pTabFrame* p) -> void { + maybe<unsigned> position; + for(auto n : range(p->tabs)) { + if(button == (GtkButton*)p->tabs[n].close) { + position = n; + break; + } + } + if(position) { + if(!p->locked()) p->self().doClose(p->self().item(*position)); + } +} + +static auto TabFrame_move(GtkNotebook* notebook, GtkWidget* page, unsigned moveTo, pTabFrame* p) -> void { + p->state().selected = gtk_notebook_get_current_page(notebook); + maybe<unsigned> moveFrom; + for(auto n : range(p->tabs)) { + if(page == p->tabs[n].child) { + moveFrom = n; + break; + } + } + if(moveFrom) { + p->state().items.insert(moveTo, p->state().items.take(*moveFrom)); + p->tabs.insert(moveTo, p->tabs.take(*moveFrom)); + if(!p->locked()) p->self().doMove(p->self().item(*moveFrom), p->self().item(moveTo)); + } +} + +auto pTabFrame::construct() -> void { + gtkWidget = gtk_notebook_new(); + gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkWidget), false); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), GTK_POS_TOP); + + tabs.reset(); //todo: memory leak, need to release each tab + for(auto& item : state().items) append(item); + setEdge(state().edge); + setItemSelected(state().selected); + + g_signal_connect(G_OBJECT(gtkWidget), "page-reordered", G_CALLBACK(TabFrame_move), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "switch-page", G_CALLBACK(TabFrame_change), (gpointer)this); + + pWidget::construct(); +} + +auto pTabFrame::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pTabFrame::append(sTabFrameItem item) -> void { + lock(); + Tab tab; + tab.child = gtk_fixed_new(); + tab.container = gtk_hbox_new(false, 0); + tab.image = gtk_image_new(); + tab.title = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(tab.title), 0.0, 0.5); + tab.close = gtk_button_new_with_label("\u00d7"); //Unicode multiplication sign (looks better than 'X') + gtk_button_set_focus_on_click(GTK_BUTTON(tab.close), false); + gtk_button_set_relief(GTK_BUTTON(tab.close), GTK_RELIEF_NONE); + pFont::setFont(tab.close, Font::sans(9, "Bold")); + auto color = CreateColor({255, 0, 0}); + gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(tab.close)), GTK_STATE_PRELIGHT, &color); + tabs.append(tab); + + gtk_widget_show(tab.child); + gtk_widget_show(tab.container); + gtk_widget_show(tab.image); + gtk_widget_show(tab.title); + gtk_widget_show(tab.close); + gtk_box_pack_start(GTK_BOX(tab.container), tab.image, false, false, 0); + gtk_box_pack_start(GTK_BOX(tab.container), tab.title, true, true, 0); + gtk_box_pack_start(GTK_BOX(tab.container), tab.close, false, false, 0); + + g_signal_connect(G_OBJECT(tab.close), "clicked", G_CALLBACK(TabFrame_close), (gpointer)this); + gtk_notebook_append_page(GTK_NOTEBOOK(gtkWidget), tab.child, tab.container); + + setFont(self().font(true)); + setItemMovable(item->offset(), item->movable()); + _synchronizeTab(tabs.size() - 1); + setGeometry(self().geometry()); + unlock(); +} + +auto pTabFrame::container(mWidget& widget) -> GtkWidget* { + auto widgetLayout = widget.parentLayout(); + unsigned position = 0; + for(auto& item : state().items) { + if(item->state.layout.data() == widgetLayout) return tabs[position].child; + position++; + } + return nullptr; +} + +auto pTabFrame::remove(sTabFrameItem item) -> void { + lock(); + //if we are removing the current tab, we have to select another tab manually + if(item->offset() == gtk_notebook_get_current_page(GTK_NOTEBOOK(gtkWidget))) { + //the new tab will be the one after this one + unsigned displacement = 1; + //... unless it's the last tab, in which case it's the one before it + if(item->offset() == self().items() - 1) displacement = -1; + //... unless there are no tabs left, in which case nothing is selected + if(self().items() > 1) { + setItemSelected(item->offset() + displacement); + } + } + tabs.remove(item->offset()); + gtk_notebook_remove_page(GTK_NOTEBOOK(gtkWidget), item->offset()); + state().selected = gtk_notebook_get_current_page(GTK_NOTEBOOK(gtkWidget)); + unlock(); +} + +auto pTabFrame::setEdge(Edge edge) -> void { + GtkPositionType type; + switch(edge) { default: + case Edge::Top: type = GTK_POS_TOP; break; + case Edge::Bottom: type = GTK_POS_BOTTOM; break; + case Edge::Left: type = GTK_POS_LEFT; break; + case Edge::Right: type = GTK_POS_RIGHT; break; + } + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), type); + setGeometry(self().geometry()); +} + +auto pTabFrame::setEnabled(bool enabled) -> void { + for(auto& item : state().items) { + if(auto layout = item->state.layout) { + if(layout->self()) layout->self()->setEnabled(layout->enabled(true)); + } + } + pWidget::setEnabled(enabled); +} + +auto pTabFrame::setFont(const string& font) -> void { + for(auto n : range(tabs.size())) { + pFont::setFont(tabs[n].title, font); + if(auto layout = state().items[n]->state.layout) { + if(layout->self()) layout->self()->setFont(layout->font(true)); + } + } +} + +auto pTabFrame::setGeometry(Geometry geometry) -> void { + pWidget::setGeometry(geometry); + + geometry.setPosition(0, 0); + if(state().edge == Edge::Top || state().edge == Edge::Bottom) { + geometry.setWidth(geometry.width() - 6); + geometry.setHeight(geometry.height() - (15 + _tabHeight())); + } else { + geometry.setWidth(geometry.width() - (17 + _tabWidth())); + geometry.setHeight(geometry.height() - 6); + } + for(auto& item : state().items) { + if(item->state.layout) item->state.layout->setGeometry(geometry); + } +} + +auto pTabFrame::setItemClosable(unsigned position, bool closable) -> void { + _synchronizeTab(position); +} + +auto pTabFrame::setItemIcon(unsigned position, const image& icon) -> void { + _synchronizeTab(position); +} + +auto pTabFrame::setItemLayout(unsigned position, shared_pointer<mLayout> layout) -> void { +//if(layout->self()) layout->self()->setParent(); +} + +auto pTabFrame::setItemMovable(unsigned position, bool movable) -> void { + lock(); + gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(gtkWidget), tabs[position].child, movable); + unlock(); +} + +auto pTabFrame::setItemSelected(unsigned position) -> void { + lock(); + gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkWidget), position); + unlock(); +} + +auto pTabFrame::setItemText(unsigned position, const string& text) -> void { + _synchronizeTab(position); +} + +auto pTabFrame::setVisible(bool visible) -> void { + for(auto& item : state().items) { + if(auto layout = item->state.layout) { + if(layout->self()) { + layout->self()->setVisible(layout->visible(true)); + } + } + } + pWidget::setVisible(visible); +} + +auto pTabFrame::_synchronizeLayout() -> void { + unsigned position = 0; + for(auto& item : state().items) { + if(auto layout = item->state.layout) { + if(layout->self()) { + layout->self()->setVisible(layout->visible(true) && position == state().selected); + } + } + position++; + } +} + +auto pTabFrame::_synchronizeTab(unsigned position) -> void { + auto& item = state().items[position]; + auto& tab = tabs[position]; + gtk_widget_set_visible(tab.close, item->closable()); + if(auto copy = item->state.icon) { + unsigned size = pFont::size(self().font(true), " ").height(); + copy.scale(size, size); + auto pixbuf = CreatePixbuf(copy); + gtk_image_set_from_pixbuf(GTK_IMAGE(tab.image), pixbuf); + } else { + gtk_image_clear(GTK_IMAGE(tab.image)); + } + string text = { + item->state.icon && item->state.text ? " " : "", + item->state.text, + item->state.text && item->state.closable ? " " : "" + }; + gtk_label_set_text(GTK_LABEL(tab.title), text); +} + +//compute the height of the tallest tab for child layout geometry calculations +auto pTabFrame::_tabHeight() -> unsigned { + signed height = 1; + + for(auto n : range(self().items())) { + height = max(height, tabs[n].image->allocation.height); + height = max(height, tabs[n].title->allocation.height); + if(!state().items[n]->closable()) continue; + height = max(height, tabs[n].close->allocation.height); + } + + return height; +} + +auto pTabFrame::_tabWidth() -> unsigned { + signed width = 1; + + for(auto n : range(self().items())) { + width = max(width, tabs[n].image->allocation.width + tabs[n].title->allocation.width + + (state().items[n]->closable() ? tabs[n].close->allocation.width : 0) + ); + } + + return width; +} + +} diff --git a/hiro/gtk/widget/tab-frame.hpp b/hiro/gtk/widget/tab-frame.hpp new file mode 100644 index 00000000..4319fc94 --- /dev/null +++ b/hiro/gtk/widget/tab-frame.hpp @@ -0,0 +1,39 @@ +namespace hiro { + +struct pTabFrame : pWidget { + Declare(TabFrame, Widget) + + auto append(sTabFrameItem item) -> void; + auto container(mWidget& widget) -> GtkWidget* override; + auto remove(sTabFrameItem item) -> void; + auto setEdge(Edge edge) -> void; + auto setEnabled(bool enabled) -> void override; + auto setFont(const string& font) -> void override; + auto setGeometry(Geometry geometry) -> void override; + auto setItemClosable(unsigned position, bool closable) -> void; + auto setItemIcon(unsigned position, const image& icon) -> void; + auto setItemLayout(unsigned position, sLayout layout) -> void; + auto setItemMovable(unsigned position, bool movable) -> void; + auto setItemSelected(unsigned position) -> void; + auto setItemText(unsigned position, const string& text) -> void; + auto setVisible(bool visible) -> void override; + + auto _append(shared_pointer<mTabFrameItem> item) -> void; + auto _remove(shared_pointer<mTabFrameItem> item) -> void; + auto _synchronizeLayout() -> void; + auto _synchronizeTab(unsigned position) -> void; + auto _tabHeight() -> unsigned; + auto _tabWidth() -> unsigned; + + struct Tab { + GtkWidget* child = nullptr; + GtkWidget* container = nullptr; + GtkWidget* layout = nullptr; + GtkWidget* image = nullptr; + GtkWidget* title = nullptr; + GtkWidget* close = nullptr; + }; + vector<Tab> tabs; +}; + +} diff --git a/hiro/gtk/widget/text-edit.cpp b/hiro/gtk/widget/text-edit.cpp new file mode 100644 index 00000000..758b782b --- /dev/null +++ b/hiro/gtk/widget/text-edit.cpp @@ -0,0 +1,100 @@ +namespace hiro { + +static auto TextEdit_change(GtkTextBuffer* textBuffer, pTextEdit* p) -> void { + if(!p->locked()) p->self().doChange(); +} + +static auto TextEdit_move(GObject* object, GParamSpec* spec, pTextEdit* p) -> void { + int position = 0; + g_object_get(p->textBuffer, "cursor-position", &position, nullptr); + + if(p->state().cursorPosition != position) { + p->state().cursorPosition = position; + if(!p->locked()) p->self().doMove(); + } +} + +auto pTextEdit::construct() -> void { + gtkWidget = gtk_scrolled_window_new(0, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); + + subWidget = gtk_text_view_new(); + gtk_widget_show(subWidget); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_WORD_CHAR); + gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); + + textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); + + setBackgroundColor(state().backgroundColor); + setEditable(state().editable); + setForegroundColor(state().foregroundColor); + setText(state().text); + setWordWrap(state().wordWrap); + + g_signal_connect(G_OBJECT(textBuffer), "changed", G_CALLBACK(TextEdit_change), (gpointer)this); + g_signal_connect(G_OBJECT(textBuffer), "notify::cursor-position", G_CALLBACK(TextEdit_move), (gpointer)this); + + pWidget::construct(); +} + +auto pTextEdit::destruct() -> void { + state().text = text(); + gtk_widget_destroy(subWidget); + gtk_widget_destroy(gtkWidget); +} + +auto pTextEdit::focused() const -> bool { + return GTK_WIDGET_HAS_FOCUS(subWidget); +} + +auto pTextEdit::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pTextEdit::setCursorPosition(unsigned position) -> void { + lock(); + GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); + GtkTextIter iter; + gtk_text_buffer_get_end_iter(textBuffer, &iter); + gtk_text_iter_set_offset(&iter, min(position, gtk_text_iter_get_offset(&iter))); + gtk_text_buffer_place_cursor(textBuffer, &iter); + gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark); + unlock(); +} + +auto pTextEdit::setEditable(bool editable) -> void { + gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), editable); +} + +auto pTextEdit::setForegroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pTextEdit::setText(const string& text) -> void { + lock(); + textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); + gtk_text_buffer_set_text(textBuffer, text, -1); + unlock(); +} + +auto pTextEdit::setWordWrap(bool wordWrap) -> void { + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), wordWrap ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), + wordWrap ? GTK_POLICY_NEVER : GTK_POLICY_ALWAYS, + GTK_POLICY_ALWAYS); +} + +auto pTextEdit::text() const -> string { + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(textBuffer, &start); + gtk_text_buffer_get_end_iter(textBuffer, &end); + char* temp = gtk_text_buffer_get_text(textBuffer, &start, &end, true); + string text = temp; + g_free(temp); + return text; +} + +} diff --git a/hiro/gtk/widget/text-edit.hpp b/hiro/gtk/widget/text-edit.hpp new file mode 100644 index 00000000..5d04e346 --- /dev/null +++ b/hiro/gtk/widget/text-edit.hpp @@ -0,0 +1,19 @@ +namespace hiro { + +struct pTextEdit : pWidget { + Declare(TextEdit, Widget) + + auto focused() const -> bool override; + auto setBackgroundColor(Color color) -> void; + auto setCursorPosition(unsigned position) -> void; + auto setEditable(bool editable) -> void; + auto setForegroundColor(Color color) -> void; + auto setText(const string& text) -> void; + auto setWordWrap(bool wordWrap) -> void; + auto text() const -> string; + + GtkWidget* subWidget = nullptr; + GtkTextBuffer* textBuffer = nullptr; +}; + +} diff --git a/hiro/gtk/widget/tree-view-item.cpp b/hiro/gtk/widget/tree-view-item.cpp new file mode 100644 index 00000000..3648e9db --- /dev/null +++ b/hiro/gtk/widget/tree-view-item.cpp @@ -0,0 +1,82 @@ +namespace hiro { + +auto pTreeViewItem::construct() -> void { +} + +auto pTreeViewItem::destruct() -> void { +} + +// + +auto pTreeViewItem::append(sTreeViewItem item) -> void { + if(auto parentWidget = _parentWidget()) { + gtk_tree_store_append(parentWidget->gtkTreeStore, &item->self()->gtkIter, >kIter); + item->setChecked(item->checked()); + item->setIcon(item->icon()); + item->setText(item->text()); + } +} + +auto pTreeViewItem::remove(sTreeViewItem item) -> void { + if(auto parentWidget = _parentWidget()) { + gtk_tree_store_remove(parentWidget->gtkTreeStore, &item->self()->gtkIter); + } +} + +auto pTreeViewItem::setChecked(bool checked) -> void { + if(auto parentWidget = _parentWidget()) { + gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 0, checked, -1); + } +} + +auto pTreeViewItem::setFocused() -> void { + if(auto parentWidget = _parentWidget()) { + GtkTreePath* path = gtk_tree_path_new_from_string(self().path().transform("/", ":")); + gtk_tree_view_set_cursor(parentWidget->gtkTreeView, path, nullptr, false); + gtk_tree_view_scroll_to_cell(parentWidget->gtkTreeView, path, nullptr, true, 0.5, 0.0); + gtk_tree_path_free(path); + } +} + +auto pTreeViewItem::setIcon(const image& icon) -> void { + if(auto parentWidget = _parentWidget()) { + if(icon) { + auto pixbuf = CreatePixbuf(icon, true); + gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 1, pixbuf, -1); + } else { + gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 1, nullptr, -1); + } + } +} + +auto pTreeViewItem::setSelected() -> void { + if(auto parentWidget = _parentWidget()) { + parentWidget->lock(); + //in order to select an item, it must first be visible + auto gtkPath = gtk_tree_model_get_path(parentWidget->gtkTreeModel, >kIter); + gtk_tree_view_expand_to_path(parentWidget->gtkTreeView, gtkPath); + gtk_tree_path_free(gtkPath); + gtk_tree_selection_select_iter(parentWidget->gtkTreeSelection, >kIter); + parentWidget->unlock(); + } +} + +auto pTreeViewItem::setText(const string& text) -> void { + if(auto parentWidget = _parentWidget()) { + gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 2, (const char*)text, -1); + } +} + +// + +auto pTreeViewItem::_parentItem() -> pTreeViewItem* { + if(auto parentItem = self().parentTreeViewItem()) return parentItem->self(); + return nullptr; +} + +auto pTreeViewItem::_parentWidget() -> pTreeView* { + if(auto parentWidget = self().parentTreeView(true)) return parentWidget->self(); + return nullptr; +} + +} diff --git a/hiro/gtk/widget/tree-view-item.hpp b/hiro/gtk/widget/tree-view-item.hpp new file mode 100644 index 00000000..224d1197 --- /dev/null +++ b/hiro/gtk/widget/tree-view-item.hpp @@ -0,0 +1,20 @@ +namespace hiro { + +struct pTreeViewItem : pObject { + Declare(TreeViewItem, Object) + + auto append(sTreeViewItem item) -> void; + auto remove(sTreeViewItem item) -> void; + auto setChecked(bool checked) -> void; + auto setFocused() -> void; + auto setIcon(const image& icon) -> void; + auto setSelected() -> void; + auto setText(const string& text) -> void; + + auto _parentItem() -> pTreeViewItem*; + auto _parentWidget() -> pTreeView*; + + GtkTreeIter gtkIter; +}; + +} diff --git a/hiro/gtk/widget/tree-view.cpp b/hiro/gtk/widget/tree-view.cpp new file mode 100644 index 00000000..fc895a40 --- /dev/null +++ b/hiro/gtk/widget/tree-view.cpp @@ -0,0 +1,162 @@ +namespace hiro { + +static auto TreeView_activate(GtkTreeView*, GtkTreePath* gtkPath, GtkTreeViewColumn*, pTreeView* p) -> void { p->_activatePath(gtkPath); } +static auto TreeView_buttonEvent(GtkTreeView*, GdkEventButton* gdkEvent, pTreeView* p) -> signed { return p->_buttonEvent(gdkEvent); } +static auto TreeView_change(GtkTreeSelection*, pTreeView* p) -> void { p->_updateSelected(); } +static auto TreeView_context(GtkTreeView*, pTreeView* p) -> void { p->self().doContext(); } +static auto TreeView_toggle(GtkCellRendererToggle*, char* path, pTreeView* p) -> void { p->_togglePath(path); } + +auto pTreeView::construct() -> void { + gtkWidget = gtk_scrolled_window_new(0, 0); + gtkScrolledWindow = GTK_SCROLLED_WINDOW(gtkWidget); + gtk_scrolled_window_set_policy(gtkScrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(gtkScrolledWindow, GTK_SHADOW_ETCHED_IN); + + gtkTreeStore = gtk_tree_store_new(3, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING); + gtkTreeModel = GTK_TREE_MODEL(gtkTreeStore); + + gtkWidgetChild = gtk_tree_view_new_with_model(gtkTreeModel); + gtkTreeView = GTK_TREE_VIEW(gtkWidgetChild); + gtkTreeSelection = gtk_tree_view_get_selection(gtkTreeView); + gtk_tree_view_set_headers_visible(gtkTreeView, false); + gtk_container_add(GTK_CONTAINER(gtkWidget), gtkWidgetChild); + gtk_widget_show(gtkWidgetChild); + + gtkTreeViewColumn = gtk_tree_view_column_new(); + + gtkCellToggle = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellToggle, false); + gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellToggle, "active", 0, nullptr); + gtk_cell_renderer_set_visible(gtkCellToggle, state().checkable); + + gtkCellPixbuf = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellPixbuf, false); + gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellPixbuf, "pixbuf", 1, nullptr); + + gtkCellText = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellText, true); + gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellText, "text", 2, nullptr); + + gtk_tree_view_append_column(gtkTreeView, gtkTreeViewColumn); + gtk_tree_view_set_search_column(gtkTreeView, 2); + + setBackgroundColor(state().backgroundColor); + setForegroundColor(state().foregroundColor); + + g_signal_connect(G_OBJECT(gtkWidgetChild), "button-press-event", G_CALLBACK(TreeView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidgetChild), "button-release-event", G_CALLBACK(TreeView_buttonEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidgetChild), "popup-menu", G_CALLBACK(TreeView_context), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidgetChild), "row-activated", G_CALLBACK(TreeView_activate), (gpointer)this); + g_signal_connect(G_OBJECT(gtkTreeSelection), "changed", G_CALLBACK(TreeView_change), (gpointer)this); + g_signal_connect(G_OBJECT(gtkCellToggle), "toggled", G_CALLBACK(TreeView_toggle), (gpointer)this); + + pWidget::construct(); +} + +auto pTreeView::destruct() -> void { + gtk_widget_destroy(gtkWidgetChild); + gtk_widget_destroy(gtkWidget); +} + +// + +auto pTreeView::append(sTreeViewItem item) -> void { + gtk_tree_store_append(gtkTreeStore, &item->self()->gtkIter, nullptr); + item->setChecked(item->checked()); + item->setIcon(item->icon()); + item->setText(item->text()); +} + +auto pTreeView::collapse() -> void { + gtk_tree_view_collapse_all(gtkTreeView); +} + +auto pTreeView::expand() -> void { + gtk_tree_view_expand_all(gtkTreeView); +} + +auto pTreeView::remove(sTreeViewItem item) -> void { + gtk_tree_store_remove(gtkTreeStore, &item->self()->gtkIter); +} + +auto pTreeView::reset() -> void { + gtk_tree_view_set_model(gtkTreeView, nullptr); + gtkTreeStore = gtk_tree_store_new(3, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING); + gtkTreeModel = GTK_TREE_MODEL(gtkTreeStore); + gtk_tree_view_set_model(gtkTreeView, gtkTreeModel); +} + +auto pTreeView::setBackgroundColor(Color color) -> void { + auto gdkColor = CreateColor(color); + gtk_widget_modify_base(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pTreeView::setCheckable(bool checkable) -> void { + gtk_cell_renderer_set_visible(gtkCellToggle, checkable); +} + +auto pTreeView::setForegroundColor(Color color) -> void { + auto gdkColor = CreateColor(color); + gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +// + +auto pTreeView::_activatePath(GtkTreePath* gtkPath) -> void { + char* path = gtk_tree_path_to_string(gtkPath); + if(auto item = self().item(string{path}.transform(":", "/"))) { + if(!locked()) self().doActivate(); + } + g_free(path); +} + +auto pTreeView::_buttonEvent(GdkEventButton* gdkEvent) -> signed { + GtkTreePath* gtkPath = nullptr; + gtk_tree_view_get_path_at_pos(gtkTreeView, gdkEvent->x, gdkEvent->y, >kPath, nullptr, nullptr, nullptr); + + if(gdkEvent->type == GDK_BUTTON_PRESS) { + //detect when the empty space of the GtkTreeView is clicked; and clear the selection + if(gtkPath == nullptr && gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) { + gtk_tree_selection_unselect_all(gtkTreeSelection); + state().selectedPath.reset(); + self().doChange(); + return true; + } + } + + if(gdkEvent->type == GDK_BUTTON_RELEASE && gdkEvent->button == 3) { + //handle right-click context menu + //have to detect on button release instead of press; as GTK+ does not update new selection prior to press event + self().doContext(); + return false; + } + + return false; +} + +auto pTreeView::_togglePath(string path) -> void { + if(auto item = self().item(path.transform(":", "/"))) { + bool checked = !item->checked(); + gtk_tree_store_set(gtkTreeStore, &item->self()->gtkIter, 0, checked, -1); + item->state.checked = checked; + if(!locked()) self().doToggle(item); + } +} + +auto pTreeView::_updateSelected() -> void { + GtkTreeIter iter; + if(gtk_tree_selection_get_selected(gtkTreeSelection, >kTreeModel, &iter)) { + char* gtkPath = gtk_tree_model_get_string_from_iter(gtkTreeModel, &iter); + string path = string{gtkPath}.transform(":", "/"); + g_free(gtkPath); + if(state().selectedPath != path) { + state().selectedPath = path; + if(!locked()) self().doChange(); + } + } else if(state().selectedPath) { + state().selectedPath.reset(); + if(!locked()) self().doChange(); + } +} + +} diff --git a/hiro/gtk/widget/tree-view.hpp b/hiro/gtk/widget/tree-view.hpp new file mode 100644 index 00000000..e3abe189 --- /dev/null +++ b/hiro/gtk/widget/tree-view.hpp @@ -0,0 +1,32 @@ +namespace hiro { + +struct pTreeView : pWidget { + Declare(TreeView, Widget) + + auto append(sTreeViewItem item) -> void; + auto collapse() -> void; + auto expand() -> void; + auto remove(sTreeViewItem item) -> void; + auto reset() -> void; + auto setBackgroundColor(Color color) -> void; + auto setCheckable(bool checkable) -> void; + auto setForegroundColor(Color color) -> void; + + auto _activatePath(GtkTreePath* gtkPath) -> void; + auto _buttonEvent(GdkEventButton* gdkEvent) -> signed; + auto _togglePath(string path) -> void; + auto _updateSelected() -> void; + + GtkScrolledWindow* gtkScrolledWindow = nullptr; + GtkWidget* gtkWidgetChild = nullptr; + GtkTreeStore* gtkTreeStore = nullptr; + GtkTreeModel* gtkTreeModel = nullptr; + GtkTreeSelection* gtkTreeSelection = nullptr; + GtkTreeView* gtkTreeView = nullptr; + GtkTreeViewColumn* gtkTreeViewColumn = nullptr; + GtkCellRenderer* gtkCellToggle = nullptr; + GtkCellRenderer* gtkCellPixbuf = nullptr; + GtkCellRenderer* gtkCellText = nullptr; +}; + +} diff --git a/hiro/gtk/widget/vertical-scroller.cpp b/hiro/gtk/widget/vertical-scroller.cpp new file mode 100644 index 00000000..0bd8ef86 --- /dev/null +++ b/hiro/gtk/widget/vertical-scroller.cpp @@ -0,0 +1,41 @@ +namespace hiro { + +static auto VerticalScroller_change(GtkRange* gtkRange, pVerticalScroller* p) -> void { + auto position = (unsigned)gtk_range_get_value(gtkRange); + if(p->state().position == position) return; + p->state().position = position; + if(!p->locked()) p->self().doChange(); +} + +auto pVerticalScroller::construct() -> void { + gtkWidget = gtk_vscrollbar_new(0); + + setLength(state().length); + setPosition(state().position); + + g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScroller_change), (gpointer)this); + + pWidget::construct(); +} + +auto pVerticalScroller::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pVerticalScroller::minimumSize() const -> Size { + return {20, 0}; +} + +auto pVerticalScroller::setLength(unsigned length) -> void { + lock(); + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); + unlock(); +} + +auto pVerticalScroller::setPosition(unsigned position) -> void { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +} diff --git a/hiro/gtk/widget/vertical-scroller.hpp b/hiro/gtk/widget/vertical-scroller.hpp new file mode 100644 index 00000000..e4333c90 --- /dev/null +++ b/hiro/gtk/widget/vertical-scroller.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pVerticalScroller : pWidget { + Declare(VerticalScroller, Widget) + + auto minimumSize() const -> Size; + auto setLength(unsigned length) -> void; + auto setPosition(unsigned position) -> void; +}; + +} diff --git a/hiro/gtk/widget/vertical-slider.cpp b/hiro/gtk/widget/vertical-slider.cpp new file mode 100644 index 00000000..25fed744 --- /dev/null +++ b/hiro/gtk/widget/vertical-slider.cpp @@ -0,0 +1,40 @@ +namespace hiro { + +static auto VerticalSlider_change(GtkRange* gtkRange, pVerticalSlider* p) -> void { + auto position = (unsigned)gtk_range_get_value(gtkRange); + if(p->state().position == position) return; + p->state().position = position; + if(!p->locked()) p->self().doChange(); +} + +auto pVerticalSlider::construct() -> void { + gtkWidget = gtk_vscale_new_with_range(0, 100, 1); + gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); + + setLength(state().length); + setPosition(state().position); + + g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)this); + + pWidget::construct(); +} + +auto pVerticalSlider::destruct() -> void { + gtk_widget_destroy(gtkWidget); +} + +auto pVerticalSlider::minimumSize() const -> Size { + return {20, 0}; +} + +auto pVerticalSlider::setLength(unsigned length) -> void { + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); +} + +auto pVerticalSlider::setPosition(unsigned position) -> void { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +} diff --git a/hiro/gtk/widget/vertical-slider.hpp b/hiro/gtk/widget/vertical-slider.hpp new file mode 100644 index 00000000..58995857 --- /dev/null +++ b/hiro/gtk/widget/vertical-slider.hpp @@ -0,0 +1,11 @@ +namespace hiro { + +struct pVerticalSlider : pWidget { + Declare(VerticalSlider, Widget) + + auto minimumSize() const -> Size; + auto setLength(unsigned length) -> void; + auto setPosition(unsigned position) -> void; +}; + +} diff --git a/hiro/gtk/widget/viewport.cpp b/hiro/gtk/widget/viewport.cpp new file mode 100644 index 00000000..f6a27c94 --- /dev/null +++ b/hiro/gtk/widget/viewport.cpp @@ -0,0 +1,78 @@ +namespace hiro { + +static auto Viewport_dropEvent(GtkWidget* widget, GdkDragContext* context, signed x, signed y, +GtkSelectionData* data, unsigned type, unsigned timestamp, pViewport* p) -> void { + if(!p->state().droppable) return; + lstring paths = DropPaths(data); + if(paths.empty()) return; + p->self().doDrop(paths); +} + +static auto Viewport_mouseLeave(GtkWidget* widget, GdkEventButton* event, pViewport* p) -> signed { + p->self().doMouseLeave(); + return true; +} + +static auto Viewport_mouseMove(GtkWidget* widget, GdkEventButton* event, pViewport* p) -> signed { + p->self().doMouseMove({(signed)event->x, (signed)event->y}); + return true; +} + +static auto Viewport_mousePress(GtkWidget* widget, GdkEventButton* event, pViewport* p) -> signed { + switch(event->button) { + case 1: p->self().doMousePress(Mouse::Button::Left); break; + case 2: p->self().doMousePress(Mouse::Button::Middle); break; + case 3: p->self().doMousePress(Mouse::Button::Right); break; + } + return true; +} + +static auto Viewport_mouseRelease(GtkWidget* widget, GdkEventButton* event, pViewport* p) -> signed { + switch(event->button) { + case 1: p->self().doMouseRelease(Mouse::Button::Left); break; + case 2: p->self().doMouseRelease(Mouse::Button::Middle); break; + case 3: p->self().doMouseRelease(Mouse::Button::Right); break; + } + return true; +} + +auto pViewport::construct() -> void { + gtkWidget = gtk_drawing_area_new(); + gtk_widget_add_events(gtkWidget, + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); + + GdkColor color; + color.pixel = 0; + color.red = 0; + color.green = 0; + color.blue = 0; + gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color); + + setDroppable(state().droppable); + + g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Viewport_mousePress), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Viewport_dropEvent), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this); + g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Viewport_mouseMove), (gpointer)this); + + pWidget::construct(); +} + +auto pViewport::destruct() -> void { + if(gtkWidget) gtk_widget_destroy(gtkWidget), gtkWidget = nullptr; + gtkParent = nullptr; +} + +auto pViewport::handle() const -> uintptr_t { + return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget)); +} + +auto pViewport::setDroppable(bool droppable) -> void { + if(droppable) { + gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_uri_targets(gtkWidget); + } +} + +} diff --git a/hiro/gtk/widget/viewport.hpp b/hiro/gtk/widget/viewport.hpp new file mode 100644 index 00000000..137d0b01 --- /dev/null +++ b/hiro/gtk/widget/viewport.hpp @@ -0,0 +1,10 @@ +namespace hiro { + +struct pViewport : pWidget { + Declare(Viewport, Widget) + + auto handle() const -> uintptr_t; + auto setDroppable(bool droppable) -> void; +}; + +} diff --git a/hiro/gtk/widget/widget.cpp b/hiro/gtk/widget/widget.cpp new file mode 100644 index 00000000..6c03f128 --- /dev/null +++ b/hiro/gtk/widget/widget.cpp @@ -0,0 +1,51 @@ +namespace hiro { + +auto pWidget::construct() -> void { + if(!gtkWidget) return; + if(auto window = self().parentWindow(true)) { + if(window->self()) window->self()->_append(self()); + setFont(self().font(true)); + setVisible(self().visible(true)); + } +} + +auto pWidget::destruct() -> void { +} + +auto pWidget::container(mWidget& widget) -> GtkWidget* { + return nullptr; +} + +auto pWidget::focused() const -> bool { + if(!gtkWidget) return false; + return GTK_WIDGET_HAS_FOCUS(gtkWidget); +} + +auto pWidget::setEnabled(bool enabled) -> void { + if(!gtkWidget) return; + gtk_widget_set_sensitive(gtkWidget, enabled); +} + +auto pWidget::setFocused() -> void { + if(!gtkWidget) return; + gtk_widget_grab_focus(gtkWidget); +} + +auto pWidget::setFont(const string& font) -> void { + if(!gtkWidget) return; + return pFont::setFont(gtkWidget, font); +} + +auto pWidget::setGeometry(Geometry geometry) -> void { + if(!gtkWidget) return; + if(gtkParent) gtk_fixed_move(GTK_FIXED(gtkParent), gtkWidget, geometry.x(), geometry.y()); + gtk_widget_set_size_request(gtkWidget, max(1, geometry.width()), max(1, geometry.height())); + self().doSize(); +} + +auto pWidget::setVisible(bool visible) -> void { + if(!gtkWidget) return; + gtk_widget_set_visible(gtkWidget, visible); +} + +} diff --git a/hiro/gtk/widget/widget.hpp b/hiro/gtk/widget/widget.hpp new file mode 100644 index 00000000..244361eb --- /dev/null +++ b/hiro/gtk/widget/widget.hpp @@ -0,0 +1,18 @@ +namespace hiro { + +struct pWidget : pSizable { + Declare(Widget, Sizable) + + virtual auto container(mWidget& widget) -> GtkWidget*; + virtual auto focused() const -> bool override; + auto setEnabled(bool enabled) -> void override; + virtual auto setFocused() -> void override; + auto setFont(const string& font) -> void override; + auto setGeometry(Geometry geometry) -> void override; + auto setVisible(bool visible) -> void override; + + GtkWidget* gtkWidget = nullptr; + GtkWidget* gtkParent = nullptr; +}; + +} diff --git a/hiro/gtk/window.cpp b/hiro/gtk/window.cpp new file mode 100644 index 00000000..11de8a97 --- /dev/null +++ b/hiro/gtk/window.cpp @@ -0,0 +1,400 @@ +namespace hiro { + +static auto Window_close(GtkWidget* widget, GdkEvent* event, pWindow* p) -> signed { + if(p->state().onClose) { + p->self().doClose(); + } else { + p->self().setVisible(false); + } + if(p->state().modal && !p->pObject::state().visible) p->self().setModal(false); + return true; +} + +static auto Window_expose(GtkWidget* widget, GdkEvent* event, pWindow* p) -> signed { + if(auto color = p->state().backgroundColor) { + cairo_t* context = gdk_cairo_create(widget->window); + + double red = (double)color.red() / 255.0; + double green = (double)color.green() / 255.0; + double blue = (double)color.blue() / 255.0; + double alpha = (double)color.alpha() / 255.0; + + if(gdk_screen_is_composited(gdk_screen_get_default()) + && gdk_screen_get_rgba_colormap(gdk_screen_get_default()) + ) { + cairo_set_source_rgba(context, red, green, blue, alpha); + } else { + cairo_set_source_rgb(context, red, green, blue); + } + + cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); + cairo_paint(context); + cairo_destroy(context); + } + return false; +} + +static auto Window_configure(GtkWidget* widget, GdkEvent* event, pWindow* p) -> signed { + if(!gtk_widget_get_realized(p->widget)) return false; + if(!p->pObject::state().visible) return false; + GdkWindow* gdkWindow = gtk_widget_get_window(widget); + + GdkRectangle border, client; + gdk_window_get_frame_extents(gdkWindow, &border); + gdk_window_get_geometry(gdkWindow, nullptr, nullptr, &client.width, &client.height, nullptr); + gdk_window_get_origin(gdkWindow, &client.x, &client.y); + + if(!p->state().fullScreen) { + //update geometry settings + settings->geometry.frameX = client.x - border.x; + settings->geometry.frameY = client.y - border.y; + settings->geometry.frameWidth = border.width - client.width; + settings->geometry.frameHeight = border.height - client.height; + settings->save(); + } + + Geometry geometry = { + client.x, + client.y + p->_menuHeight(), + client.width, + client.height - p->_menuHeight() - p->_statusHeight() + }; + + //move + if(geometry.x() != p->state().geometry.x() || geometry.y() != p->state().geometry.y()) { + if(!p->state().fullScreen) { + p->state().geometry.setX(geometry.x()); + p->state().geometry.setY(geometry.y()); + } + if(!p->locked()) p->self().doMove(); + } + + //size + if(geometry.width() != p->state().geometry.width() || geometry.height() != p->state().geometry.height()) { + p->onSizePending = true; + } + + return false; +} + +static auto Window_drop(GtkWidget* widget, GdkDragContext* context, signed x, signed y, +GtkSelectionData* data, unsigned type, unsigned timestamp, pWindow* p) -> void { + if(!p->state().droppable) return; + lstring paths = DropPaths(data); + if(paths.empty()) return; + p->self().doDrop(paths); +} + +static auto Window_keyPress(GtkWidget* widget, GdkEventKey* event, pWindow* p) -> signed { + if(auto key = pKeyboard::_translate(event->keyval)) { + p->self().doKeyPress(key); + } + return false; +} + +static auto Window_keyRelease(GtkWidget* widget, GdkEventKey* event, pWindow* p) -> signed { + if(auto key = pKeyboard::_translate(event->keyval)) { + p->self().doKeyRelease(key); + } + return false; +} + +static auto Window_sizeAllocate(GtkWidget* widget, GtkAllocation* allocation, pWindow* p) -> void { + //size-allocate sent from gtk_fixed_move(); detect if layout unchanged and return + if(allocation->width == p->lastAllocation.width + && allocation->height == p->lastAllocation.height) return; + + p->state().geometry.setWidth(allocation->width); + p->state().geometry.setHeight(allocation->height); + + if(auto& layout = p->state().layout) { + layout->setGeometry(p->self().geometry().setPosition(0, 0)); + } + + if(!p->locked() && p->onSizePending) { + p->onSizePending = false; + p->self().doSize(); + } + + p->lastAllocation = *allocation; +} + +static auto Window_sizeRequest(GtkWidget* widget, GtkRequisition* requisition, pWindow* p) -> void { + requisition->width = p->state().geometry.width(); + requisition->height = p->state().geometry.height(); +} + +auto pWindow::construct() -> void { + lastAllocation.width = 0; + lastAllocation.height = 0; + onSizePending = false; + + widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_resizable(GTK_WINDOW(widget), true); + + //if program was given a name, try and set the window taskbar icon from one of the pixmaps folders + if(!Application::state.name); + else if(_setIcon({userpath(), ".local/share/icons/"})); + else if(_setIcon("/usr/local/share/pixmaps/")); + else if(_setIcon("/usr/share/pixmaps/")); + + GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default()); + if(!colormap) colormap = gdk_screen_get_rgb_colormap(gdk_screen_get_default()); + if(colormap) gtk_widget_set_colormap(widget, colormap); + + gtk_widget_set_app_paintable(widget, true); + gtk_widget_add_events(widget, GDK_CONFIGURE); + + menuContainer = gtk_vbox_new(false, 0); + gtk_container_add(GTK_CONTAINER(widget), menuContainer); + gtk_widget_show(menuContainer); + + gtkMenu = gtk_menu_bar_new(); + gtk_box_pack_start(GTK_BOX(menuContainer), gtkMenu, false, false, 0); + + formContainer = gtk_fixed_new(); + gtk_box_pack_start(GTK_BOX(menuContainer), formContainer, true, true, 0); + gtk_widget_show(formContainer); + + statusContainer = gtk_event_box_new(); + gtkStatus = gtk_statusbar_new(); + gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(gtkStatus), true); + gtk_container_add(GTK_CONTAINER(statusContainer), gtkStatus); + gtk_box_pack_start(GTK_BOX(menuContainer), statusContainer, false, false, 0); + gtk_widget_show(statusContainer); + + setBackgroundColor(state().backgroundColor); + setDroppable(state().droppable); + setGeometry(state().geometry); + setResizable(state().resizable); + setTitle(state().title); + + g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)this); + g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)this); + g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)this); + g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_drop), (gpointer)this); + g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPress), (gpointer)this); + g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyRelease), (gpointer)this); + g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)this); + g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)this); +} + +auto pWindow::destruct() -> void { +} + +auto pWindow::append(shared_pointer<mMenuBar> menuBar) -> void { +} + +auto pWindow::append(shared_pointer<mStatusBar> statusBar) -> void { + _setStatusEnabled(statusBar->enabled(true)); + _setStatusFont(statusBar->font(true)); + _setStatusText(statusBar->text()); + _setStatusVisible(statusBar->visible(true)); +} + +auto pWindow::focused() const -> bool { + return gtk_window_is_active(GTK_WINDOW(widget)); +} + +auto pWindow::frameMargin() const -> Geometry { + if(state().fullScreen) return { + 0, _menuHeight(), + 0, _menuHeight() + _statusHeight() + }; + + return { + settings->geometry.frameX, + settings->geometry.frameY + _menuHeight(), + settings->geometry.frameWidth, + settings->geometry.frameHeight + _menuHeight() + _statusHeight() + }; +} + +auto pWindow::remove(shared_pointer<mMenuBar> menuBar) -> void { + _setMenuVisible(false); +} + +auto pWindow::remove(shared_pointer<mStatusBar> statusBar) -> void { + _setStatusVisible(false); +} + +auto pWindow::setBackgroundColor(Color color) -> void { + GdkColor gdkColor = CreateColor(color); + gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); +} + +auto pWindow::setDroppable(bool droppable) -> void { + gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); + if(droppable) gtk_drag_dest_add_uri_targets(widget); +} + +auto pWindow::setEnabled(bool enabled) -> void { + if(auto& menuBar = state().menuBar) { + if(menuBar->self()) menuBar->self()->setEnabled(menuBar->enabled(true)); + } + + if(auto& statusBar = state().statusBar) { + if(statusBar->self()) statusBar->self()->setEnabled(statusBar->enabled(true)); + } + + if(auto& layout = state().layout) { + if(layout->self()) layout->self()->setEnabled(layout->enabled(true)); + } +} + +auto pWindow::setFocused() -> void { + gtk_window_present(GTK_WINDOW(widget)); +} + +auto pWindow::setFullScreen(bool fullScreen) -> void { + if(fullScreen == false) { + gtk_window_unfullscreen(GTK_WINDOW(widget)); + } else { + gtk_window_fullscreen(GTK_WINDOW(widget)); + } +} + +auto pWindow::setGeometry(Geometry geometry) -> void { + Geometry margin = frameMargin(); + gtk_window_move(GTK_WINDOW(widget), geometry.x() - margin.x(), geometry.y() - margin.y()); + + GdkGeometry geom; + geom.min_width = state().resizable ? 1 : state().geometry.width(); + geom.min_height = state().resizable ? 1 : state().geometry.height(); + gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE); + + gtk_widget_set_size_request(formContainer, geometry.width(), geometry.height()); + gtk_window_resize(GTK_WINDOW(widget), geometry.width(), geometry.height() + _menuHeight() + _statusHeight()); +} + +auto pWindow::setModal(bool modal) -> void { + if(modal) { + gtk_window_set_modal(GTK_WINDOW(widget), true); + while(state().modal) { + Application::processEvents(); + if(Application::state.onMain) { + Application::doMain(); + } else { + usleep(20 * 1000); + } + } + gtk_window_set_modal(GTK_WINDOW(widget), false); + } +} + +auto pWindow::setResizable(bool resizable) -> void { + gtk_window_set_resizable(GTK_WINDOW(widget), resizable); + gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(gtkStatus), resizable); +} + +auto pWindow::setTitle(const string& title) -> void { + gtk_window_set_title(GTK_WINDOW(widget), title ? title : " "); +} + +auto pWindow::setVisible(bool visible) -> void { + gtk_widget_set_visible(widget, visible); + + if(auto& menuBar = state().menuBar) { + if(menuBar->self()) menuBar->self()->setVisible(menuBar->visible(true)); + } + + if(auto& statusBar = state().statusBar) { + if(statusBar->self()) statusBar->self()->setVisible(statusBar->visible(true)); + } + + if(visible) { + if(gtk_widget_get_visible(gtkMenu)) { + GtkAllocation allocation; + gtk_widget_get_allocation(gtkMenu, &allocation); + settings->geometry.menuHeight = allocation.height; + } + + if(gtk_widget_get_visible(gtkStatus)) { + GtkAllocation allocation; + gtk_widget_get_allocation(gtkStatus, &allocation); + settings->geometry.statusHeight = allocation.height; + } + } + + if(auto& layout = state().layout) { + if(layout->self()) layout->self()->setVisible(layout->visible(true)); + Application::processEvents(); //todo: this should not be necessary + layout->setGeometry(self().geometry().setPosition(0, 0)); + } +} + +auto pWindow::_append(mWidget& widget) -> void { + if(!widget.self()) return; + if(auto parent = widget.parentWidget(true)) { + if(parent->self()) widget.self()->gtkParent = parent->self()->container(widget); + } else { + widget.self()->gtkParent = formContainer; + } + gtk_fixed_put(GTK_FIXED(widget.self()->gtkParent), widget.self()->gtkWidget, 0, 0); +} + +auto pWindow::_append(mMenu& menu) -> void { + if(menu.self()) gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), menu.self()->widget); +} + +auto pWindow::_menuHeight() const -> signed { + return gtk_widget_get_visible(gtkMenu) ? settings->geometry.menuHeight : 0; +} + +auto pWindow::_setIcon(const string& pathname) -> bool { + string filename; + + filename = {pathname, Application::state.name, ".svg"}; + if(file::exists(filename)) { + gtk_window_set_icon_from_file(GTK_WINDOW(widget), filename, nullptr); + return true; + } + + filename = {pathname, Application::state.name, ".png"}; + if(file::exists(filename)) { + //maximum image size GTK+ supports is 256x256; scale image down if necessary to prevent error + nall::image icon(filename); + icon.scale(min(256u, icon.width), min(256u, icon.height), true); + GdkPixbuf* pixbuf = CreatePixbuf(icon); + gtk_window_set_icon(GTK_WINDOW(widget), pixbuf); + g_object_unref(G_OBJECT(pixbuf)); + return true; + } + + return false; +} + +auto pWindow::_setMenuEnabled(bool enabled) -> void { + gtk_widget_set_sensitive(gtkMenu, enabled); +} + +auto pWindow::_setMenuFont(const string& font) -> void { + pFont::setFont(gtkMenu, font); +} + +auto pWindow::_setMenuVisible(bool visible) -> void { + gtk_widget_set_visible(gtkMenu, visible); +} + +auto pWindow::_setStatusEnabled(bool enabled) -> void { + gtk_widget_set_sensitive(gtkStatus, enabled); +} + +auto pWindow::_setStatusFont(const string& font) -> void { + pFont::setFont(gtkStatus, font); +} + +auto pWindow::_setStatusText(const string& text) -> void { + gtk_statusbar_pop(GTK_STATUSBAR(gtkStatus), 1); + gtk_statusbar_push(GTK_STATUSBAR(gtkStatus), 1, text); +} + +auto pWindow::_setStatusVisible(bool visible) -> void { + gtk_widget_set_visible(gtkStatus, visible); +} + +auto pWindow::_statusHeight() const -> signed { + return gtk_widget_get_visible(gtkStatus) ? settings->geometry.statusHeight : 0; +} + +} diff --git a/hiro/gtk/window.hpp b/hiro/gtk/window.hpp new file mode 100644 index 00000000..7f88ba8f --- /dev/null +++ b/hiro/gtk/window.hpp @@ -0,0 +1,46 @@ +namespace hiro { + +struct pWindow : pObject { + Declare(Window, Object) + + GtkWidget* widget = nullptr; + GtkWidget* menuContainer = nullptr; + GtkWidget* formContainer = nullptr; + GtkWidget* statusContainer = nullptr; + GtkWidget* gtkMenu = nullptr; + GtkWidget* gtkStatus = nullptr; + GtkAllocation lastAllocation = {0}; + bool onSizePending = false; + + auto append(shared_pointer<mMenuBar> menuBar) -> void; + auto append(shared_pointer<mStatusBar> statusBar) -> void; + auto focused() const -> bool override; + auto frameMargin() const -> Geometry; + auto remove(shared_pointer<mMenuBar> menuBar) -> void; + auto remove(shared_pointer<mStatusBar> statusBar) -> void; + auto setBackgroundColor(Color color) -> void; + auto setDroppable(bool droppable) -> void; + auto setEnabled(bool enabled) -> void override; + auto setFocused() -> void override; + auto setFullScreen(bool fullScreen) -> void; + auto setGeometry(Geometry geometry) -> void; + auto setModal(bool modal) -> void; + auto setResizable(bool resizable) -> void; + auto setTitle(const string& title) -> void; + auto setVisible(bool visible) -> void override; + + auto _append(mWidget& widget) -> void; + auto _append(mMenu& menu) -> void; + auto _menuHeight() const -> signed; + auto _setIcon(const string& basename) -> bool; + auto _setMenuEnabled(bool enabled) -> void; + auto _setMenuFont(const string& font) -> void; + auto _setMenuVisible(bool visible) -> void; + auto _setStatusEnabled(bool enabled) -> void; + auto _setStatusFont(const string& font) -> void; + auto _setStatusText(const string& text) -> void; + auto _setStatusVisible(bool visible) -> void; + auto _statusHeight() const -> signed; +}; + +} diff --git a/hiro/hiro.cpp b/hiro/hiro.cpp new file mode 100644 index 00000000..ab89294f --- /dev/null +++ b/hiro/hiro.cpp @@ -0,0 +1,7 @@ +#ifndef HIRO_CPP +#define HIRO_CPP + +#include "core/core.cpp" +#include "extension/extension.cpp" + +#endif diff --git a/hiro/hiro.hpp b/hiro/hiro.hpp new file mode 100644 index 00000000..8adb9a69 --- /dev/null +++ b/hiro/hiro.hpp @@ -0,0 +1,16 @@ +/* hiro + * author: byuu + * license: ISC + * + * hiro is a cross-platform GUI toolkit + * it provides a consistent, minimal API wrapper to: Windows, Cocoa, GTK+ and Qt + * it also provides a reference wrapper for terminal applications with optional UIs + */ + +#ifndef HIRO_HPP +#define HIRO_HPP + +#include "core/core.hpp" +#include "extension/extension.hpp" + +#endif diff --git a/phoenix/qt/action/action.cpp b/hiro/qt/action/action.cpp similarity index 100% rename from phoenix/qt/action/action.cpp rename to hiro/qt/action/action.cpp diff --git a/phoenix/qt/action/check-item.cpp b/hiro/qt/action/check-item.cpp similarity index 100% rename from phoenix/qt/action/check-item.cpp rename to hiro/qt/action/check-item.cpp diff --git a/phoenix/qt/action/item.cpp b/hiro/qt/action/item.cpp similarity index 100% rename from phoenix/qt/action/item.cpp rename to hiro/qt/action/item.cpp diff --git a/phoenix/qt/action/menu.cpp b/hiro/qt/action/menu.cpp similarity index 96% rename from phoenix/qt/action/menu.cpp rename to hiro/qt/action/menu.cpp index efe5188a..0b258fa3 100644 --- a/phoenix/qt/action/menu.cpp +++ b/hiro/qt/action/menu.cpp @@ -18,7 +18,7 @@ void pMenu::remove(Action& action) { if(dynamic_cast<Menu*>(&action)) { //QMenu::removeMenu() does not exist qtMenu->clear(); - for(auto &action : menu.state.action) append(action); + for(auto& action : menu.state.action) append(action); } else if(dynamic_cast<Separator*>(&action)) { qtMenu->removeAction(((Separator&)action).p.qtAction); } else if(dynamic_cast<Item*>(&action)) { diff --git a/phoenix/qt/action/radio-item.cpp b/hiro/qt/action/radio-item.cpp similarity index 89% rename from phoenix/qt/action/radio-item.cpp rename to hiro/qt/action/radio-item.cpp index e7c9974b..0dc16084 100644 --- a/phoenix/qt/action/radio-item.cpp +++ b/hiro/qt/action/radio-item.cpp @@ -1,13 +1,13 @@ namespace phoenix { void pRadioItem::setChecked() { - locked = true; + lock(); for(auto& item : radioItem.state.group) { bool checkState = item.p.qtAction == qtAction; item.state.checked = checkState; item.p.qtAction->setChecked(checkState); } - locked = false; + unlock(); } void pRadioItem::setGroup(const group<RadioItem>& group) { @@ -35,7 +35,7 @@ void pRadioItem::destructor() { void pRadioItem::onActivate() { if(!radioItem.state.checked) { setChecked(); - if(!locked && radioItem.onActivate) radioItem.onActivate(); + if(!locked() && radioItem.onActivate) radioItem.onActivate(); } } diff --git a/phoenix/qt/action/separator.cpp b/hiro/qt/action/separator.cpp similarity index 100% rename from phoenix/qt/action/separator.cpp rename to hiro/qt/action/separator.cpp diff --git a/phoenix/qt/application.cpp b/hiro/qt/application.cpp similarity index 100% rename from phoenix/qt/application.cpp rename to hiro/qt/application.cpp diff --git a/phoenix/qt/browser-window.cpp b/hiro/qt/browser-window.cpp similarity index 100% rename from phoenix/qt/browser-window.cpp rename to hiro/qt/browser-window.cpp diff --git a/phoenix/qt/desktop.cpp b/hiro/qt/desktop.cpp similarity index 100% rename from phoenix/qt/desktop.cpp rename to hiro/qt/desktop.cpp diff --git a/phoenix/qt/font.cpp b/hiro/qt/font.cpp similarity index 93% rename from phoenix/qt/font.cpp rename to hiro/qt/font.cpp index 3c6fe572..58542f67 100644 --- a/phoenix/qt/font.cpp +++ b/hiro/qt/font.cpp @@ -23,9 +23,7 @@ Size pFont::size(string font, string text) { } QFont pFont::create(string description) { - lstring part; - part.split<2>(",", description); - for(auto& item : part) item.trim(" "); + lstring part = description.split<2>(",").strip(); string family = "Sans"; unsigned size = 8u; diff --git a/phoenix/qt/header.hpp b/hiro/qt/header.hpp similarity index 100% rename from phoenix/qt/header.hpp rename to hiro/qt/header.hpp diff --git a/phoenix/gtk/keyboard.cpp b/hiro/qt/keyboard.cpp similarity index 100% rename from phoenix/gtk/keyboard.cpp rename to hiro/qt/keyboard.cpp diff --git a/phoenix/qt/message-window.cpp b/hiro/qt/message-window.cpp similarity index 100% rename from phoenix/qt/message-window.cpp rename to hiro/qt/message-window.cpp diff --git a/phoenix/qt/monitor.cpp b/hiro/qt/monitor.cpp similarity index 100% rename from phoenix/qt/monitor.cpp rename to hiro/qt/monitor.cpp diff --git a/phoenix/qt/mouse.cpp b/hiro/qt/mouse.cpp similarity index 100% rename from phoenix/qt/mouse.cpp rename to hiro/qt/mouse.cpp diff --git a/phoenix/qt/platform.cpp b/hiro/qt/platform.cpp similarity index 95% rename from phoenix/qt/platform.cpp rename to hiro/qt/platform.cpp index 4547e362..849bd5b4 100644 --- a/phoenix/qt/platform.cpp +++ b/hiro/qt/platform.cpp @@ -13,6 +13,7 @@ #include "font.cpp" #include "timer.cpp" #include "window.cpp" +#include "popup-menu.cpp" #include "action/action.cpp" #include "action/menu.cpp" @@ -32,6 +33,7 @@ #include "widget/hex-edit.cpp" #include "widget/horizontal-scroller.cpp" #include "widget/horizontal-slider.cpp" +#include "widget/icon-view.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" #include "widget/list-view.cpp" diff --git a/phoenix/qt/platform.moc b/hiro/qt/platform.moc similarity index 90% rename from phoenix/qt/platform.moc rename to hiro/qt/platform.moc index ccf22d32..7ff83e9b 100644 --- a/phoenix/qt/platform.moc +++ b/hiro/qt/platform.moc @@ -1,8 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Fri Feb 14 13:37:55 2014 -** by: The Qt Meta Object Compiler version 63 (Qt 4.8.2) +** Created by: The Qt Meta Object Compiler version 63 (Qt 4.8.5) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ @@ -10,7 +9,7 @@ #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'platform.moc.hpp' doesn't include <QObject>." #elif Q_MOC_OUTPUT_REVISION != 63 -#error "This file was generated using the moc from 4.8.2. It" +#error "This file was generated using the moc from 4.8.5. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif @@ -30,13 +29,13 @@ static const uint qt_meta_data_phoenix__pTimer[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 17, 16, 16, 16, 0x0a, + 16, 29, 29, 29, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pTimer[] = { - "phoenix::pTimer\0\0onActivate()\0" + "phoenix::pTimer\0onActivate()\0\0" }; void phoenix::pTimer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -169,13 +168,13 @@ static const uint qt_meta_data_phoenix__pItem[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 16, 15, 15, 15, 0x0a, + 15, 28, 28, 28, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pItem[] = { - "phoenix::pItem\0\0onActivate()\0" + "phoenix::pItem\0onActivate()\0\0" }; void phoenix::pItem::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -245,13 +244,13 @@ static const uint qt_meta_data_phoenix__pCheckItem[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 21, 20, 20, 20, 0x0a, + 20, 31, 31, 31, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pCheckItem[] = { - "phoenix::pCheckItem\0\0onToggle()\0" + "phoenix::pCheckItem\0onToggle()\0\0" }; void phoenix::pCheckItem::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -321,13 +320,13 @@ static const uint qt_meta_data_phoenix__pRadioItem[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 21, 20, 20, 20, 0x0a, + 20, 33, 33, 33, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pRadioItem[] = { - "phoenix::pRadioItem\0\0onActivate()\0" + "phoenix::pRadioItem\0onActivate()\0\0" }; void phoenix::pRadioItem::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -397,13 +396,13 @@ static const uint qt_meta_data_phoenix__pButton[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 18, 17, 17, 17, 0x0a, + 17, 30, 30, 30, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pButton[] = { - "phoenix::pButton\0\0onActivate()\0" + "phoenix::pButton\0onActivate()\0\0" }; void phoenix::pButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -536,14 +535,14 @@ static const uint qt_meta_data_phoenix__pCheckButton[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 31, 23, 22, 22, 0x0a, + 22, 37, 45, 45, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pCheckButton[] = { - "phoenix::pCheckButton\0\0checked\0" - "onToggle(bool)\0" + "phoenix::pCheckButton\0onToggle(bool)\0" + "checked\0\0" }; void phoenix::pCheckButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -612,13 +611,13 @@ static const uint qt_meta_data_phoenix__pCheckLabel[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 22, 21, 21, 21, 0x0a, + 21, 32, 32, 32, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pCheckLabel[] = { - "phoenix::pCheckLabel\0\0onToggle()\0" + "phoenix::pCheckLabel\0onToggle()\0\0" }; void phoenix::pCheckLabel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -688,13 +687,13 @@ static const uint qt_meta_data_phoenix__pComboButton[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 23, 22, 22, 22, 0x0a, + 22, 33, 33, 33, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pComboButton[] = { - "phoenix::pComboButton\0\0onChange()\0" + "phoenix::pComboButton\0onChange()\0\0" }; void phoenix::pComboButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -890,13 +889,13 @@ static const uint qt_meta_data_phoenix__pHexEdit[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 19, 18, 18, 18, 0x0a, + 18, 29, 29, 29, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pHexEdit[] = { - "phoenix::pHexEdit\0\0onScroll()\0" + "phoenix::pHexEdit\0onScroll()\0\0" }; void phoenix::pHexEdit::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -966,13 +965,14 @@ static const uint qt_meta_data_phoenix__pHorizontalScroller[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 30, 29, 29, 29, 0x0a, + 29, 40, 40, 40, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pHorizontalScroller[] = { - "phoenix::pHorizontalScroller\0\0onChange()\0" + "phoenix::pHorizontalScroller\0onChange()\0" + "\0" }; void phoenix::pHorizontalScroller::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1042,13 +1042,14 @@ static const uint qt_meta_data_phoenix__pHorizontalSlider[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 28, 27, 27, 27, 0x0a, + 27, 38, 38, 38, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pHorizontalSlider[] = { - "phoenix::pHorizontalSlider\0\0onChange()\0" + "phoenix::pHorizontalSlider\0onChange()\0" + "\0" }; void phoenix::pHorizontalSlider::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1104,6 +1105,87 @@ int phoenix::pHorizontalSlider::qt_metacall(QMetaObject::Call _c, int _id, void } return _id; } +static const uint qt_meta_data_phoenix__pIconView[] = { + + // content: + 6, // revision + 0, // classname + 0, 0, // classinfo + 3, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 19, 32, 32, 32, 0x0a, + 33, 32, 32, 32, 0x0a, + 44, 32, 32, 32, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_phoenix__pIconView[] = { + "phoenix::pIconView\0onActivate()\0\0" + "onChange()\0onContext()\0" +}; + +void phoenix::pIconView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + if (_c == QMetaObject::InvokeMetaMethod) { + Q_ASSERT(staticMetaObject.cast(_o)); + pIconView *_t = static_cast<pIconView *>(_o); + switch (_id) { + case 0: _t->onActivate(); break; + case 1: _t->onChange(); break; + case 2: _t->onContext(); break; + default: ; + } + } + Q_UNUSED(_a); +} + +const QMetaObjectExtraData phoenix::pIconView::staticMetaObjectExtraData = { + 0, qt_static_metacall +}; + +const QMetaObject phoenix::pIconView::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_phoenix__pIconView, + qt_meta_data_phoenix__pIconView, &staticMetaObjectExtraData } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &phoenix::pIconView::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *phoenix::pIconView::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *phoenix::pIconView::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_phoenix__pIconView)) + return static_cast<void*>(const_cast< pIconView*>(this)); + if (!strcmp(_clname, "pWidget")) + return static_cast< pWidget*>(const_cast< pIconView*>(this)); + return QObject::qt_metacast(_clname); +} + +int phoenix::pIconView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + if (_id < 3) + qt_static_metacall(this, _c, _id, _a); + _id -= 3; + } + return _id; +} static const uint qt_meta_data_phoenix__pLineEdit[] = { // content: @@ -1118,14 +1200,14 @@ static const uint qt_meta_data_phoenix__pLineEdit[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 20, 19, 19, 19, 0x0a, - 33, 19, 19, 19, 0x0a, + 19, 32, 32, 32, 0x0a, + 33, 32, 32, 32, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pLineEdit[] = { - "phoenix::pLineEdit\0\0onActivate()\0" + "phoenix::pLineEdit\0onActivate()\0\0" "onChange()\0" }; @@ -1189,7 +1271,7 @@ static const uint qt_meta_data_phoenix__pListView[] = { 6, // revision 0, // classname 0, 0, // classinfo - 3, 14, // methods + 6, 14, // methods 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors @@ -1197,17 +1279,22 @@ static const uint qt_meta_data_phoenix__pListView[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 20, 19, 19, 19, 0x0a, - 38, 33, 19, 19, 0x0a, - 65, 33, 19, 19, 0x0a, + 19, 32, 32, 32, 0x0a, + 33, 32, 32, 32, 0x0a, + 44, 32, 32, 32, 0x0a, + 56, 68, 32, 32, 0x0a, + 75, 102, 32, 32, 0x0a, + 107, 141, 161, 32, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pListView[] = { - "phoenix::pListView\0\0onActivate()\0item\0" - "onChange(QTreeWidgetItem*)\0" - "onToggle(QTreeWidgetItem*)\0" + "phoenix::pListView\0onActivate()\0\0" + "onChange()\0onContext()\0onSort(int)\0" + "column\0onToggle(QTreeWidgetItem*)\0" + "item\0calculateAlignment(double,double)\0" + "horizontal,vertical\0int\0" }; void phoenix::pListView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1217,8 +1304,12 @@ void phoenix::pListView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, i pListView *_t = static_cast<pListView *>(_o); switch (_id) { case 0: _t->onActivate(); break; - case 1: _t->onChange((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break; - case 2: _t->onToggle((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break; + case 1: _t->onChange(); break; + case 2: _t->onContext(); break; + case 3: _t->onSort((*reinterpret_cast< int(*)>(_a[1]))); break; + case 4: _t->onToggle((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break; + case 5: { int _r = _t->calculateAlignment((*reinterpret_cast< double(*)>(_a[1])),(*reinterpret_cast< double(*)>(_a[2]))); + if (_a[0]) *reinterpret_cast< int*>(_a[0]) = _r; } break; default: ; } } @@ -1258,9 +1349,9 @@ int phoenix::pListView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { - if (_id < 3) + if (_id < 6) qt_static_metacall(this, _c, _id, _a); - _id -= 3; + _id -= 6; } return _id; } @@ -1278,13 +1369,13 @@ static const uint qt_meta_data_phoenix__pRadioLabel[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 22, 21, 21, 21, 0x0a, + 21, 34, 34, 34, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pRadioLabel[] = { - "phoenix::pRadioLabel\0\0onActivate()\0" + "phoenix::pRadioLabel\0onActivate()\0\0" }; void phoenix::pRadioLabel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1354,13 +1445,13 @@ static const uint qt_meta_data_phoenix__pRadioButton[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 23, 22, 22, 22, 0x0a, + 22, 35, 35, 35, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pRadioButton[] = { - "phoenix::pRadioButton\0\0onActivate()\0" + "phoenix::pRadioButton\0onActivate()\0\0" }; void phoenix::pRadioButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1430,14 +1521,14 @@ static const uint qt_meta_data_phoenix__pTabFrame[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 30, 20, 19, 19, 0x0a, + 19, 33, 43, 43, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pTabFrame[] = { - "phoenix::pTabFrame\0\0selection\0" - "onChange(int)\0" + "phoenix::pTabFrame\0onChange(int)\0" + "selection\0\0" }; void phoenix::pTabFrame::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1506,13 +1597,13 @@ static const uint qt_meta_data_phoenix__pTextEdit[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 20, 19, 19, 19, 0x0a, + 19, 30, 30, 30, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pTextEdit[] = { - "phoenix::pTextEdit\0\0onChange()\0" + "phoenix::pTextEdit\0onChange()\0\0" }; void phoenix::pTextEdit::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1582,13 +1673,14 @@ static const uint qt_meta_data_phoenix__pVerticalScroller[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 28, 27, 27, 27, 0x0a, + 27, 38, 38, 38, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pVerticalScroller[] = { - "phoenix::pVerticalScroller\0\0onChange()\0" + "phoenix::pVerticalScroller\0onChange()\0" + "\0" }; void phoenix::pVerticalScroller::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) @@ -1658,13 +1750,14 @@ static const uint qt_meta_data_phoenix__pVerticalSlider[] = { 0, // signalCount // slots: signature, parameters, type, tag, flags - 26, 25, 25, 25, 0x0a, + 25, 36, 36, 36, 0x0a, 0 // eod }; static const char qt_meta_stringdata_phoenix__pVerticalSlider[] = { - "phoenix::pVerticalSlider\0\0onChange()\0" + "phoenix::pVerticalSlider\0onChange()\0" + "\0" }; void phoenix::pVerticalSlider::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) diff --git a/phoenix/qt/platform.moc.hpp b/hiro/qt/platform.moc.hpp similarity index 83% rename from phoenix/qt/platform.moc.hpp rename to hiro/qt/platform.moc.hpp index 7a8a5677..ac1b96b7 100644 --- a/phoenix/qt/platform.moc.hpp +++ b/hiro/qt/platform.moc.hpp @@ -84,9 +84,13 @@ struct pMessageWindow { struct pObject { Object& object; - bool locked; + signed locks = 0; - pObject(Object& object) : object(object), locked(false) {} + bool locked() const { return locks != 0; } + void lock() { locks++; } + void unlock() { locks--; } + + pObject(Object& object) : object(object) {} virtual ~pObject() {} void constructor() {} void destructor() {} @@ -138,7 +142,6 @@ public: void append(Widget& widget); Geometry frameMargin(); bool focused(); - Geometry geometry(); void remove(Layout& layout); void remove(Menu& menu); void remove(Widget& widget); @@ -164,6 +167,19 @@ public: void updateFrameGeometry(); }; +struct pPopupMenu : public pObject { + PopupMenu& popupMenu; + QMenu* qtMenu; + + void append(Action& action); + void remove(Action& action); + void setVisible(); + + pPopupMenu(PopupMenu& popupMenu) : pObject(popupMenu), popupMenu(popupMenu) {} + void constructor(); + void destructor(); +}; + struct pAction : public pObject { Action& action; @@ -304,6 +320,7 @@ public: QToolButton* qtButton; Size minimumSize(); + void setBordered(bool bordered); void setImage(const image& image, Orientation orientation); void setText(string text); @@ -400,12 +417,11 @@ public: ComboButton& comboButton; QComboBox* qtComboButton; - void append(string text); + void append(); Size minimumSize(); void remove(unsigned selection); void reset(); - unsigned selection(); - void setSelection(unsigned selection); + void setSelected(unsigned selection); void setText(unsigned selection, string text); pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {} @@ -543,6 +559,42 @@ public slots: void onChange(); }; +struct pIconView : public QObject, public pWidget { + Q_OBJECT + +public: + IconView& iconView; + struct QtListWidget : public QListWidget { + void resizeEvent(QResizeEvent*); + }; + QtListWidget* qtIconView; + + void append(); + void remove(unsigned selection); + void reset(); + void setBackgroundColor(Color color); + void setFlow(Orientation flow); + void setForegroundColor(Color color); + void setImage(unsigned selection, const image& image); + void setOrientation(Orientation orientation); + void setSelected(unsigned selection, bool selected); + void setSelected(const vector<unsigned>& selections); + void setSelectedAll(); + void setSelectedNone(); + void setSingleSelection(bool singleSelection); + void setText(unsigned selection, const string& text); + + pIconView(IconView& iconView) : pWidget(iconView), iconView(iconView) {} + void constructor(); + void destructor(); + void orphan(); + +public slots: + void onActivate(); + void onChange(); + void onContext(); +}; + struct pLabel : public pWidget { Label& label; QLabel* qtLabel; @@ -585,22 +637,53 @@ struct pListView : public QObject, public pWidget { public: ListView& listView; - QTreeWidget* qtListView; + struct QtTreeWidget : public QTreeWidget { + pListView& self; + void mousePressEvent(QMouseEvent*); + QtTreeWidget(pListView& self); + }; + struct QtTreeWidgetDelegate : public QStyledItemDelegate { + pListView& self; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + QtTreeWidgetDelegate(pListView& self); + }; + QtTreeWidget* qtListView; + QtTreeWidgetDelegate* qtListViewDelegate; - void append(const lstring& text); - void autoSizeColumns(); - void remove(unsigned selection); + void appendColumn(); + void appendItem(); + void removeColumn(unsigned position); + void removeItem(unsigned position); void reset(); + void resizeColumns(); + void setActiveColumn(unsigned column); void setBackgroundColor(Color color); void setCheckable(bool checkable); - void setChecked(unsigned selection, bool checked); + void setChecked(unsigned position, bool checked); + void setChecked(const vector<unsigned>& selections); + void setCheckedAll(); + void setCheckedNone(); + void setColumnBackgroundColor(unsigned position, maybe<Color> color); + void setColumnEditable(unsigned position, bool editable); + void setColumnFont(unsigned position, maybe<string> font); + void setColumnForegroundColor(unsigned position, maybe<Color> color); + void setColumnHorizontalAlignment(unsigned position, double alignment); + void setColumnResizable(unsigned position, bool resizable); + void setColumnSortable(unsigned position, bool sortable); + void setColumnText(unsigned position, const string& text); + void setColumnVerticalAlignment(unsigned position, double alignment); + void setColumnVisible(unsigned position, bool visible); + void setColumnWidth(unsigned position, signed width); void setForegroundColor(Color color); - void setHeaderText(const lstring& text); + void setGridVisible(bool visible); void setHeaderVisible(bool visible); - void setImage(unsigned selection, unsigned position, const image& image); - void setSelected(bool selected); - void setSelection(unsigned selection); - void setText(unsigned selection, unsigned position, string text); + void setImage(unsigned row, unsigned column, const image& image); + void setSelected(unsigned position, bool selected); + void setSelected(const vector<unsigned>& selections); + void setSelectedAll(); + void setSelectedNone(); + void setSingleSelection(bool singleSelection); + void setText(unsigned row, unsigned column, string text); pListView(ListView& listView) : pWidget(listView), listView(listView) {} void constructor(); @@ -609,8 +692,11 @@ public: public slots: void onActivate(); - void onChange(QTreeWidgetItem* item); + void onChange(); + void onContext(); + void onSort(int column); void onToggle(QTreeWidgetItem* item); + int calculateAlignment(double horizontal, double vertical); }; struct pProgressBar : public pWidget { @@ -679,14 +765,14 @@ public: TabFrame& tabFrame; QTabWidget* qtTabFrame; - void append(string text, const image& image); + void append(); QWidget* container(Widget& widget); Position displacement(); void remove(unsigned selection); void setEnabled(bool enabled); void setGeometry(Geometry geometry); void setImage(unsigned selection, const image& image); - void setSelection(unsigned selection); + void setSelected(unsigned selection); void setText(unsigned selection, string text); void setVisible(bool visible); diff --git a/hiro/qt/popup-menu.cpp b/hiro/qt/popup-menu.cpp new file mode 100644 index 00000000..789765c6 --- /dev/null +++ b/hiro/qt/popup-menu.cpp @@ -0,0 +1,46 @@ +namespace phoenix { + +void pPopupMenu::append(Action& action) { + if(dynamic_cast<Menu*>(&action)) { + qtMenu->addMenu(((Menu&)action).p.qtMenu); + } else if(dynamic_cast<Separator*>(&action)) { + qtMenu->addAction(((Separator&)action).p.qtAction); + } else if(dynamic_cast<Item*>(&action)) { + qtMenu->addAction(((Item&)action).p.qtAction); + } else if(dynamic_cast<CheckItem*>(&action)) { + qtMenu->addAction(((CheckItem&)action).p.qtAction); + } else if(dynamic_cast<RadioItem*>(&action)) { + qtMenu->addAction(((RadioItem&)action).p.qtAction); + } +} + +void pPopupMenu::remove(Action& action) { + if(dynamic_cast<Menu*>(&action)) { + //QMenu::removeMenu() does not exist + qtMenu->clear(); + for(auto& action : popupMenu.state.action) append(action); + } else if(dynamic_cast<Separator*>(&action)) { + qtMenu->removeAction(((Separator&)action).p.qtAction); + } else if(dynamic_cast<Item*>(&action)) { + qtMenu->removeAction(((Item&)action).p.qtAction); + } else if(dynamic_cast<CheckItem*>(&action)) { + qtMenu->removeAction(((CheckItem&)action).p.qtAction); + } else if(dynamic_cast<RadioItem*>(&action)) { + qtMenu->removeAction(((RadioItem&)action).p.qtAction); + } +} + +void pPopupMenu::setVisible() { + qtMenu->popup(QCursor::pos()); +} + +void pPopupMenu::constructor() { + qtMenu = new QMenu; +} + +void pPopupMenu::destructor() { + delete qtMenu; + qtMenu = nullptr; +} + +} diff --git a/phoenix/qt/settings.cpp b/hiro/qt/settings.cpp similarity index 100% rename from phoenix/qt/settings.cpp rename to hiro/qt/settings.cpp diff --git a/phoenix/qt/timer.cpp b/hiro/qt/timer.cpp similarity index 100% rename from phoenix/qt/timer.cpp rename to hiro/qt/timer.cpp diff --git a/phoenix/qt/utility.cpp b/hiro/qt/utility.cpp similarity index 99% rename from phoenix/qt/utility.cpp rename to hiro/qt/utility.cpp index 5e4f34c8..4a175807 100644 --- a/phoenix/qt/utility.cpp +++ b/hiro/qt/utility.cpp @@ -1,6 +1,7 @@ namespace phoenix { static QIcon CreateIcon(const nall::image& image, bool scale = false) { + if(image.empty()) return QIcon(); nall::image qtBuffer = image; qtBuffer.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); if(scale) qtBuffer.scale(16, 16, Interpolation::Linear); diff --git a/phoenix/qt/widget/button.cpp b/hiro/qt/widget/button.cpp similarity index 84% rename from phoenix/qt/widget/button.cpp rename to hiro/qt/widget/button.cpp index 32ad8463..083e5272 100644 --- a/phoenix/qt/widget/button.cpp +++ b/hiro/qt/widget/button.cpp @@ -13,7 +13,11 @@ Size pButton::minimumSize() { size.height += button.state.image.height; } - return {size.width + 20, size.height + 12}; + return {size.width + (button.state.text ? 20 : 12), size.height + 12}; +} + +void pButton::setBordered(bool bordered) { + qtButton->setAutoRaise(bordered == false); } void pButton::setImage(const image& image, Orientation orientation) { @@ -36,6 +40,8 @@ void pButton::constructor() { connect(qtButton, SIGNAL(released()), SLOT(onActivate())); pWidget::synchronizeState(); + setBordered(button.state.bordered); + setImage(button.state.image, button.state.orientation); setText(button.state.text); } diff --git a/phoenix/qt/widget/canvas.cpp b/hiro/qt/widget/canvas.cpp similarity index 100% rename from phoenix/qt/widget/canvas.cpp rename to hiro/qt/widget/canvas.cpp diff --git a/phoenix/qt/widget/check-button.cpp b/hiro/qt/widget/check-button.cpp similarity index 94% rename from phoenix/qt/widget/check-button.cpp rename to hiro/qt/widget/check-button.cpp index 921dc15d..6248ab51 100644 --- a/phoenix/qt/widget/check-button.cpp +++ b/hiro/qt/widget/check-button.cpp @@ -17,9 +17,9 @@ Size pCheckButton::minimumSize() { } void pCheckButton::setChecked(bool checked) { - locked = true; + lock(); qtCheckButton->setChecked(checked); - locked = false; + unlock(); } void pCheckButton::setImage(const image& image, Orientation orientation) { @@ -57,7 +57,7 @@ void pCheckButton::orphan() { void pCheckButton::onToggle(bool checked) { checkButton.state.checked = checked; - if(!locked && checkButton.onToggle) checkButton.onToggle(); + if(!locked() && checkButton.onToggle) checkButton.onToggle(); } } diff --git a/phoenix/qt/widget/check-label.cpp b/hiro/qt/widget/check-label.cpp similarity index 90% rename from phoenix/qt/widget/check-label.cpp rename to hiro/qt/widget/check-label.cpp index 4e88e5b6..b3246fa4 100644 --- a/phoenix/qt/widget/check-label.cpp +++ b/hiro/qt/widget/check-label.cpp @@ -6,9 +6,9 @@ Size pCheckLabel::minimumSize() { } void pCheckLabel::setChecked(bool checked) { - locked = true; + lock(); qtCheckLabel->setChecked(checked); - locked = false; + unlock(); } void pCheckLabel::setText(string text) { @@ -36,7 +36,7 @@ void pCheckLabel::orphan() { void pCheckLabel::onToggle() { checkLabel.state.checked = qtCheckLabel->isChecked(); - if(!locked && checkLabel.onToggle) checkLabel.onToggle(); + if(!locked() && checkLabel.onToggle) checkLabel.onToggle(); } } diff --git a/phoenix/qt/widget/combo-button.cpp b/hiro/qt/widget/combo-button.cpp similarity index 67% rename from phoenix/qt/widget/combo-button.cpp rename to hiro/qt/widget/combo-button.cpp index 5b25bc79..4e7250c7 100644 --- a/phoenix/qt/widget/combo-button.cpp +++ b/hiro/qt/widget/combo-button.cpp @@ -1,9 +1,9 @@ namespace phoenix { -void pComboButton::append(string text) { - locked = true; - qtComboButton->addItem(QString::fromUtf8(text)); - locked = false; +void pComboButton::append() { + lock(); + qtComboButton->addItem(""); + unlock(); } Size pComboButton::minimumSize() { @@ -14,23 +14,22 @@ Size pComboButton::minimumSize() { } void pComboButton::remove(unsigned selection) { - locked = true; + lock(); qtComboButton->removeItem(selection); - locked = false; - - if(selection == comboButton.state.selection) comboButton.setSelection(0); + if(selection == comboButton.state.selection) comboButton[0].setSelected(); + unlock(); } void pComboButton::reset() { - locked = true; + lock(); while(qtComboButton->count()) qtComboButton->removeItem(0); - locked = false; + unlock(); } -void pComboButton::setSelection(unsigned selection) { - locked = true; +void pComboButton::setSelected(unsigned selection) { + lock(); qtComboButton->setCurrentIndex(selection); - locked = false; + unlock(); } void pComboButton::setText(unsigned selection, string text) { @@ -43,10 +42,11 @@ void pComboButton::constructor() { pWidget::synchronizeState(); unsigned selection = comboButton.state.selection; - locked = true; - for(auto& text : comboButton.state.text) append(text); - locked = false; - comboButton.setSelection(selection); + for(unsigned n = 0; n < comboButton.count(); n++) { + append(); + setText(n, comboButton.state.text[n]); + } + comboButton[selection].setSelected(); } void pComboButton::destructor() { @@ -61,7 +61,7 @@ void pComboButton::orphan() { void pComboButton::onChange() { comboButton.state.selection = qtComboButton->currentIndex(); - if(!locked && comboButton.onChange) comboButton.onChange(); + if(!locked() && comboButton.onChange) comboButton.onChange(); } } diff --git a/phoenix/qt/widget/console.cpp b/hiro/qt/widget/console.cpp similarity index 67% rename from phoenix/qt/widget/console.cpp rename to hiro/qt/widget/console.cpp index 22a3d813..5173a126 100644 --- a/phoenix/qt/widget/console.cpp +++ b/hiro/qt/widget/console.cpp @@ -7,9 +7,16 @@ void pConsole::reset() { } void pConsole::setBackgroundColor(Color color) { + QPalette palette = qtConsole->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + qtConsole->setPalette(palette); + qtConsole->setAutoFillBackground(true); } void pConsole::setForegroundColor(Color color) { + QPalette palette = qtConsole->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtConsole->setPalette(palette); } void pConsole::setPrompt(string prompt) { diff --git a/phoenix/qt/widget/frame.cpp b/hiro/qt/widget/frame.cpp similarity index 100% rename from phoenix/qt/widget/frame.cpp rename to hiro/qt/widget/frame.cpp diff --git a/phoenix/qt/widget/hex-edit.cpp b/hiro/qt/widget/hex-edit.cpp similarity index 95% rename from phoenix/qt/widget/hex-edit.cpp rename to hiro/qt/widget/hex-edit.cpp index f0883e36..4a465886 100644 --- a/phoenix/qt/widget/hex-edit.cpp +++ b/hiro/qt/widget/hex-edit.cpp @@ -1,6 +1,10 @@ namespace phoenix { void pHexEdit::setBackgroundColor(Color color) { + QPalette palette = qtHexEdit->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + qtHexEdit->setPalette(palette); + qtHexEdit->setAutoFillBackground(true); } void pHexEdit::setColumns(unsigned columns) { @@ -8,6 +12,9 @@ void pHexEdit::setColumns(unsigned columns) { } void pHexEdit::setForegroundColor(Color color) { + QPalette palette = qtHexEdit->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtHexEdit->setPalette(palette); } void pHexEdit::setLength(unsigned length) { @@ -18,9 +25,9 @@ void pHexEdit::setLength(unsigned length) { } void pHexEdit::setOffset(unsigned offset) { - locked = true; + lock(); qtScroll->setSliderPosition(hexEdit.state.offset / hexEdit.state.columns); - locked = false; + unlock(); update(); } @@ -254,7 +261,7 @@ void pHexEdit::scrollTo(signed position) { } void pHexEdit::onScroll() { - if(locked) return; + if(locked()) return; unsigned offset = qtScroll->sliderPosition(); hexEdit.state.offset = offset * hexEdit.state.columns; update(); diff --git a/phoenix/qt/widget/horizontal-scroller.cpp b/hiro/qt/widget/horizontal-scroller.cpp similarity index 100% rename from phoenix/qt/widget/horizontal-scroller.cpp rename to hiro/qt/widget/horizontal-scroller.cpp diff --git a/phoenix/qt/widget/horizontal-slider.cpp b/hiro/qt/widget/horizontal-slider.cpp similarity index 100% rename from phoenix/qt/widget/horizontal-slider.cpp rename to hiro/qt/widget/horizontal-slider.cpp diff --git a/hiro/qt/widget/icon-view.cpp b/hiro/qt/widget/icon-view.cpp new file mode 100644 index 00000000..d829cd0d --- /dev/null +++ b/hiro/qt/widget/icon-view.cpp @@ -0,0 +1,148 @@ +namespace phoenix { + +void pIconView::append() { + lock(); + auto item = new QListWidgetItem(qtIconView); + unlock(); +} + +void pIconView::remove(unsigned selection) { + lock(); + if(auto item = qtIconView->item(selection)) { + delete item; + } + unlock(); +} + +void pIconView::reset() { + lock(); + qtIconView->clear(); + unlock(); +} + +void pIconView::setBackgroundColor(Color color) { + QPalette palette = qtIconView->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + qtIconView->setPalette(palette); + qtIconView->setAutoFillBackground(true); +} + +void pIconView::setFlow(Orientation flow) { + qtIconView->setFlow(flow == Orientation::Horizontal ? QListView::LeftToRight : QListView::TopToBottom); + qtIconView->resize(qtIconView->size()); //adjust visibility of scroll bars +} + +void pIconView::setForegroundColor(Color color) { + QPalette palette = qtIconView->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtIconView->setPalette(palette); +} + +void pIconView::setImage(unsigned selection, const image& image) { + if(auto item = qtIconView->item(selection)) { + item->setIcon(CreateIcon(image)); + } +} + +void pIconView::setOrientation(Orientation orientation) { + qtIconView->setViewMode(orientation == Orientation::Horizontal ? QListView::ListMode : QListView::IconMode); + qtIconView->setWrapping(true); +} + +void pIconView::setSelected(unsigned selection, bool selected) { + lock(); + if(auto item = qtIconView->item(selection)) { + item->setSelected(selected); + } + unlock(); +} + +void pIconView::setSelected(const vector<unsigned>& selections) { + lock(); + qtIconView->clearSelection(); + for(auto& selection : selections) { + if(auto item = qtIconView->item(selection)) { + item->setSelected(true); + } + } + unlock(); +} + +void pIconView::setSelectedAll() { + lock(); + qtIconView->selectAll(); + unlock(); +} + +void pIconView::setSelectedNone() { + lock(); + qtIconView->clearSelection(); + unlock(); +} + +void pIconView::setSingleSelection(bool singleSelection) { + qtIconView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection); +} + +void pIconView::setText(unsigned selection, const string& text) { + if(auto item = qtIconView->item(selection)) { + item->setText(QString::fromUtf8(text)); + } +} + +void pIconView::constructor() { + qtWidget = qtIconView = new QtListWidget; + qtIconView->setContextMenuPolicy(Qt::CustomContextMenu); + qtIconView->setMovement(QListView::Static); + qtIconView->setResizeMode(QListView::Adjust); + qtIconView->setSelectionRectVisible(true); + qtIconView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + qtIconView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + + connect(qtIconView, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(onActivate())); + connect(qtIconView, SIGNAL(itemSelectionChanged()), SLOT(onChange())); + connect(qtIconView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext())); + + setFlow(iconView.state.flow); + setOrientation(iconView.state.orientation); + setSingleSelection(iconView.state.singleSelection); +} + +void pIconView::destructor() { + delete qtIconView; + qtWidget = qtIconView = nullptr; +} + +void pIconView::orphan() { + destructor(); + constructor(); +} + +void pIconView::onActivate() { + if(!locked() && iconView.onActivate) iconView.onActivate(); +} + +void pIconView::onChange() { + for(auto& selected : iconView.state.selected) selected = false; + for(unsigned n = 0; n < qtIconView->count(); n++) { + if(auto item = qtIconView->item(n)) { + if(item->isSelected()) iconView.state.selected[n] = true; + } + } + if(!locked() && iconView.onChange) iconView.onChange(); +} + +void pIconView::onContext() { + if(!locked() && iconView.onContext) iconView.onContext(); +} + +void pIconView::QtListWidget::resizeEvent(QResizeEvent* event) { + //Qt::ScrollBarAsNeeded results in the scroll bar area being reserved from the icon viewport even when scroll bar is hidden + //this creates the appearance of an invisible gap that wastes precious screen space + //below code simulates a Qt::ScrollBarAsNeeded which uses the extra space when the scroll bar is hidden + setHorizontalScrollBarPolicy(horizontalScrollBar()->maximum() > horizontalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(verticalScrollBar()->maximum() > verticalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff); + return QListWidget::resizeEvent(event); +} + +} diff --git a/phoenix/qt/widget/label.cpp b/hiro/qt/widget/label.cpp similarity index 100% rename from phoenix/qt/widget/label.cpp rename to hiro/qt/widget/label.cpp diff --git a/phoenix/qt/widget/line-edit.cpp b/hiro/qt/widget/line-edit.cpp similarity index 76% rename from phoenix/qt/widget/line-edit.cpp rename to hiro/qt/widget/line-edit.cpp index 3142c8ad..ab537608 100644 --- a/phoenix/qt/widget/line-edit.cpp +++ b/hiro/qt/widget/line-edit.cpp @@ -6,6 +6,10 @@ Size pLineEdit::minimumSize() { } void pLineEdit::setBackgroundColor(Color color) { + QPalette palette = qtLineEdit->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + qtLineEdit->setPalette(palette); + qtLineEdit->setAutoFillBackground(true); } void pLineEdit::setEditable(bool editable) { @@ -13,6 +17,9 @@ void pLineEdit::setEditable(bool editable) { } void pLineEdit::setForegroundColor(Color color) { + QPalette palette = qtLineEdit->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtLineEdit->setPalette(palette); } void pLineEdit::setText(string text) { diff --git a/hiro/qt/widget/list-view.cpp b/hiro/qt/widget/list-view.cpp new file mode 100644 index 00000000..113b6e0b --- /dev/null +++ b/hiro/qt/widget/list-view.cpp @@ -0,0 +1,395 @@ +namespace phoenix { + +void pListView::appendColumn() { + orphan(); +} + +void pListView::appendItem() { + lock(); + auto item = new QTreeWidgetItem(qtListView); + for(unsigned column = 0; column < listView.columns(); column++) { + auto& state = listView.state.columns[column]; + if(state.backgroundColor) { + item->setBackground(column, QColor( + state.backgroundColor->red, state.backgroundColor->green, state.backgroundColor->blue + )); + } + if(state.font) { + item->setFont(column, pFont::create(*state.font)); + } + if(state.foregroundColor) { + item->setForeground(column, QColor( + state.foregroundColor->red, state.foregroundColor->green, state.foregroundColor->blue + )); + } + item->setTextAlignment(column, calculateAlignment( + state.horizontalAlignment, state.verticalAlignment + )); + } + if(listView.state.checkable) item->setCheckState(0, Qt::Unchecked); + unlock(); +} + +void pListView::removeColumn(unsigned position) { + orphan(); +} + +void pListView::removeItem(unsigned position) { + lock(); + if(auto item = qtListView->topLevelItem(position)) { + delete item; + } + unlock(); +} + +void pListView::reset() { + lock(); + qtListView->clear(); + unlock(); +} + +void pListView::resizeColumns() { +} + +//todo: this doesn't work ... +void pListView::setActiveColumn(unsigned column) { + if(column >= listView.columns()) return; + qtListView->header()->setSortIndicator(column, Qt::DescendingOrder); +} + +void pListView::setBackgroundColor(Color color) { + QPalette palette = qtListView->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + palette.setColor(QPalette::AlternateBase, QColor(max(0, (signed)color.red - 17), max(0, (signed)color.green - 17), max(0, (signed)color.blue - 17))); + qtListView->setPalette(palette); + qtListView->setAutoFillBackground(true); +} + +void pListView::setCheckable(bool checkable) { + lock(); + if(checkable) { + for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) { + if(auto item = qtListView->topLevelItem(n)) { + item->setCheckState(0, Qt::Unchecked); + } + } + } + unlock(); +} + +void pListView::setChecked(unsigned position, bool checked) { + lock(); + if(auto item = qtListView->topLevelItem(position)) { + item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked); + } + unlock(); +} + +void pListView::setChecked(const vector<unsigned>& selections) { + lock(); + setCheckedNone(); + for(auto& position : selections) setChecked(position, true); + unlock(); +} + +void pListView::setCheckedAll() { + lock(); + for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) { + if(auto item = qtListView->topLevelItem(n)) { + item->setCheckState(0, Qt::Checked); + } + } + unlock(); +} + +void pListView::setCheckedNone() { + lock(); + for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) { + if(auto item = qtListView->topLevelItem(n)) { + item->setCheckState(0, Qt::Unchecked); + } + } + unlock(); +} + +void pListView::setColumnBackgroundColor(unsigned column, maybe<Color> color) { + for(unsigned row = 0; row < listView.items(); row++) { + if(auto item = qtListView->topLevelItem(row)) { + item->setBackground(column, color ? QColor(color->red, color->green, color->blue) : QBrush()); + } + } +} + +void pListView::setColumnEditable(unsigned column, bool editable) { +} + +void pListView::setColumnFont(unsigned column, maybe<string> font) { + auto qtFont = pFont::create(font ? *font : widget.state.font); + for(unsigned row = 0; row < listView.items(); row++) { + if(auto item = qtListView->topLevelItem(row)) { + item->setFont(column, qtFont); + } + } +} + +void pListView::setColumnForegroundColor(unsigned column, maybe<Color> color) { + for(unsigned row = 0; row < listView.items(); row++) { + if(auto item = qtListView->topLevelItem(row)) { + item->setForeground(column, color ? QColor(color->red, color->green, color->blue) : QBrush()); + } + } +} + +void pListView::setColumnHorizontalAlignment(unsigned column, double alignment) { + qtListView->headerItem()->setTextAlignment(column, calculateAlignment(alignment, 0.5)); + for(unsigned row = 0; row < listView.items(); row++) { + if(auto item = qtListView->topLevelItem(row)) { + auto& state = listView.state.columns[column]; + item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment)); + } + } +} + +void pListView::setColumnResizable(unsigned column, bool resizable) { + qtListView->header()->setResizeMode(column, resizable ? QHeaderView::Interactive : QHeaderView::Fixed); +} + +void pListView::setColumnSortable(unsigned column, bool sortable) { + bool clickable = false; + for(auto& column : listView.state.columns) clickable |= column.sortable; + qtListView->header()->setClickable(clickable); +} + +void pListView::setColumnText(unsigned column, const string& text) { + qtListView->headerItem()->setText(column, QString::fromUtf8(text)); +} + +void pListView::setColumnVerticalAlignment(unsigned column, double alignment) { + for(unsigned row = 0; row < listView.items(); row++) { + if(auto item = qtListView->topLevelItem(row)) { + auto& state = listView.state.columns[column]; + item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment)); + } + } +} + +void pListView::setColumnVisible(unsigned column, bool visible) { + if(column >= listView.columns()) return; + qtListView->setColumnHidden(column, !visible); +} + +void pListView::setColumnWidth(unsigned column, signed width) { + if(column >= listView.columns()) return; + resizeColumns(); +} + +void pListView::setForegroundColor(Color color) { + QPalette palette = qtListView->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtListView->setPalette(palette); +} + +void pListView::setGridVisible(bool visible) { + qtListView->repaint(); +} + +void pListView::setHeaderVisible(bool visible) { + qtListView->setHeaderHidden(!visible); + resizeColumns(); +} + +void pListView::setImage(unsigned row, unsigned column, const nall::image& image) { + if(auto item = qtListView->topLevelItem(row)) { + item->setIcon(column, CreateIcon(image)); + } +} + +void pListView::setSelected(unsigned position, bool selected) { + lock(); + if(auto item = qtListView->topLevelItem(position)) { + item->setSelected(selected); + } + unlock(); +} + +void pListView::setSelected(const vector<unsigned>& selections) { + lock(); + setSelectedNone(); + if(selections.size()) { + if(auto item = qtListView->topLevelItem(selections[0])) { + qtListView->setCurrentItem(item); + } + for(auto& position : selections) setSelected(position, true); + } + unlock(); +} + +void pListView::setSelectedAll() { + lock(); + qtListView->selectAll(); + unlock(); +} + +void pListView::setSelectedNone() { + lock(); + qtListView->clearSelection(); + unlock(); +} + +void pListView::setSingleSelection(bool singleSelection) { + lock(); + qtListView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection); + unlock(); +} + +void pListView::setText(unsigned row, unsigned column, string text) { + lock(); + if(auto item = qtListView->topLevelItem(row)) { + item->setText(column, QString::fromUtf8(text)); + } + unlock(); +} + +void pListView::constructor() { + qtWidget = qtListView = new QtTreeWidget(*this); + qtListView->setAllColumnsShowFocus(true); + qtListView->setAlternatingRowColors(listView.columns() >= 2); + qtListView->setColumnCount(max(1u, listView.columns())); + qtListView->setContextMenuPolicy(Qt::CustomContextMenu); + qtListView->setRootIsDecorated(false); + qtListView->header()->setMovable(false); + + qtListViewDelegate = new QtTreeWidgetDelegate(*this); + qtListView->setItemDelegate(qtListViewDelegate); + + connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate())); + connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange())); + connect(qtListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext())); + connect(qtListView->header(), SIGNAL(sectionClicked(int)), SLOT(onSort(int))); + connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onToggle(QTreeWidgetItem*))); + + pWidget::synchronizeState(); + for(unsigned column = 0; column < listView.columns(); column++) { + auto& state = listView.state.columns[column]; + setColumnBackgroundColor(column, state.backgroundColor); + setColumnEditable(column, state.editable); + setColumnFont(column, state.font); + setColumnForegroundColor(column, state.foregroundColor); + //setColumnHorizontalAlignment(column, state.horizontalAlignment); + setColumnResizable(column, state.resizable); + setColumnSortable(column, state.sortable); + setColumnText(column, state.text); + //setColumnVerticalAlignment(column, state.verticalAlignment); + setColumnVisible(column, state.visible); + //setColumnWidth(column, state.width); + qtListView->headerItem()->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, 0.5)); + } + setActiveColumn(listView.state.activeColumn); + setCheckable(listView.state.checkable); +//setGridVisible(listView.state.gridVisible); + setHeaderVisible(listView.state.headerVisible); + setSingleSelection(listView.state.singleSelection); + for(unsigned row = 0; row < listView.items(); row++) { + appendItem(); + setSelected(row, listView.state.items[row].selected); + if(listView.state.checkable) { + setChecked(row, listView.state.items[row].checked); + } + for(unsigned column = 0; column < listView.columns(); column++) { + setImage(row, column, listView.state.items[row].image(column, {})); + setText(row, column, listView.state.items[row].text(column, "")); + } + } + resizeColumns(); +} + +void pListView::destructor() { + delete qtListViewDelegate; + delete qtListView; + qtWidget = qtListView = nullptr; + qtListViewDelegate = nullptr; +} + +void pListView::orphan() { + destructor(); + constructor(); +} + +void pListView::onActivate() { + if(!locked() && listView.onActivate) listView.onActivate(); +} + +void pListView::onChange() { + for(auto& item : listView.state.items) item.selected = false; + for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) { + if(auto item = qtListView->topLevelItem(position)) { + if(item->isSelected()) listView.state.items[position].selected = true; + } + } + if(!locked() && listView.onChange) listView.onChange(); +} + +void pListView::onContext() { + if(!locked() && listView.onContext) listView.onContext(); +} + +void pListView::onSort(int column) { + if(column >= listView.columns()) return; + if(listView.state.columns[column].sortable) { + if(!locked() && listView.onSort) listView.onSort(column); + } +} + +void pListView::onToggle(QTreeWidgetItem* item) { + maybe<unsigned> row; + for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) { + if(auto topLevelItem = qtListView->topLevelItem(position)) { + if(topLevelItem == item) { + row = position; + break; + } + } + } + if(row) { + listView.state.items[*row].checked = (item->checkState(0) == Qt::Checked); + if(!locked() && listView.onToggle) listView.onToggle(*row); + } +} + +int pListView::calculateAlignment(double horizontal, double vertical) { + int alignment = 0; + if(horizontal < 0.333) alignment |= Qt::AlignLeft; + else if(horizontal > 0.666) alignment |= Qt::AlignRight; + else alignment |= Qt::AlignCenter; + if(vertical < 0.333) alignment |= Qt::AlignTop; + else if(vertical > 0.666) alignment |= Qt::AlignBottom; + else alignment |= Qt::AlignVCenter; + return alignment; +} + +void pListView::QtTreeWidget::mousePressEvent(QMouseEvent* event) { + QTreeWidget::mousePressEvent(event); + + if(event->button() == Qt::RightButton) { + self.onContext(); + } +} + +pListView::QtTreeWidget::QtTreeWidget(pListView& self) : self(self) { +} + +void pListView::QtTreeWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QStyledItemDelegate::paint(painter, option, index); + if(self.listView.state.gridVisible) { + QPen pen; + pen.setColor(QColor(192, 192, 192)); + pen.setWidth(1); + painter->setPen(pen); + painter->drawRect(option.rect); + } +} + +pListView::QtTreeWidgetDelegate::QtTreeWidgetDelegate(pListView& self) : QStyledItemDelegate(self.qtListView), self(self) { +} + +} diff --git a/phoenix/qt/widget/progress-bar.cpp b/hiro/qt/widget/progress-bar.cpp similarity index 100% rename from phoenix/qt/widget/progress-bar.cpp rename to hiro/qt/widget/progress-bar.cpp diff --git a/phoenix/qt/widget/radio-button.cpp b/hiro/qt/widget/radio-button.cpp similarity index 94% rename from phoenix/qt/widget/radio-button.cpp rename to hiro/qt/widget/radio-button.cpp index b3554b85..3ba491ab 100644 --- a/phoenix/qt/widget/radio-button.cpp +++ b/hiro/qt/widget/radio-button.cpp @@ -17,20 +17,20 @@ Size pRadioButton::minimumSize() { } void pRadioButton::setChecked() { - parent().locked = true; + parent().lock(); for(auto& item : radioButton.state.group) { bool checked = &item.p == this; item.p.qtRadioButton->setChecked(item.state.checked = checked); } - parent().locked = false; + parent().unlock(); } void pRadioButton::setGroup(const group<RadioButton>& group) { - parent().locked = true; + parent().lock(); for(auto& item : radioButton.state.group) { item.p.qtRadioButton->setChecked(item.state.checked); } - parent().locked = false; + parent().unlock(); } void pRadioButton::setImage(const image& image, Orientation orientation) { @@ -74,7 +74,7 @@ void pRadioButton::orphan() { } void pRadioButton::onActivate() { - if(parent().locked) return; + if(parent().locked()) return; bool wasChecked = radioButton.state.checked; setChecked(); if(!wasChecked) { diff --git a/phoenix/qt/widget/radio-label.cpp b/hiro/qt/widget/radio-label.cpp similarity index 91% rename from phoenix/qt/widget/radio-label.cpp rename to hiro/qt/widget/radio-label.cpp index 927591a4..cdbf013f 100644 --- a/phoenix/qt/widget/radio-label.cpp +++ b/hiro/qt/widget/radio-label.cpp @@ -6,20 +6,20 @@ Size pRadioLabel::minimumSize() { } void pRadioLabel::setChecked() { - parent().locked = true; + parent().lock(); for(auto& item : radioLabel.state.group) { bool checked = &item == &radioLabel; item.p.qtRadioLabel->setChecked(item.state.checked = checked); } - parent().locked = false; + parent().unlock(); } void pRadioLabel::setGroup(const group<RadioLabel>& group) { - parent().locked = true; + parent().lock(); for(auto& item : radioLabel.state.group) { item.p.qtRadioLabel->setChecked(item.state.checked); } - parent().locked = false; + parent().unlock(); } void pRadioLabel::setText(string text) { @@ -52,7 +52,7 @@ void pRadioLabel::orphan() { } void pRadioLabel::onActivate() { - if(parent().locked) return; + if(parent().locked()) return; bool wasChecked = radioLabel.state.checked; setChecked(); if(!wasChecked) { diff --git a/phoenix/qt/widget/tab-frame.cpp b/hiro/qt/widget/tab-frame.cpp similarity index 83% rename from phoenix/qt/widget/tab-frame.cpp rename to hiro/qt/widget/tab-frame.cpp index 6fb9396d..e2b393f0 100644 --- a/phoenix/qt/widget/tab-frame.cpp +++ b/hiro/qt/widget/tab-frame.cpp @@ -1,9 +1,7 @@ namespace phoenix { -void pTabFrame::append(string text, const image& image) { - unsigned selection = tabFrame.state.text.size() - 1; - qtTabFrame->addTab(new QWidget, QString::fromUtf8(text)); - if(!image.empty()) setImage(selection, image); +void pTabFrame::append() { + qtTabFrame->addTab(new QWidget, ""); } QWidget* pTabFrame::container(Widget& widget) { @@ -45,11 +43,11 @@ void pTabFrame::setImage(unsigned selection, const image& image) { qtTabFrame->setTabIcon(selection, CreateIcon(image)); } -void pTabFrame::setSelection(unsigned selection) { - locked = true; +void pTabFrame::setSelected(unsigned selection) { + lock(); qtTabFrame->setCurrentIndex(selection); synchronizeLayout(); - locked = false; + unlock(); } void pTabFrame::setText(unsigned selection, string text) { @@ -67,7 +65,7 @@ void pTabFrame::constructor() { qtWidget = qtTabFrame = new QTabWidget; connect(qtTabFrame, SIGNAL(currentChanged(int)), SLOT(onChange(int))); - setSelection(tabFrame.state.selection); + setSelected(tabFrame.state.selection); } void pTabFrame::destructor() { @@ -91,7 +89,7 @@ void pTabFrame::synchronizeLayout() { void pTabFrame::onChange(int selection) { tabFrame.state.selection = selection; synchronizeLayout(); - if(!locked && tabFrame.onChange) tabFrame.onChange(); + if(!locked() && tabFrame.onChange) tabFrame.onChange(); } } diff --git a/phoenix/qt/widget/text-edit.cpp b/hiro/qt/widget/text-edit.cpp similarity index 81% rename from phoenix/qt/widget/text-edit.cpp rename to hiro/qt/widget/text-edit.cpp index ec705731..8097e2cf 100644 --- a/phoenix/qt/widget/text-edit.cpp +++ b/hiro/qt/widget/text-edit.cpp @@ -1,6 +1,10 @@ namespace phoenix { void pTextEdit::setBackgroundColor(Color color) { + QPalette palette = qtTextEdit->palette(); + palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue)); + qtTextEdit->setPalette(palette); + qtTextEdit->setAutoFillBackground(true); } void pTextEdit::setCursorPosition(unsigned position) { @@ -15,6 +19,9 @@ void pTextEdit::setEditable(bool editable) { } void pTextEdit::setForegroundColor(Color color) { + QPalette palette = qtTextEdit->palette(); + palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue)); + qtTextEdit->setPalette(palette); } void pTextEdit::setText(string text) { diff --git a/phoenix/qt/widget/vertical-scroller.cpp b/hiro/qt/widget/vertical-scroller.cpp similarity index 100% rename from phoenix/qt/widget/vertical-scroller.cpp rename to hiro/qt/widget/vertical-scroller.cpp diff --git a/phoenix/qt/widget/vertical-slider.cpp b/hiro/qt/widget/vertical-slider.cpp similarity index 100% rename from phoenix/qt/widget/vertical-slider.cpp rename to hiro/qt/widget/vertical-slider.cpp diff --git a/phoenix/qt/widget/viewport.cpp b/hiro/qt/widget/viewport.cpp similarity index 100% rename from phoenix/qt/widget/viewport.cpp rename to hiro/qt/widget/viewport.cpp diff --git a/phoenix/qt/widget/widget.cpp b/hiro/qt/widget/widget.cpp similarity index 100% rename from phoenix/qt/widget/widget.cpp rename to hiro/qt/widget/widget.cpp diff --git a/phoenix/qt/window.cpp b/hiro/qt/window.cpp similarity index 89% rename from phoenix/qt/window.cpp rename to hiro/qt/window.cpp index 8753f2ef..6c6ae89c 100644 --- a/phoenix/qt/window.cpp +++ b/hiro/qt/window.cpp @@ -41,16 +41,6 @@ bool pWindow::focused() { return qtWindow->isActiveWindow() && !qtWindow->isMinimized(); } -Geometry pWindow::geometry() { - if(window.state.fullScreen) { - unsigned menuHeight = window.state.menuVisible ? qtMenu->height() : 0; - unsigned statusHeight = window.state.statusVisible ? qtStatus->height() : 0; - QRect geometry = qtWindow->geometry(); //frameGeometry() includes frame even though it's not visible in fullscreen mode - return {geometry.x(), geometry.y() + menuHeight, geometry.width(), geometry.height() - menuHeight - statusHeight}; - } - return window.state.geometry; -} - void pWindow::remove(Layout& layout) { } @@ -97,10 +87,9 @@ void pWindow::setFullScreen(bool fullScreen) { } void pWindow::setGeometry(Geometry geometry) { - locked = true; + lock(); Application::processEvents(); QApplication::syncX(); - Geometry margin = frameMargin(); setResizable(window.state.resizable); qtWindow->move(geometry.x - frameMargin().x, geometry.y - frameMargin().y); @@ -116,7 +105,7 @@ void pWindow::setGeometry(Geometry geometry) { geometry.x = geometry.y = 0; layout.setGeometry(geometry); } - locked = false; + unlock(); } void pWindow::setMenuFont(string font) { @@ -137,7 +126,11 @@ void pWindow::setModal(bool modal) { setVisible(true); while(window.state.modal) { Application::processEvents(); - usleep(20 * 1000); + if(Application::main) { + Application::main(); + } else { + usleep(20 * 1000); + } } qtWindow->setWindowModality(Qt::NonModal); } @@ -172,13 +165,13 @@ void pWindow::setTitle(string text) { } void pWindow::setVisible(bool visible) { - locked = true; + lock(); qtWindow->setVisible(visible); if(visible) { updateFrameGeometry(); setGeometry(window.state.geometry); } - locked = false; + unlock(); } void pWindow::setWidgetFont(string font) { @@ -194,6 +187,8 @@ void pWindow::constructor() { qtWindow->setWindowIcon(QIcon(string{"/usr/share/pixmaps/", applicationState.name, ".png"})); } else if(file::exists({"/usr/local/share/pixmaps/", applicationState.name, ".png"})) { qtWindow->setWindowIcon(QIcon(string{"/usr/local/share/pixmaps/", applicationState.name, ".png"})); + } else if(file::exists({userpath(), ".local/share/icons/", applicationState.name, ".png"})) { + qtWindow->setWindowIcon(QIcon(string{userpath(), ".local/share/icons/", applicationState.name, ".png"})); } } @@ -263,14 +258,12 @@ void pWindow::QtWindow::closeEvent(QCloseEvent* event) { } void pWindow::QtWindow::moveEvent(QMoveEvent* event) { - if(self.locked == false && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) { + if(!self.locked() && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) { self.window.state.geometry.x += event->pos().x() - event->oldPos().x(); self.window.state.geometry.y += event->pos().y() - event->oldPos().y(); } - if(self.locked == false) { - if(self.window.onMove) self.window.onMove(); - } + if(!self.locked() && self.window.onMove) self.window.onMove(); } void pWindow::QtWindow::dragEnterEvent(QDragEnterEvent* event) { @@ -296,20 +289,18 @@ void pWindow::QtWindow::keyReleaseEvent(QKeyEvent* event) { } void pWindow::QtWindow::resizeEvent(QResizeEvent*) { - if(self.locked == false && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) { + if(!self.locked() && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) { self.window.state.geometry.width = self.qtContainer->geometry().width(); self.window.state.geometry.height = self.qtContainer->geometry().height(); } for(auto& layout : self.window.state.layout) { - Geometry geometry = self.geometry(); + Geometry geometry = self.window.state.geometry; geometry.x = geometry.y = 0; layout.setGeometry(geometry); } - if(self.locked == false) { - if(self.window.onSize) self.window.onSize(); - } + if(!self.locked() && self.window.onSize) self.window.onSize(); } QSize pWindow::QtWindow::sizeHint() const { diff --git a/phoenix/reference/action/action.cpp b/hiro/reference/action/action.cpp similarity index 100% rename from phoenix/reference/action/action.cpp rename to hiro/reference/action/action.cpp diff --git a/phoenix/reference/action/action.hpp b/hiro/reference/action/action.hpp similarity index 100% rename from phoenix/reference/action/action.hpp rename to hiro/reference/action/action.hpp diff --git a/phoenix/reference/action/check-item.cpp b/hiro/reference/action/check-item.cpp similarity index 100% rename from phoenix/reference/action/check-item.cpp rename to hiro/reference/action/check-item.cpp diff --git a/phoenix/reference/action/check-item.hpp b/hiro/reference/action/check-item.hpp similarity index 100% rename from phoenix/reference/action/check-item.hpp rename to hiro/reference/action/check-item.hpp diff --git a/phoenix/reference/action/item.cpp b/hiro/reference/action/item.cpp similarity index 100% rename from phoenix/reference/action/item.cpp rename to hiro/reference/action/item.cpp diff --git a/phoenix/reference/action/item.hpp b/hiro/reference/action/item.hpp similarity index 100% rename from phoenix/reference/action/item.hpp rename to hiro/reference/action/item.hpp diff --git a/phoenix/reference/action/menu.cpp b/hiro/reference/action/menu.cpp similarity index 100% rename from phoenix/reference/action/menu.cpp rename to hiro/reference/action/menu.cpp diff --git a/phoenix/reference/action/menu.hpp b/hiro/reference/action/menu.hpp similarity index 100% rename from phoenix/reference/action/menu.hpp rename to hiro/reference/action/menu.hpp diff --git a/phoenix/reference/action/radio-item.cpp b/hiro/reference/action/radio-item.cpp similarity index 100% rename from phoenix/reference/action/radio-item.cpp rename to hiro/reference/action/radio-item.cpp diff --git a/phoenix/reference/action/radio-item.hpp b/hiro/reference/action/radio-item.hpp similarity index 100% rename from phoenix/reference/action/radio-item.hpp rename to hiro/reference/action/radio-item.hpp diff --git a/phoenix/reference/action/separator.cpp b/hiro/reference/action/separator.cpp similarity index 100% rename from phoenix/reference/action/separator.cpp rename to hiro/reference/action/separator.cpp diff --git a/phoenix/reference/action/separator.hpp b/hiro/reference/action/separator.hpp similarity index 100% rename from phoenix/reference/action/separator.hpp rename to hiro/reference/action/separator.hpp diff --git a/phoenix/reference/application.cpp b/hiro/reference/application.cpp similarity index 100% rename from phoenix/reference/application.cpp rename to hiro/reference/application.cpp diff --git a/phoenix/reference/application.hpp b/hiro/reference/application.hpp similarity index 100% rename from phoenix/reference/application.hpp rename to hiro/reference/application.hpp diff --git a/phoenix/reference/browser-window.cpp b/hiro/reference/browser-window.cpp similarity index 100% rename from phoenix/reference/browser-window.cpp rename to hiro/reference/browser-window.cpp diff --git a/phoenix/reference/browser-window.hpp b/hiro/reference/browser-window.hpp similarity index 100% rename from phoenix/reference/browser-window.hpp rename to hiro/reference/browser-window.hpp diff --git a/phoenix/reference/desktop.cpp b/hiro/reference/desktop.cpp similarity index 100% rename from phoenix/reference/desktop.cpp rename to hiro/reference/desktop.cpp diff --git a/phoenix/reference/desktop.hpp b/hiro/reference/desktop.hpp similarity index 100% rename from phoenix/reference/desktop.hpp rename to hiro/reference/desktop.hpp diff --git a/phoenix/reference/font.cpp b/hiro/reference/font.cpp similarity index 100% rename from phoenix/reference/font.cpp rename to hiro/reference/font.cpp diff --git a/phoenix/reference/font.hpp b/hiro/reference/font.hpp similarity index 100% rename from phoenix/reference/font.hpp rename to hiro/reference/font.hpp diff --git a/phoenix/reference/header.hpp b/hiro/reference/header.hpp similarity index 100% rename from phoenix/reference/header.hpp rename to hiro/reference/header.hpp diff --git a/phoenix/reference/keyboard.cpp b/hiro/reference/keyboard.cpp similarity index 100% rename from phoenix/reference/keyboard.cpp rename to hiro/reference/keyboard.cpp diff --git a/phoenix/reference/keyboard.hpp b/hiro/reference/keyboard.hpp similarity index 100% rename from phoenix/reference/keyboard.hpp rename to hiro/reference/keyboard.hpp diff --git a/phoenix/reference/message-window.cpp b/hiro/reference/message-window.cpp similarity index 100% rename from phoenix/reference/message-window.cpp rename to hiro/reference/message-window.cpp diff --git a/phoenix/reference/message-window.hpp b/hiro/reference/message-window.hpp similarity index 100% rename from phoenix/reference/message-window.hpp rename to hiro/reference/message-window.hpp diff --git a/phoenix/reference/monitor.cpp b/hiro/reference/monitor.cpp similarity index 100% rename from phoenix/reference/monitor.cpp rename to hiro/reference/monitor.cpp diff --git a/phoenix/reference/monitor.hpp b/hiro/reference/monitor.hpp similarity index 100% rename from phoenix/reference/monitor.hpp rename to hiro/reference/monitor.hpp diff --git a/phoenix/reference/mouse.cpp b/hiro/reference/mouse.cpp similarity index 100% rename from phoenix/reference/mouse.cpp rename to hiro/reference/mouse.cpp diff --git a/phoenix/reference/mouse.hpp b/hiro/reference/mouse.hpp similarity index 100% rename from phoenix/reference/mouse.hpp rename to hiro/reference/mouse.hpp diff --git a/phoenix/reference/object.cpp b/hiro/reference/object.cpp similarity index 100% rename from phoenix/reference/object.cpp rename to hiro/reference/object.cpp diff --git a/phoenix/reference/object.hpp b/hiro/reference/object.hpp similarity index 100% rename from phoenix/reference/object.hpp rename to hiro/reference/object.hpp diff --git a/phoenix/reference/platform.cpp b/hiro/reference/platform.cpp similarity index 97% rename from phoenix/reference/platform.cpp rename to hiro/reference/platform.cpp index 2a9ff663..883b0b2d 100644 --- a/phoenix/reference/platform.cpp +++ b/hiro/reference/platform.cpp @@ -10,6 +10,7 @@ #include "object.cpp" #include "timer.cpp" #include "window.cpp" +#include "popup-menu.cpp" #include "action/action.cpp" #include "action/menu.cpp" diff --git a/phoenix/reference/platform.hpp b/hiro/reference/platform.hpp similarity index 98% rename from phoenix/reference/platform.hpp rename to hiro/reference/platform.hpp index 059f7799..15cecec4 100644 --- a/phoenix/reference/platform.hpp +++ b/hiro/reference/platform.hpp @@ -16,6 +16,7 @@ namespace phoenix { #include "object.hpp" #include "timer.hpp" #include "window.hpp" +#include "popup-menu.hpp" #include "action/action.hpp" #include "action/menu.hpp" diff --git a/hiro/reference/popup-menu.cpp b/hiro/reference/popup-menu.cpp new file mode 100644 index 00000000..1dea8c2f --- /dev/null +++ b/hiro/reference/popup-menu.cpp @@ -0,0 +1,18 @@ +namespace phoenix { + +void pPopupMenu::append(Action& action) { +} + +void pPopupMenu::remove(Action& action) { +} + +void pPopupMenu::setVisible() { +} + +void pPopupMenu::constructor() { +} + +void pPopupMenu::destructor() { +} + +} diff --git a/hiro/reference/popup-menu.hpp b/hiro/reference/popup-menu.hpp new file mode 100644 index 00000000..c1eb0641 --- /dev/null +++ b/hiro/reference/popup-menu.hpp @@ -0,0 +1,15 @@ +namespace phoenix { + +struct pPopupMenu : public pObject { + PopupMenu& popupMenu; + + void append(Action& action); + void remove(Action& action); + void setVisible(); + + pPopupMenu(PopupMenu& popupMenu) : pObject(popupMenu), popupMenu(popupMenu) {} + void constructor(); + void destructor(); +}; + +} diff --git a/phoenix/reference/timer.cpp b/hiro/reference/timer.cpp similarity index 100% rename from phoenix/reference/timer.cpp rename to hiro/reference/timer.cpp diff --git a/phoenix/reference/timer.hpp b/hiro/reference/timer.hpp similarity index 100% rename from phoenix/reference/timer.hpp rename to hiro/reference/timer.hpp diff --git a/phoenix/reference/widget/button.cpp b/hiro/reference/widget/button.cpp similarity index 81% rename from phoenix/reference/widget/button.cpp rename to hiro/reference/widget/button.cpp index e2a3dfbc..ad7c3362 100644 --- a/phoenix/reference/widget/button.cpp +++ b/hiro/reference/widget/button.cpp @@ -1,5 +1,8 @@ namespace phoenix { +void pButton::setBordered(bool bordered) { +} + void pButton::setImage(const image& image, Orientation orientation) { } diff --git a/phoenix/reference/widget/button.hpp b/hiro/reference/widget/button.hpp similarity index 88% rename from phoenix/reference/widget/button.hpp rename to hiro/reference/widget/button.hpp index be591979..c4e697b1 100644 --- a/phoenix/reference/widget/button.hpp +++ b/hiro/reference/widget/button.hpp @@ -3,6 +3,7 @@ namespace phoenix { struct pButton : public pWidget { Button& button; + void setBordered(bool bordered); void setImage(const image& image, Orientation orientation); void setText(string text); diff --git a/phoenix/reference/widget/canvas.cpp b/hiro/reference/widget/canvas.cpp similarity index 100% rename from phoenix/reference/widget/canvas.cpp rename to hiro/reference/widget/canvas.cpp diff --git a/phoenix/reference/widget/canvas.hpp b/hiro/reference/widget/canvas.hpp similarity index 100% rename from phoenix/reference/widget/canvas.hpp rename to hiro/reference/widget/canvas.hpp diff --git a/phoenix/reference/widget/check-button.cpp b/hiro/reference/widget/check-button.cpp similarity index 100% rename from phoenix/reference/widget/check-button.cpp rename to hiro/reference/widget/check-button.cpp diff --git a/phoenix/reference/widget/check-button.hpp b/hiro/reference/widget/check-button.hpp similarity index 100% rename from phoenix/reference/widget/check-button.hpp rename to hiro/reference/widget/check-button.hpp diff --git a/phoenix/reference/widget/check-label.cpp b/hiro/reference/widget/check-label.cpp similarity index 100% rename from phoenix/reference/widget/check-label.cpp rename to hiro/reference/widget/check-label.cpp diff --git a/phoenix/reference/widget/check-label.hpp b/hiro/reference/widget/check-label.hpp similarity index 100% rename from phoenix/reference/widget/check-label.hpp rename to hiro/reference/widget/check-label.hpp diff --git a/phoenix/reference/widget/combo-button.cpp b/hiro/reference/widget/combo-button.cpp similarity index 72% rename from phoenix/reference/widget/combo-button.cpp rename to hiro/reference/widget/combo-button.cpp index 0eac259b..d9f5d3b1 100644 --- a/phoenix/reference/widget/combo-button.cpp +++ b/hiro/reference/widget/combo-button.cpp @@ -1,6 +1,6 @@ namespace phoenix { -void pComboButton::append(string text) { +void pComboButton::append() { } void pComboButton::remove(unsigned selection) { @@ -9,7 +9,7 @@ void pComboButton::remove(unsigned selection) { void pComboButton::reset() { } -void pComboButton::setSelection(unsigned selection) { +void pComboButton::setSelected(unsigned selection) { } void pComboButton::setText(unsigned selection, string text) { diff --git a/phoenix/reference/widget/combo-button.hpp b/hiro/reference/widget/combo-button.hpp similarity index 82% rename from phoenix/reference/widget/combo-button.hpp rename to hiro/reference/widget/combo-button.hpp index 9c183481..8b2b303f 100644 --- a/phoenix/reference/widget/combo-button.hpp +++ b/hiro/reference/widget/combo-button.hpp @@ -3,10 +3,10 @@ namespace phoenix { struct pComboButton : public pWidget { ComboButton& comboButton; - void append(string text); + void append(); void remove(unsigned selection); void reset(); - void setSelection(unsigned selection); + void setSelected(unsigned selection); void setText(unsigned selection, string text); pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {} diff --git a/phoenix/reference/widget/console.cpp b/hiro/reference/widget/console.cpp similarity index 100% rename from phoenix/reference/widget/console.cpp rename to hiro/reference/widget/console.cpp diff --git a/phoenix/reference/widget/console.hpp b/hiro/reference/widget/console.hpp similarity index 100% rename from phoenix/reference/widget/console.hpp rename to hiro/reference/widget/console.hpp diff --git a/phoenix/reference/widget/frame.cpp b/hiro/reference/widget/frame.cpp similarity index 100% rename from phoenix/reference/widget/frame.cpp rename to hiro/reference/widget/frame.cpp diff --git a/phoenix/reference/widget/frame.hpp b/hiro/reference/widget/frame.hpp similarity index 100% rename from phoenix/reference/widget/frame.hpp rename to hiro/reference/widget/frame.hpp diff --git a/phoenix/reference/widget/hex-edit.cpp b/hiro/reference/widget/hex-edit.cpp similarity index 100% rename from phoenix/reference/widget/hex-edit.cpp rename to hiro/reference/widget/hex-edit.cpp diff --git a/phoenix/reference/widget/hex-edit.hpp b/hiro/reference/widget/hex-edit.hpp similarity index 100% rename from phoenix/reference/widget/hex-edit.hpp rename to hiro/reference/widget/hex-edit.hpp diff --git a/phoenix/reference/widget/horizontal-scroller.cpp b/hiro/reference/widget/horizontal-scroller.cpp similarity index 100% rename from phoenix/reference/widget/horizontal-scroller.cpp rename to hiro/reference/widget/horizontal-scroller.cpp diff --git a/phoenix/reference/widget/horizontal-scroller.hpp b/hiro/reference/widget/horizontal-scroller.hpp similarity index 100% rename from phoenix/reference/widget/horizontal-scroller.hpp rename to hiro/reference/widget/horizontal-scroller.hpp diff --git a/phoenix/reference/widget/horizontal-slider.cpp b/hiro/reference/widget/horizontal-slider.cpp similarity index 100% rename from phoenix/reference/widget/horizontal-slider.cpp rename to hiro/reference/widget/horizontal-slider.cpp diff --git a/phoenix/reference/widget/horizontal-slider.hpp b/hiro/reference/widget/horizontal-slider.hpp similarity index 100% rename from phoenix/reference/widget/horizontal-slider.hpp rename to hiro/reference/widget/horizontal-slider.hpp diff --git a/phoenix/reference/widget/label.cpp b/hiro/reference/widget/label.cpp similarity index 100% rename from phoenix/reference/widget/label.cpp rename to hiro/reference/widget/label.cpp diff --git a/phoenix/reference/widget/label.hpp b/hiro/reference/widget/label.hpp similarity index 100% rename from phoenix/reference/widget/label.hpp rename to hiro/reference/widget/label.hpp diff --git a/phoenix/reference/widget/layout.hpp b/hiro/reference/widget/layout.hpp similarity index 100% rename from phoenix/reference/widget/layout.hpp rename to hiro/reference/widget/layout.hpp diff --git a/phoenix/reference/widget/line-edit.cpp b/hiro/reference/widget/line-edit.cpp similarity index 100% rename from phoenix/reference/widget/line-edit.cpp rename to hiro/reference/widget/line-edit.cpp diff --git a/phoenix/reference/widget/line-edit.hpp b/hiro/reference/widget/line-edit.hpp similarity index 100% rename from phoenix/reference/widget/line-edit.hpp rename to hiro/reference/widget/line-edit.hpp diff --git a/phoenix/reference/widget/list-view.cpp b/hiro/reference/widget/list-view.cpp similarity index 61% rename from phoenix/reference/widget/list-view.cpp rename to hiro/reference/widget/list-view.cpp index e882907c..d774389d 100644 --- a/phoenix/reference/widget/list-view.cpp +++ b/hiro/reference/widget/list-view.cpp @@ -1,6 +1,6 @@ namespace phoenix { -void pListView::append(const lstring& text) { +void pListView::append() { } void pListView::autoSizeColumns() { @@ -21,6 +21,15 @@ void pListView::setCheckable(bool checkable) { void pListView::setChecked(unsigned selection, bool checked) { } +void pListView::setChecked(const vector<unsigned>& selections) { +} + +void pListView::setCheckedAll() { +} + +void pListView::setCheckedNone() { +} + void pListView::setForegroundColor(Color color) { } @@ -33,10 +42,19 @@ void pListView::setHeaderVisible(bool visible) { void pListView::setImage(unsigned selection, unsigned position, const image& image) { } -void pListView::setSelected(bool selected) { +void pListView::setSelected(unsigned selection, bool selected) { } -void pListView::setSelection(unsigned selection) { +void pListView::setSelected(const vector<unsigned>& selections) { +} + +void pListView::setSelectedAll() { +} + +void pListView::setSelectedNone() { +} + +void pListView::setSingleSelection(bool singleSelection) { } void pListView::setText(unsigned selection, unsigned position, string text) { diff --git a/phoenix/reference/widget/list-view.hpp b/hiro/reference/widget/list-view.hpp similarity index 67% rename from phoenix/reference/widget/list-view.hpp rename to hiro/reference/widget/list-view.hpp index 8a97a955..3b2e1528 100644 --- a/phoenix/reference/widget/list-view.hpp +++ b/hiro/reference/widget/list-view.hpp @@ -3,19 +3,25 @@ namespace phoenix { struct pListView : public pWidget { ListView& listView; - void append(const lstring& text); + void append(); void autoSizeColumns(); void remove(unsigned selection); void reset(); void setBackgroundColor(Color color); void setCheckable(bool checkable); void setChecked(unsigned selection, bool checked); + void setChecked(const vector<unsigned>& selections); + void setCheckedAll(); + void setCheckedNone(); void setForegroundColor(Color color); void setHeaderText(const lstring& text); void setHeaderVisible(bool visible); void setImage(unsigned selection, unsigned position, const image& image); - void setSelected(bool selected); - void setSelection(unsigned selection); + void setSelected(unsigned selection, bool selected); + void setSelected(const vector<unsigned>& selections); + void setSelectedAll(); + void setSelectedNone(); + void setSingleSelection(bool singleSelection); void setText(unsigned selection, unsigned position, string text); pListView(ListView& listView) : pWidget(listView), listView(listView) {} diff --git a/phoenix/reference/widget/progress-bar.cpp b/hiro/reference/widget/progress-bar.cpp similarity index 100% rename from phoenix/reference/widget/progress-bar.cpp rename to hiro/reference/widget/progress-bar.cpp diff --git a/phoenix/reference/widget/progress-bar.hpp b/hiro/reference/widget/progress-bar.hpp similarity index 100% rename from phoenix/reference/widget/progress-bar.hpp rename to hiro/reference/widget/progress-bar.hpp diff --git a/phoenix/reference/widget/radio-button.cpp b/hiro/reference/widget/radio-button.cpp similarity index 100% rename from phoenix/reference/widget/radio-button.cpp rename to hiro/reference/widget/radio-button.cpp diff --git a/phoenix/reference/widget/radio-button.hpp b/hiro/reference/widget/radio-button.hpp similarity index 100% rename from phoenix/reference/widget/radio-button.hpp rename to hiro/reference/widget/radio-button.hpp diff --git a/phoenix/reference/widget/radio-label.cpp b/hiro/reference/widget/radio-label.cpp similarity index 100% rename from phoenix/reference/widget/radio-label.cpp rename to hiro/reference/widget/radio-label.cpp diff --git a/phoenix/reference/widget/radio-label.hpp b/hiro/reference/widget/radio-label.hpp similarity index 100% rename from phoenix/reference/widget/radio-label.hpp rename to hiro/reference/widget/radio-label.hpp diff --git a/phoenix/reference/widget/sizable.hpp b/hiro/reference/widget/sizable.hpp similarity index 100% rename from phoenix/reference/widget/sizable.hpp rename to hiro/reference/widget/sizable.hpp diff --git a/phoenix/reference/widget/tab-frame.cpp b/hiro/reference/widget/tab-frame.cpp similarity index 71% rename from phoenix/reference/widget/tab-frame.cpp rename to hiro/reference/widget/tab-frame.cpp index 074a018a..065a89b7 100644 --- a/phoenix/reference/widget/tab-frame.cpp +++ b/hiro/reference/widget/tab-frame.cpp @@ -1,6 +1,6 @@ namespace phoenix { -void pTabFrame::append(string text, const image& image) { +void pTabFrame::append() { } void pTabFrame::remove(unsigned selection) { @@ -9,7 +9,7 @@ void pTabFrame::remove(unsigned selection) { void pTabFrame::setImage(unsigned selection, const image& image) { } -void pTabFrame::setSelection(unsigned selection) { +void pTabFrame::setSelected(unsigned selection) { } void pTabFrame::setText(unsigned selection, string text) { diff --git a/phoenix/reference/widget/tab-frame.hpp b/hiro/reference/widget/tab-frame.hpp similarity index 79% rename from phoenix/reference/widget/tab-frame.hpp rename to hiro/reference/widget/tab-frame.hpp index 3efd9890..9984ef1d 100644 --- a/phoenix/reference/widget/tab-frame.hpp +++ b/hiro/reference/widget/tab-frame.hpp @@ -3,10 +3,10 @@ namespace phoenix { struct pTabFrame : public pWidget { TabFrame& tabFrame; - void append(string text, const image& image); + void append(); void remove(unsigned selection); void setImage(unsigned selection, const image& image); - void setSelection(unsigned selection); + void setSelected(unsigned selection); void setText(unsigned selection, string text); pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {} diff --git a/phoenix/reference/widget/text-edit.cpp b/hiro/reference/widget/text-edit.cpp similarity index 100% rename from phoenix/reference/widget/text-edit.cpp rename to hiro/reference/widget/text-edit.cpp diff --git a/phoenix/reference/widget/text-edit.hpp b/hiro/reference/widget/text-edit.hpp similarity index 100% rename from phoenix/reference/widget/text-edit.hpp rename to hiro/reference/widget/text-edit.hpp diff --git a/phoenix/reference/widget/vertical-scroller.cpp b/hiro/reference/widget/vertical-scroller.cpp similarity index 100% rename from phoenix/reference/widget/vertical-scroller.cpp rename to hiro/reference/widget/vertical-scroller.cpp diff --git a/phoenix/reference/widget/vertical-scroller.hpp b/hiro/reference/widget/vertical-scroller.hpp similarity index 100% rename from phoenix/reference/widget/vertical-scroller.hpp rename to hiro/reference/widget/vertical-scroller.hpp diff --git a/phoenix/reference/widget/vertical-slider.cpp b/hiro/reference/widget/vertical-slider.cpp similarity index 100% rename from phoenix/reference/widget/vertical-slider.cpp rename to hiro/reference/widget/vertical-slider.cpp diff --git a/phoenix/reference/widget/vertical-slider.hpp b/hiro/reference/widget/vertical-slider.hpp similarity index 100% rename from phoenix/reference/widget/vertical-slider.hpp rename to hiro/reference/widget/vertical-slider.hpp diff --git a/phoenix/reference/widget/viewport.cpp b/hiro/reference/widget/viewport.cpp similarity index 100% rename from phoenix/reference/widget/viewport.cpp rename to hiro/reference/widget/viewport.cpp diff --git a/phoenix/reference/widget/viewport.hpp b/hiro/reference/widget/viewport.hpp similarity index 100% rename from phoenix/reference/widget/viewport.hpp rename to hiro/reference/widget/viewport.hpp diff --git a/phoenix/reference/widget/widget.cpp b/hiro/reference/widget/widget.cpp similarity index 100% rename from phoenix/reference/widget/widget.cpp rename to hiro/reference/widget/widget.cpp diff --git a/phoenix/reference/widget/widget.hpp b/hiro/reference/widget/widget.hpp similarity index 100% rename from phoenix/reference/widget/widget.hpp rename to hiro/reference/widget/widget.hpp diff --git a/phoenix/reference/window.cpp b/hiro/reference/window.cpp similarity index 95% rename from phoenix/reference/window.cpp rename to hiro/reference/window.cpp index 416f2151..20b63eba 100644 --- a/phoenix/reference/window.cpp +++ b/hiro/reference/window.cpp @@ -23,10 +23,6 @@ Geometry pWindow::frameMargin() { return {0, 0, 0, 0}; } -Geometry pWindow::geometry() { - return {0, 0, 0, 0}; -} - void pWindow::remove(Layout& layout) { } diff --git a/phoenix/reference/window.hpp b/hiro/reference/window.hpp similarity index 97% rename from phoenix/reference/window.hpp rename to hiro/reference/window.hpp index 1039b9e6..b72efc84 100644 --- a/phoenix/reference/window.hpp +++ b/hiro/reference/window.hpp @@ -10,7 +10,6 @@ struct pWindow : public pObject { void append(Widget& widget); bool focused(); Geometry frameMargin(); - Geometry geometry(); void remove(Layout& layout); void remove(Menu& menu); void remove(Widget& widget); diff --git a/hiro/resource/GNUmakefile b/hiro/resource/GNUmakefile new file mode 100644 index 00000000..97e085c2 --- /dev/null +++ b/hiro/resource/GNUmakefile @@ -0,0 +1,13 @@ +all: + sourcery resource.bml resource.cpp resource.hpp + +permissions: + chmod +w icon/action/*.png + chmod +w icon/application/*.png + chmod +w icon/device/*.png + chmod +w icon/edit/*.png + chmod +w icon/emblem/*.png + chmod +w icon/go/*.png + chmod +w icon/media/*.png + chmod +w icon/place/*.png + chmod +w icon/prompt/*.png diff --git a/hiro/resource/icon/action/add.png b/hiro/resource/icon/action/add.png new file mode 100644 index 00000000..1aa7f095 Binary files /dev/null and b/hiro/resource/icon/action/add.png differ diff --git a/hiro/resource/icon/action/attach.png b/hiro/resource/icon/action/attach.png new file mode 100644 index 00000000..529bb7f5 Binary files /dev/null and b/hiro/resource/icon/action/attach.png differ diff --git a/hiro/resource/icon/action/bookmark.png b/hiro/resource/icon/action/bookmark.png new file mode 100644 index 00000000..6cf6443a Binary files /dev/null and b/hiro/resource/icon/action/bookmark.png differ diff --git a/hiro/resource/icon/action/full-screen.png b/hiro/resource/icon/action/full-screen.png new file mode 100644 index 00000000..ffdabd4e Binary files /dev/null and b/hiro/resource/icon/action/full-screen.png differ diff --git a/hiro/resource/icon/action/mute.png b/hiro/resource/icon/action/mute.png new file mode 100644 index 00000000..af5a97b5 Binary files /dev/null and b/hiro/resource/icon/action/mute.png differ diff --git a/hiro/resource/icon/action/new.png b/hiro/resource/icon/action/new.png new file mode 100644 index 00000000..4c3efdd6 Binary files /dev/null and b/hiro/resource/icon/action/new.png differ diff --git a/hiro/resource/icon/action/open.png b/hiro/resource/icon/action/open.png new file mode 100644 index 00000000..ab940462 Binary files /dev/null and b/hiro/resource/icon/action/open.png differ diff --git a/hiro/resource/icon/action/properties.png b/hiro/resource/icon/action/properties.png new file mode 100644 index 00000000..ab0e8ea3 Binary files /dev/null and b/hiro/resource/icon/action/properties.png differ diff --git a/hiro/resource/icon/action/quit.png b/hiro/resource/icon/action/quit.png new file mode 100644 index 00000000..0010931e Binary files /dev/null and b/hiro/resource/icon/action/quit.png differ diff --git a/hiro/resource/icon/action/refresh.png b/hiro/resource/icon/action/refresh.png new file mode 100644 index 00000000..3fd71d6e Binary files /dev/null and b/hiro/resource/icon/action/refresh.png differ diff --git a/hiro/resource/icon/action/remove.png b/hiro/resource/icon/action/remove.png new file mode 100644 index 00000000..00b654e8 Binary files /dev/null and b/hiro/resource/icon/action/remove.png differ diff --git a/hiro/resource/icon/action/save.png b/hiro/resource/icon/action/save.png new file mode 100644 index 00000000..22ff4957 Binary files /dev/null and b/hiro/resource/icon/action/save.png differ diff --git a/hiro/resource/icon/action/search.png b/hiro/resource/icon/action/search.png new file mode 100644 index 00000000..fd7f0b07 Binary files /dev/null and b/hiro/resource/icon/action/search.png differ diff --git a/target-higan/resource/advanced.png b/hiro/resource/icon/action/settings.png similarity index 100% rename from target-higan/resource/advanced.png rename to hiro/resource/icon/action/settings.png diff --git a/hiro/resource/icon/action/stop.png b/hiro/resource/icon/action/stop.png new file mode 100644 index 00000000..ab6808fb Binary files /dev/null and b/hiro/resource/icon/action/stop.png differ diff --git a/hiro/resource/icon/application/browser.png b/hiro/resource/icon/application/browser.png new file mode 100644 index 00000000..ac5957ad Binary files /dev/null and b/hiro/resource/icon/application/browser.png differ diff --git a/hiro/resource/icon/application/calculator.png b/hiro/resource/icon/application/calculator.png new file mode 100644 index 00000000..9248971a Binary files /dev/null and b/hiro/resource/icon/application/calculator.png differ diff --git a/hiro/resource/icon/application/calendar.png b/hiro/resource/icon/application/calendar.png new file mode 100644 index 00000000..106a592e Binary files /dev/null and b/hiro/resource/icon/application/calendar.png differ diff --git a/hiro/resource/icon/application/chat.png b/hiro/resource/icon/application/chat.png new file mode 100644 index 00000000..f6e83254 Binary files /dev/null and b/hiro/resource/icon/application/chat.png differ diff --git a/target-higan/resource/state-manager.png b/hiro/resource/icon/application/file-manager.png similarity index 100% rename from target-higan/resource/state-manager.png rename to hiro/resource/icon/application/file-manager.png diff --git a/hiro/resource/icon/application/mail.png b/hiro/resource/icon/application/mail.png new file mode 100644 index 00000000..859251fe Binary files /dev/null and b/hiro/resource/icon/application/mail.png differ diff --git a/hiro/resource/icon/application/monitor.png b/hiro/resource/icon/application/monitor.png new file mode 100644 index 00000000..8734e777 Binary files /dev/null and b/hiro/resource/icon/application/monitor.png differ diff --git a/hiro/resource/icon/application/terminal.png b/hiro/resource/icon/application/terminal.png new file mode 100644 index 00000000..c5b797a7 Binary files /dev/null and b/hiro/resource/icon/application/terminal.png differ diff --git a/hiro/resource/icon/application/text-editor.png b/hiro/resource/icon/application/text-editor.png new file mode 100644 index 00000000..188e1c12 Binary files /dev/null and b/hiro/resource/icon/application/text-editor.png differ diff --git a/target-higan/resource/timing.png b/hiro/resource/icon/device/clock.png similarity index 100% rename from target-higan/resource/timing.png rename to hiro/resource/icon/device/clock.png diff --git a/target-higan/resource/video.png b/hiro/resource/icon/device/display.png similarity index 100% rename from target-higan/resource/video.png rename to hiro/resource/icon/device/display.png diff --git a/target-higan/resource/input.png b/hiro/resource/icon/device/joypad.png similarity index 100% rename from target-higan/resource/input.png rename to hiro/resource/icon/device/joypad.png diff --git a/target-higan/resource/hotkeys.png b/hiro/resource/icon/device/keyboard.png similarity index 100% rename from target-higan/resource/hotkeys.png rename to hiro/resource/icon/device/keyboard.png diff --git a/hiro/resource/icon/device/microphone.png b/hiro/resource/icon/device/microphone.png new file mode 100644 index 00000000..53a03931 Binary files /dev/null and b/hiro/resource/icon/device/microphone.png differ diff --git a/hiro/resource/icon/device/mouse.png b/hiro/resource/icon/device/mouse.png new file mode 100644 index 00000000..eeda4db8 Binary files /dev/null and b/hiro/resource/icon/device/mouse.png differ diff --git a/target-higan/resource/server.png b/hiro/resource/icon/device/network.png similarity index 100% rename from target-higan/resource/server.png rename to hiro/resource/icon/device/network.png diff --git a/hiro/resource/icon/device/optical.png b/hiro/resource/icon/device/optical.png new file mode 100644 index 00000000..4ced6fe4 Binary files /dev/null and b/hiro/resource/icon/device/optical.png differ diff --git a/hiro/resource/icon/device/printer.png b/hiro/resource/icon/device/printer.png new file mode 100644 index 00000000..12a4e39d Binary files /dev/null and b/hiro/resource/icon/device/printer.png differ diff --git a/target-higan/resource/audio.png b/hiro/resource/icon/device/speaker.png similarity index 100% rename from target-higan/resource/audio.png rename to hiro/resource/icon/device/speaker.png diff --git a/hiro/resource/icon/device/storage.png b/hiro/resource/icon/device/storage.png new file mode 100644 index 00000000..5c3b8587 Binary files /dev/null and b/hiro/resource/icon/device/storage.png differ diff --git a/hiro/resource/icon/edit/clear.png b/hiro/resource/icon/edit/clear.png new file mode 100644 index 00000000..e6c8e8b9 Binary files /dev/null and b/hiro/resource/icon/edit/clear.png differ diff --git a/hiro/resource/icon/edit/copy.png b/hiro/resource/icon/edit/copy.png new file mode 100644 index 00000000..8dd48c49 Binary files /dev/null and b/hiro/resource/icon/edit/copy.png differ diff --git a/hiro/resource/icon/edit/cut.png b/hiro/resource/icon/edit/cut.png new file mode 100644 index 00000000..dc9eb9a7 Binary files /dev/null and b/hiro/resource/icon/edit/cut.png differ diff --git a/hiro/resource/icon/edit/delete.png b/hiro/resource/icon/edit/delete.png new file mode 100644 index 00000000..ea03150a Binary files /dev/null and b/hiro/resource/icon/edit/delete.png differ diff --git a/hiro/resource/icon/edit/find.png b/hiro/resource/icon/edit/find.png new file mode 100644 index 00000000..d072d3cb Binary files /dev/null and b/hiro/resource/icon/edit/find.png differ diff --git a/hiro/resource/icon/edit/paste.png b/hiro/resource/icon/edit/paste.png new file mode 100644 index 00000000..24588a3a Binary files /dev/null and b/hiro/resource/icon/edit/paste.png differ diff --git a/hiro/resource/icon/edit/redo.png b/hiro/resource/icon/edit/redo.png new file mode 100644 index 00000000..c3b0df03 Binary files /dev/null and b/hiro/resource/icon/edit/redo.png differ diff --git a/hiro/resource/icon/edit/replace.png b/hiro/resource/icon/edit/replace.png new file mode 100644 index 00000000..6edbef61 Binary files /dev/null and b/hiro/resource/icon/edit/replace.png differ diff --git a/hiro/resource/icon/edit/undo.png b/hiro/resource/icon/edit/undo.png new file mode 100644 index 00000000..8b0fef9a Binary files /dev/null and b/hiro/resource/icon/edit/undo.png differ diff --git a/hiro/resource/icon/emblem/archive.png b/hiro/resource/icon/emblem/archive.png new file mode 100644 index 00000000..90154261 Binary files /dev/null and b/hiro/resource/icon/emblem/archive.png differ diff --git a/hiro/resource/icon/emblem/audio.png b/hiro/resource/icon/emblem/audio.png new file mode 100644 index 00000000..2bd5af93 Binary files /dev/null and b/hiro/resource/icon/emblem/audio.png differ diff --git a/hiro/resource/icon/emblem/binary.png b/hiro/resource/icon/emblem/binary.png new file mode 100644 index 00000000..003ded24 Binary files /dev/null and b/hiro/resource/icon/emblem/binary.png differ diff --git a/hiro/resource/icon/emblem/file.png b/hiro/resource/icon/emblem/file.png new file mode 100644 index 00000000..3c285b01 Binary files /dev/null and b/hiro/resource/icon/emblem/file.png differ diff --git a/hiro/resource/icon/emblem/folder.png b/hiro/resource/icon/emblem/folder.png new file mode 100644 index 00000000..65bd0bbd Binary files /dev/null and b/hiro/resource/icon/emblem/folder.png differ diff --git a/hiro/resource/icon/emblem/font.png b/hiro/resource/icon/emblem/font.png new file mode 100644 index 00000000..bdbc1a80 Binary files /dev/null and b/hiro/resource/icon/emblem/font.png differ diff --git a/hiro/resource/icon/emblem/image.png b/hiro/resource/icon/emblem/image.png new file mode 100644 index 00000000..68da5027 Binary files /dev/null and b/hiro/resource/icon/emblem/image.png differ diff --git a/hiro/resource/icon/emblem/markup.png b/hiro/resource/icon/emblem/markup.png new file mode 100644 index 00000000..53014ab1 Binary files /dev/null and b/hiro/resource/icon/emblem/markup.png differ diff --git a/hiro/resource/icon/emblem/program.png b/hiro/resource/icon/emblem/program.png new file mode 100644 index 00000000..0d49f9df Binary files /dev/null and b/hiro/resource/icon/emblem/program.png differ diff --git a/hiro/resource/icon/emblem/script.png b/hiro/resource/icon/emblem/script.png new file mode 100644 index 00000000..c923098e Binary files /dev/null and b/hiro/resource/icon/emblem/script.png differ diff --git a/hiro/resource/icon/emblem/text.png b/hiro/resource/icon/emblem/text.png new file mode 100644 index 00000000..2d7f2d60 Binary files /dev/null and b/hiro/resource/icon/emblem/text.png differ diff --git a/hiro/resource/icon/emblem/video.png b/hiro/resource/icon/emblem/video.png new file mode 100644 index 00000000..3e4ced5b Binary files /dev/null and b/hiro/resource/icon/emblem/video.png differ diff --git a/hiro/resource/icon/go/down.png b/hiro/resource/icon/go/down.png new file mode 100644 index 00000000..3dd7fccd Binary files /dev/null and b/hiro/resource/icon/go/down.png differ diff --git a/target-higan/resource/home.png b/hiro/resource/icon/go/home.png similarity index 100% rename from target-higan/resource/home.png rename to hiro/resource/icon/go/home.png diff --git a/hiro/resource/icon/go/left.png b/hiro/resource/icon/go/left.png new file mode 100644 index 00000000..659cd90d Binary files /dev/null and b/hiro/resource/icon/go/left.png differ diff --git a/hiro/resource/icon/go/right.png b/hiro/resource/icon/go/right.png new file mode 100644 index 00000000..6ef8de76 Binary files /dev/null and b/hiro/resource/icon/go/right.png differ diff --git a/target-higan/resource/up.png b/hiro/resource/icon/go/up.png similarity index 100% rename from target-higan/resource/up.png rename to hiro/resource/icon/go/up.png diff --git a/hiro/resource/icon/media/back.png b/hiro/resource/icon/media/back.png new file mode 100644 index 00000000..94381f54 Binary files /dev/null and b/hiro/resource/icon/media/back.png differ diff --git a/hiro/resource/icon/media/eject.png b/hiro/resource/icon/media/eject.png new file mode 100644 index 00000000..2084067e Binary files /dev/null and b/hiro/resource/icon/media/eject.png differ diff --git a/hiro/resource/icon/media/flash.png b/hiro/resource/icon/media/flash.png new file mode 100644 index 00000000..bef542a1 Binary files /dev/null and b/hiro/resource/icon/media/flash.png differ diff --git a/hiro/resource/icon/media/floppy.png b/hiro/resource/icon/media/floppy.png new file mode 100644 index 00000000..f1d7a198 Binary files /dev/null and b/hiro/resource/icon/media/floppy.png differ diff --git a/hiro/resource/icon/media/next.png b/hiro/resource/icon/media/next.png new file mode 100644 index 00000000..758ec6f1 Binary files /dev/null and b/hiro/resource/icon/media/next.png differ diff --git a/hiro/resource/icon/media/optical.png b/hiro/resource/icon/media/optical.png new file mode 100644 index 00000000..760de938 Binary files /dev/null and b/hiro/resource/icon/media/optical.png differ diff --git a/hiro/resource/icon/media/pause.png b/hiro/resource/icon/media/pause.png new file mode 100644 index 00000000..c8b4fe22 Binary files /dev/null and b/hiro/resource/icon/media/pause.png differ diff --git a/hiro/resource/icon/media/play.png b/hiro/resource/icon/media/play.png new file mode 100644 index 00000000..a7de0feb Binary files /dev/null and b/hiro/resource/icon/media/play.png differ diff --git a/hiro/resource/icon/media/record.png b/hiro/resource/icon/media/record.png new file mode 100644 index 00000000..2f66cdeb Binary files /dev/null and b/hiro/resource/icon/media/record.png differ diff --git a/hiro/resource/icon/media/rewind.png b/hiro/resource/icon/media/rewind.png new file mode 100644 index 00000000..ffcac311 Binary files /dev/null and b/hiro/resource/icon/media/rewind.png differ diff --git a/hiro/resource/icon/media/skip.png b/hiro/resource/icon/media/skip.png new file mode 100644 index 00000000..4d7e2cd4 Binary files /dev/null and b/hiro/resource/icon/media/skip.png differ diff --git a/hiro/resource/icon/media/stop.png b/hiro/resource/icon/media/stop.png new file mode 100644 index 00000000..ede2815e Binary files /dev/null and b/hiro/resource/icon/media/stop.png differ diff --git a/hiro/resource/icon/place/bookmarks.png b/hiro/resource/icon/place/bookmarks.png new file mode 100644 index 00000000..f3b5d9d9 Binary files /dev/null and b/hiro/resource/icon/place/bookmarks.png differ diff --git a/hiro/resource/icon/place/desktop.png b/hiro/resource/icon/place/desktop.png new file mode 100644 index 00000000..4c9787cc Binary files /dev/null and b/hiro/resource/icon/place/desktop.png differ diff --git a/hiro/resource/icon/place/home.png b/hiro/resource/icon/place/home.png new file mode 100644 index 00000000..7b9110df Binary files /dev/null and b/hiro/resource/icon/place/home.png differ diff --git a/hiro/resource/icon/place/server.png b/hiro/resource/icon/place/server.png new file mode 100644 index 00000000..068ffebe Binary files /dev/null and b/hiro/resource/icon/place/server.png differ diff --git a/hiro/resource/icon/place/share.png b/hiro/resource/icon/place/share.png new file mode 100644 index 00000000..5234eab4 Binary files /dev/null and b/hiro/resource/icon/place/share.png differ diff --git a/hiro/resource/icon/prompt/error.png b/hiro/resource/icon/prompt/error.png new file mode 100644 index 00000000..3bbbb4a0 Binary files /dev/null and b/hiro/resource/icon/prompt/error.png differ diff --git a/hiro/resource/icon/prompt/information.png b/hiro/resource/icon/prompt/information.png new file mode 100644 index 00000000..8851b99b Binary files /dev/null and b/hiro/resource/icon/prompt/information.png differ diff --git a/hiro/resource/icon/prompt/question.png b/hiro/resource/icon/prompt/question.png new file mode 100644 index 00000000..f25fc3fb Binary files /dev/null and b/hiro/resource/icon/prompt/question.png differ diff --git a/hiro/resource/icon/prompt/warning.png b/hiro/resource/icon/prompt/warning.png new file mode 100644 index 00000000..a9e4ff39 Binary files /dev/null and b/hiro/resource/icon/prompt/warning.png differ diff --git a/hiro/resource/resource.bml b/hiro/resource/resource.bml new file mode 100644 index 00000000..3c3effbd --- /dev/null +++ b/hiro/resource/resource.bml @@ -0,0 +1,92 @@ +namespace name=Icon + namespace name=Action + binary name=Add file=icon/action/add.png + binary name=Attach file=icon/action/attach.png + binary name=Bookmark file=icon/action/bookmark.png + binary name=FullScreen file=icon/action/full-screen.png + binary name=Mute file=icon/action/mute.png + binary name=New file=icon/action/new.png + binary name=Open file=icon/action/open.png + binary name=Properties file=icon/action/properties.png + binary name=Quit file=icon/action/quit.png + binary name=Refresh file=icon/action/refresh.png + binary name=Remove file=icon/action/remove.png + binary name=Save file=icon/action/save.png + binary name=Search file=icon/action/search.png + binary name=Settings file=icon/action/settings.png + binary name=Stop file=icon/action/stop.png + namespace name=Application + binary name=Browser file=icon/application/browser.png + binary name=Calculator file=icon/application/calculator.png + binary name=Calendar file=icon/application/calendar.png + binary name=Chat file=icon/application/chat.png + binary name=FileManager file=icon/application/file-manager.png + binary name=Mail file=icon/application/mail.png + binary name=Monitor file=icon/application/monitor.png + binary name=Terminal file=icon/application/terminal.png + binary name=TextEditor file=icon/application/text-editor.png + namespace name=Device + binary name=Clock file=icon/device/clock.png + binary name=Display file=icon/device/display.png + binary name=Joypad file=icon/device/joypad.png + binary name=Keyboard file=icon/device/keyboard.png + binary name=Microphone file=icon/device/microphone.png + binary name=Mouse file=icon/device/mouse.png + binary name=Network file=icon/device/network.png + binary name=Optical file=icon/device/optical.png + binary name=Printer file=icon/device/printer.png + binary name=Speaker file=icon/device/speaker.png + binary name=Storage file=icon/device/storage.png + namespace name=Edit + binary name=Clear file=icon/edit/clear.png + binary name=Copy file=icon/edit/copy.png + binary name=Cut file=icon/edit/cut.png + binary name=Delete file=icon/edit/delete.png + binary name=Find file=icon/edit/find.png + binary name=Paste file=icon/edit/paste.png + binary name=Redo file=icon/edit/redo.png + binary name=Replace file=icon/edit/replace.png + binary name=Undo file=icon/edit/undo.png + namespace name=Emblem + binary name=Archive file=icon/emblem/archive.png + binary name=Audio file=icon/emblem/audio.png + binary name=Binary file=icon/emblem/binary.png + binary name=File file=icon/emblem/file.png + binary name=Folder file=icon/emblem/folder.png + binary name=Font file=icon/emblem/font.png + binary name=Image file=icon/emblem/image.png + binary name=Markup file=icon/emblem/markup.png + binary name=Program file=icon/emblem/program.png + binary name=Script file=icon/emblem/script.png + binary name=Text file=icon/emblem/text.png + binary name=Video file=icon/emblem/video.png + namespace name=Go + binary name=Down file=icon/go/down.png + binary name=Home file=icon/go/home.png + binary name=Left file=icon/go/left.png + binary name=Right file=icon/go/right.png + binary name=Up file=icon/go/up.png + namespace name=Media + binary name=Back file=icon/media/back.png + binary name=Eject file=icon/media/eject.png + binary name=Flash file=icon/media/flash.png + binary name=Floppy file=icon/media/floppy.png + binary name=Next file=icon/media/next.png + binary name=Optical file=icon/media/optical.png + binary name=Pause file=icon/media/pause.png + binary name=Play file=icon/media/play.png + binary name=Record file=icon/media/record.png + binary name=Rewind file=icon/media/rewind.png + binary name=Skip file=icon/media/skip.png + binary name=Stop file=icon/media/stop.png + namespace name=Place + binary name=Bookmarks file=icon/place/bookmarks.png + binary name=Desktop file=icon/place/desktop.png + binary name=Home file=icon/place/home.png + binary name=Server file=icon/place/server.png + binary name=Share file=icon/place/share.png + namespace name=Prompt + binary name=Error file=icon/prompt/error.png + binary name=Information file=icon/prompt/information.png + binary name=Question file=icon/prompt/question.png + binary name=Warning file=icon/prompt/warning.png diff --git a/hiro/resource/resource.cpp b/hiro/resource/resource.cpp new file mode 100644 index 00000000..19096fbd --- /dev/null +++ b/hiro/resource/resource.cpp @@ -0,0 +1,1891 @@ +namespace Icon { +namespace Action { +const nall::vector<uint8_t> Add = { //size: 323 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,214,1,11,16,0,17,148,68,120,161,0,0,0,208,73, + 68,65,84,56,203,205,145,189,14,193,96,20,134,31,210,197,96,183,114,7,210,186,129,198,96,54,91,59,116,113,7,68, + 210,196,100,23,177,90,13,38,131,132,27,232,103,55,90,44,86,105,226,167,223,49,16,138,250,139,4,239,118,242,157,188, + 249,158,231,192,175,147,184,247,96,57,61,31,48,143,163,242,187,21,43,110,47,249,160,220,244,92,27,207,181,137,20,189, + 85,240,82,62,46,48,238,48,199,57,145,200,120,114,98,68,153,91,213,34,91,45,36,128,109,120,222,247,92,27,17,16, + 57,88,175,119,198,230,205,15,0,86,235,144,249,50,64,4,180,22,180,64,176,17,194,80,216,105,65,107,200,101,82,241, + 8,128,106,116,38,23,8,229,82,1,128,193,200,191,38,82,79,229,88,78,79,134,211,133,52,251,51,185,226,255,242,25, + 243,217,244,107,103,140,137,170,181,79,182,21,127,155,61,84,114,75,11,139,178,119,142,0,0,0,0,73,69,78,68,174, + 66,96,130, +}; +const nall::vector<uint8_t> Attach = { //size: 649 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,27,73,68,65,84,56,141, + 133,211,223,107,146,81,24,192,241,175,250,170,140,114,25,221,76,47,212,205,233,88,233,162,112,51,2,7,131,193,198,168, + 219,32,168,151,94,120,137,186,136,8,130,160,191,160,174,130,26,196,64,144,12,162,187,230,72,27,68,174,117,185,173,232, + 231,42,236,23,25,182,145,166,108,110,234,252,213,133,89,175,154,235,92,29,158,243,240,57,207,121,120,142,170,90,173,210, + 188,36,89,84,3,19,192,49,96,4,72,1,247,128,169,128,63,184,162,204,85,53,3,146,44,118,0,51,93,166,174,209, + 189,253,253,216,29,118,54,55,54,137,197,98,44,45,62,253,94,169,84,60,1,127,48,81,207,87,183,92,15,151,157,125, + 206,209,241,177,49,86,86,87,185,21,184,77,36,242,0,147,201,132,203,237,50,1,23,149,201,127,0,73,22,207,72,178, + 248,25,56,231,243,249,152,158,14,177,252,102,121,106,107,171,48,148,254,153,62,31,141,62,198,235,245,2,156,250,39,0, + 92,241,249,134,109,192,174,78,67,39,153,76,6,224,82,192,31,92,4,110,172,175,173,97,216,177,19,96,119,59,160,99, + 208,51,8,128,86,208,214,99,21,73,22,143,2,215,0,4,65,7,208,208,52,65,177,87,105,117,186,102,192,12,132,204, + 102,179,42,145,72,160,17,132,22,64,89,129,74,39,252,6,180,186,122,108,15,160,58,45,159,5,64,87,131,219,3,245, + 155,133,191,21,84,149,21,105,212,255,1,234,39,149,114,21,181,90,13,208,3,80,42,149,0,40,150,138,219,3,249,92, + 30,128,87,175,95,50,224,222,15,48,105,179,118,243,241,211,7,0,242,185,92,11,208,208,196,66,161,6,204,205,71,57, + 113,252,36,86,139,205,104,177,88,9,71,102,0,40,20,10,219,2,235,217,108,214,160,215,235,73,38,127,100,38,111,94, + 55,246,218,29,60,138,62,36,187,145,197,209,235,36,254,45,14,16,107,247,132,217,133,165,5,38,198,143,208,211,109,55, + 106,52,26,222,189,127,75,185,82,198,181,207,205,161,161,195,204,63,153,3,184,218,174,130,11,207,95,60,27,72,165,146, + 125,86,139,149,131,7,60,8,130,64,169,88,226,107,252,11,247,35,33,210,153,116,24,184,163,4,26,126,163,36,139,6, + 106,179,62,2,12,83,155,131,52,48,11,220,5,194,1,127,176,172,4,126,1,41,32,186,81,242,76,218,213,0,0,0, + 0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Bookmark = { //size: 686 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,17,21,6,52,65,49,61,207,0,0,2,59,73, + 68,65,84,56,203,149,210,65,72,147,97,28,199,241,239,255,125,158,247,221,187,185,114,91,35,107,172,21,45,17,44,47, + 129,66,69,247,194,168,32,130,14,65,135,162,123,208,161,162,118,176,67,167,162,171,116,173,131,224,37,40,138,40,43,208, + 166,65,33,120,113,83,9,209,201,212,68,90,178,215,109,239,246,118,152,168,43,19,252,93,158,231,240,252,63,252,255,207, + 243,8,107,233,58,115,231,22,240,24,240,216,136,7,32,34,243,247,174,231,146,221,167,127,181,129,238,130,218,34,212,210, + 192,162,6,232,237,237,237,207,231,243,151,38,38,167,200,46,198,228,193,221,171,245,114,169,19,15,31,61,143,13,166,93, + 167,53,17,231,192,161,19,24,214,65,86,150,62,12,238,9,142,221,80,0,157,157,157,125,169,84,138,93,193,32,3,233, + 31,132,91,162,124,207,228,152,156,249,137,83,170,48,49,62,205,237,155,199,232,56,122,4,171,249,2,166,125,8,67,251, + 19,218,253,58,167,55,181,75,161,80,192,173,20,89,90,94,102,126,97,25,0,91,215,112,43,69,10,191,93,220,154,139, + 174,58,136,50,40,23,103,240,41,41,24,155,129,106,181,74,181,178,74,185,228,80,114,86,40,59,43,84,86,29,220,178, + 195,216,120,137,153,156,80,45,14,224,21,223,49,59,157,6,175,242,173,1,0,16,101,161,181,133,105,249,80,166,15,165, + 77,196,48,217,31,75,16,217,119,22,167,214,129,152,49,70,70,77,160,58,218,0,136,8,218,244,99,218,1,44,59,136, + 207,223,132,105,251,209,166,159,220,108,142,76,118,10,79,98,96,29,103,110,161,9,221,242,114,85,255,221,129,97,40,12, + 67,161,180,9,128,82,38,134,210,196,227,113,218,218,218,64,4,17,141,231,9,0,13,128,101,89,235,251,189,145,32,181, + 218,198,151,176,253,138,173,210,48,66,32,16,168,255,30,15,190,188,31,102,120,96,4,207,171,35,77,129,102,68,100,123, + 192,231,243,1,240,233,237,16,137,216,110,14,39,66,124,124,51,132,231,121,228,243,121,50,153,204,63,64,195,8,182,109, + 3,112,237,242,41,174,92,60,137,97,24,244,191,26,230,217,139,207,180,183,183,147,76,38,183,7,162,209,40,79,238,159, + 67,41,69,54,155,69,68,232,104,13,243,52,117,158,112,56,188,254,82,255,5,66,161,16,161,80,8,17,89,63,184,121, + 221,234,14,26,128,72,36,194,78,163,215,90,127,221,211,211,211,189,147,194,104,52,218,7,240,7,70,86,184,198,50,151, + 228,191,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> FullScreen = { //size: 650 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,214,3,16,19,13,53,226,119,223,154,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,1,214, + 73,68,65,84,56,203,157,147,59,104,147,81,20,199,127,255,155,27,53,21,105,211,37,72,241,5,113,8,8,130,32,148, + 42,118,42,20,95,80,197,201,199,224,208,193,42,213,197,65,112,112,72,249,154,224,168,96,6,193,65,80,2,237,224,179, + 86,81,116,80,113,13,45,138,37,45,22,69,106,77,83,21,77,76,251,117,248,146,216,188,28,114,224,192,133,115,207,239, + 254,207,185,231,200,137,69,111,0,253,52,103,9,156,88,212,109,214,156,88,212,181,37,212,238,254,219,21,232,39,195,189, + 0,72,6,112,233,185,248,168,34,254,46,113,28,0,83,173,201,24,253,75,6,36,144,196,211,248,126,140,81,77,13,166, + 58,121,67,192,207,133,235,111,188,151,101,80,209,79,57,47,104,89,107,177,62,213,7,72,48,230,244,178,177,61,64,184, + 163,149,123,175,103,144,60,25,119,158,127,100,199,214,118,66,193,0,227,241,131,248,86,41,41,247,96,60,118,0,128,107, + 131,123,25,125,53,77,40,24,224,253,167,69,172,53,132,59,218,88,99,125,92,58,177,11,23,241,236,234,161,90,128,228, + 85,45,160,111,223,54,38,166,51,68,182,180,97,100,248,48,187,64,103,36,92,190,231,174,170,188,12,176,182,116,244,32, + 126,191,197,250,252,200,136,245,45,235,240,89,11,18,194,5,87,245,122,96,144,132,145,33,241,96,130,185,133,63,76,125, + 206,50,59,247,147,236,175,60,35,47,167,138,191,98,74,114,43,1,221,231,71,145,12,199,174,60,102,114,38,67,42,253, + 157,237,155,130,108,14,181,146,74,207,243,118,242,43,71,46,63,4,96,207,217,100,45,192,117,161,123,112,132,204,143,28, + 233,47,139,156,59,186,19,73,72,226,100,79,132,84,122,158,111,217,223,116,13,36,27,207,193,178,11,185,191,75,220,119, + 14,123,157,40,2,36,49,22,239,99,105,217,253,255,32,149,172,107,32,137,49,194,200,115,100,232,60,115,183,238,54,217, + 234,217,110,100,141,226,182,80,40,220,28,142,15,157,110,102,151,243,185,252,173,21,142,211,185,159,81,219,35,189,0,0, + 0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Mute = { //size: 632 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,10,73,68,65,84,56,141, + 165,147,207,75,84,81,24,134,159,115,61,215,51,214,140,46,100,26,17,141,22,226,70,178,50,23,21,65,11,33,152,85, + 139,113,156,153,173,155,41,92,70,250,31,68,45,204,173,182,82,180,140,68,72,9,4,17,90,185,147,72,200,12,209,96, + 108,51,11,113,225,189,206,56,115,127,124,45,6,103,97,72,86,31,156,213,199,251,188,223,11,239,81,34,194,255,140,117, + 222,98,48,55,216,159,207,231,237,127,2,100,179,169,190,6,212,90,181,90,109,248,107,64,54,155,234,179,27,35,159,68, + 164,249,79,98,0,157,201,165,29,32,162,181,62,70,100,210,110,140,60,25,30,30,110,158,122,61,21,92,4,96,41,84, + 100,98,124,66,143,141,142,181,8,140,142,140,140,52,223,189,115,15,173,245,69,244,104,65,136,199,175,16,143,39,16,17, + 117,235,230,109,140,49,40,165,46,6,0,216,250,246,181,238,184,179,243,29,219,182,241,60,143,135,11,239,243,243,211,211, + 207,4,34,103,133,10,78,4,158,107,0,199,113,234,0,207,247,16,106,221,176,124,255,101,39,24,109,12,150,49,4,71, + 71,232,214,86,252,195,67,2,17,10,240,202,2,112,92,7,199,117,16,17,188,170,135,87,245,78,141,204,37,99,232,89, + 93,229,250,250,58,177,238,110,110,108,110,210,61,51,67,83,45,162,209,0,174,235,82,46,151,1,40,252,220,167,179,163, + 163,126,170,233,234,226,114,127,63,202,24,122,182,183,1,104,73,38,209,137,4,20,139,88,34,34,139,139,139,193,202,202, + 202,137,165,172,169,165,165,15,238,126,97,191,14,56,217,218,226,71,38,83,203,109,213,106,179,51,48,128,95,44,214,98, + 2,49,17,137,134,97,24,125,251,230,221,99,175,18,36,151,63,46,187,97,24,90,0,118,123,59,87,39,39,65,41,36, + 8,64,132,107,179,179,88,177,88,205,65,68,126,123,233,116,250,126,58,147,58,158,3,249,210,214,38,149,66,65,188,131, + 3,217,203,229,36,40,149,196,221,216,144,207,209,168,204,129,168,243,126,227,208,208,208,131,71,11,11,107,93,160,35,137, + 4,13,209,40,149,189,61,154,122,123,169,236,238,82,45,149,216,5,255,92,0,192,188,82,47,66,120,122,218,151,51,227, + 91,48,254,11,41,211,229,38,66,238,34,57,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> New = { //size: 477 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,252,0,233,0,79,52,215,177,13,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,2,18,14,38,28,211,182,25,41,0,0,1,106,73, + 68,65,84,56,203,173,144,79,75,91,81,16,197,127,115,239,141,86,36,125,37,130,208,202,91,22,220,212,238,92,102,169, + 27,243,13,178,113,89,191,69,222,178,221,119,35,4,196,130,223,192,77,55,221,42,133,82,74,178,82,74,73,90,132,16, + 255,69,98,155,222,119,199,133,38,198,24,147,84,122,54,51,12,115,230,156,51,82,46,151,183,107,181,90,145,17,152,157, + 253,203,220,92,155,103,209,111,242,203,159,223,229,162,111,31,225,207,190,100,195,25,165,82,73,199,225,252,120,83,47,79, + 223,104,231,188,160,151,39,43,157,139,198,226,174,182,178,235,218,50,51,174,171,210,108,54,9,33,0,32,34,61,245,140, + 217,99,218,126,33,227,190,34,102,9,235,76,38,216,246,106,199,183,91,83,206,87,123,7,6,201,221,106,228,8,107,234, + 136,121,133,184,2,96,49,42,70,211,95,139,224,94,186,254,172,131,228,235,94,111,58,11,76,129,56,16,11,130,0,23, + 110,52,89,8,58,79,208,231,216,80,69,211,105,64,208,180,162,222,155,122,198,166,21,247,208,231,187,135,2,175,241,225, + 39,224,177,90,1,20,239,95,232,233,89,235,211,204,252,247,131,145,17,68,4,229,41,29,93,67,117,129,52,253,1,60, + 97,107,231,208,108,108,108,191,5,112,163,200,183,53,139,215,60,34,66,20,69,52,26,73,79,212,48,33,250,127,211,143, + 123,17,134,57,120,136,124,199,193,176,165,193,217,176,29,51,169,221,177,17,114,185,28,143,129,139,227,248,67,146,36,197, + 127,33,197,113,252,158,255,133,43,204,61,153,96,123,172,20,201,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Open = { //size: 672 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,29,73,68,65,84,56,141,141,147,191,75,151,81,20,198,63,231,125, + 175,111,73,160,107,4,225,210,82,208,24,168,75,63,164,37,13,114,106,208,165,197,193,160,230,134,254,130,134,16,55,135, + 138,6,251,15,4,35,133,8,77,43,104,104,138,16,33,181,69,66,45,205,239,247,222,115,207,105,248,234,155,150,96,207, + 112,238,185,151,123,159,231,57,231,222,43,67,67,67,28,68,202,205,134,136,148,238,46,34,2,64,81,20,34,34,180,181, + 181,125,254,181,221,184,92,85,213,250,254,254,208,213,213,245,212,221,111,238,47,44,45,127,57,241,236,201,115,138,162,64, + 68,216,39,17,17,38,95,76,158,159,158,158,250,128,115,17,248,1,16,204,108,112,112,112,176,211,204,200,57,51,54,254, + 152,149,149,21,154,205,38,0,238,78,206,25,51,99,120,104,152,173,205,205,179,11,239,23,230,227,110,186,84,85,213,110, + 72,41,185,170,178,190,190,142,170,238,91,102,241,221,226,161,210,122,186,187,1,24,29,189,43,229,68,184,48,55,255,102, + 12,99,100,143,32,161,170,152,25,34,66,85,85,244,93,235,195,221,107,23,101,89,214,34,189,61,189,242,118,97,238,182, + 25,35,65,85,77,53,147,115,174,29,132,16,152,153,125,69,206,185,118,112,245,202,53,98,140,173,137,128,153,21,80,16, + 82,74,30,99,172,9,246,186,77,255,141,129,90,253,239,177,253,100,59,56,6,16,98,140,166,170,76,204,59,13,13,208, + 121,139,129,135,47,113,107,137,249,129,216,34,216,75,218,251,59,202,162,88,13,170,74,74,137,157,8,143,238,95,231,40, + 72,29,254,32,170,241,96,124,230,76,72,41,89,74,9,112,74,129,143,203,91,71,146,28,68,89,10,231,78,159,2,113, + 15,41,37,83,77,8,80,136,80,133,226,88,130,108,142,27,8,98,123,215,152,17,9,196,100,148,114,176,226,195,208,236, + 52,147,161,102,52,83,6,240,160,170,22,99,68,36,240,109,163,193,207,134,162,217,73,217,49,115,204,157,108,78,210,86, + 14,16,74,97,245,251,46,136,88,16,17,51,51,4,216,216,142,108,55,148,164,255,122,8,165,212,157,44,10,216,220,137, + 136,187,7,119,103,109,163,245,96,94,127,90,173,63,207,113,216,217,217,5,145,175,33,23,237,179,83,75,29,119,192,89, + 94,90,251,175,195,180,188,108,100,228,222,111,248,2,75,29,117,50,217,195,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Properties = { //size: 464 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,4,10,21,27,198,210,43,84,0,0,1,93,73, + 68,65,84,56,203,173,147,189,106,194,80,24,134,159,175,186,25,13,145,108,14,14,130,34,222,130,102,117,232,216,161,215, + 224,45,56,40,113,200,37,136,46,93,116,105,233,218,193,81,112,245,2,78,68,232,162,100,208,156,213,41,118,16,131,49, + 162,8,125,167,195,251,113,158,239,239,28,1,24,143,199,223,65,16,188,241,156,222,251,253,254,23,0,174,235,30,159,149, + 235,186,71,128,236,37,114,191,223,19,69,17,0,34,18,251,231,179,136,144,201,100,48,77,51,142,37,0,81,20,225,251, + 126,226,194,165,68,132,122,189,158,240,178,215,141,213,106,53,0,122,189,94,236,117,58,29,74,165,82,10,8,240,114,157, + 193,247,125,86,171,21,237,118,27,173,53,90,107,60,207,67,41,133,82,234,62,0,96,58,157,98,24,6,205,102,147,110, + 183,139,101,89,88,86,129,106,181,26,87,119,23,112,206,184,88,44,240,60,15,17,65,36,203,118,251,123,115,151,169,22, + 78,25,45,102,179,25,197,98,49,142,141,70,31,4,65,240,184,130,203,222,195,48,36,12,67,180,214,28,14,7,134,195, + 33,187,221,238,254,22,90,173,22,142,227,196,21,109,54,27,38,147,9,133,66,129,92,46,199,124,62,167,82,169,220,6, + 136,8,74,169,212,59,112,28,135,245,122,141,97,24,228,243,249,199,239,224,52,184,36,164,209,104,176,92,46,239,3,46, + 135,118,45,211,52,41,151,203,41,63,11,96,219,246,207,96,48,120,125,230,43,218,182,253,201,127,232,15,224,142,163,230, + 109,49,155,36,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Quit = { //size: 799 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,156,73,68,65,84,56,141,117,147,79,104,20,73,20,198,127,175,170, + 186,187,122,178,131,123,136,30,140,32,234,206,97,47,226,69,65,133,16,209,171,104,80,195,170,228,40,30,12,44,26,15, + 146,187,46,30,246,224,31,140,160,87,69,80,47,158,68,80,20,36,106,4,133,21,28,221,29,119,66,38,108,64,103,162, + 201,244,100,58,157,238,169,61,196,25,255,63,248,168,122,151,175,126,95,61,158,28,28,220,127,50,73,146,17,126,80,34, + 130,239,251,216,192,98,140,1,17,178,44,197,6,246,207,179,103,206,159,48,73,146,140,244,239,218,67,185,92,38,138,34, + 26,141,6,205,102,147,56,142,73,211,148,11,23,206,163,148,66,107,131,82,10,128,102,220,228,236,185,51,195,192,105,3, + 16,4,1,65,16,144,36,9,105,154,210,106,181,112,206,161,181,6,64,41,141,49,230,99,47,104,109,232,89,217,3,144, + 87,0,249,124,158,48,12,201,229,114,132,97,216,185,91,107,1,65,4,68,20,165,209,139,60,216,190,29,17,193,218,16, + 192,152,118,78,107,45,206,185,78,110,17,65,41,133,8,184,44,227,217,209,33,178,106,149,15,197,34,245,191,95,195,127, + 211,252,51,58,218,109,150,16,21,90,107,180,214,248,190,79,150,101,29,179,180,94,231,201,254,131,116,23,10,172,30,24, + 32,46,151,25,223,187,143,101,201,2,79,203,19,247,58,4,109,19,165,84,71,54,138,120,216,219,199,218,29,59,88,190, + 110,29,233,244,52,235,15,29,2,17,196,24,238,28,62,188,20,161,77,209,150,214,154,220,212,20,171,110,222,164,176,115, + 39,63,25,67,116,255,62,40,181,36,17,242,125,125,136,82,116,12,218,175,183,207,238,91,183,88,93,40,96,227,152,232, + 249,115,90,113,76,171,209,160,53,63,143,238,234,34,88,179,6,68,80,159,19,124,30,225,237,224,32,111,94,189,98,186, + 88,68,133,33,139,149,10,217,220,28,46,77,201,234,117,146,74,5,151,101,159,8,218,255,208,54,74,86,172,96,234,200, + 17,114,55,174,19,55,155,172,220,176,1,29,134,44,46,44,208,82,138,249,106,21,156,147,14,193,247,166,145,134,33,183, + 183,108,193,21,126,161,92,169,144,68,17,127,141,143,243,239,228,36,47,138,47,241,186,186,158,126,97,96,140,233,104,98, + 98,130,192,250,12,13,31,227,215,203,151,88,214,191,155,215,165,18,218,90,54,62,30,99,242,248,48,251,162,168,255,139, + 8,158,231,81,122,83,194,134,62,191,29,24,32,159,207,163,181,38,106,212,89,254,251,16,178,170,135,217,187,119,153,157, + 251,64,181,246,14,96,222,0,120,158,71,173,86,37,89,92,96,243,214,77,120,158,143,115,45,230,234,179,128,124,218,204, + 109,189,252,188,173,151,247,239,107,204,204,204,44,25,248,190,127,234,234,181,43,35,181,90,21,17,97,236,209,216,55,235, + 252,117,57,231,8,130,224,15,32,253,31,63,61,253,93,147,0,165,101,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Refresh = { //size: 912 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,3,34,73,68,65,84,56,141, + 109,82,77,108,84,101,20,61,247,123,239,149,249,173,51,109,7,91,168,182,10,134,18,166,161,162,51,141,127,209,152,70, + 55,196,96,88,168,188,68,140,144,129,240,179,97,7,27,12,77,12,17,116,97,162,224,3,163,49,76,37,152,52,1,55, + 252,4,33,146,212,194,171,113,209,208,146,212,210,198,1,70,59,180,29,232,204,180,243,222,251,190,235,162,243,146,89,112, + 146,155,220,197,61,39,39,231,92,98,102,248,72,101,178,207,52,232,218,17,16,222,244,164,106,213,132,152,39,194,184,227, + 202,19,0,46,216,150,233,214,221,30,4,112,130,124,129,116,38,187,69,211,196,64,79,215,42,125,93,103,179,209,214,20, + 1,152,81,40,86,48,50,118,191,124,103,250,161,39,21,239,182,45,243,108,122,87,54,195,140,239,0,196,136,153,145,202, + 100,215,27,186,24,217,218,215,29,138,199,130,208,137,208,28,13,32,28,208,17,13,25,8,26,2,51,197,69,28,207,14, + 87,10,197,138,29,13,53,244,62,46,87,13,102,52,17,51,227,213,61,103,79,245,172,107,251,52,24,48,196,173,209,28, + 170,174,7,67,215,228,154,213,177,197,190,244,243,225,222,245,173,164,9,130,16,132,95,174,77,168,183,94,108,23,7,190, + 190,234,56,174,108,209,1,128,153,63,188,51,93,16,174,167,88,49,47,50,227,51,199,149,103,198,167,103,147,19,247,230, + 143,94,239,104,238,218,183,117,83,40,17,11,225,227,119,187,68,45,6,2,160,4,0,72,169,194,85,199,243,146,47,60, + 251,131,148,234,17,128,65,219,50,243,182,101,94,249,227,219,143,94,26,157,44,236,221,125,236,18,238,63,44,97,122,166, + 12,169,24,0,3,0,11,44,175,170,233,169,72,127,99,36,240,85,103,251,202,110,0,83,117,105,235,186,38,118,110,123, + 39,233,118,62,29,69,162,113,5,52,65,190,3,214,107,119,241,95,63,223,188,128,39,227,180,39,213,107,23,135,39,171, + 87,237,169,37,223,188,227,170,0,0,246,91,168,2,48,106,4,174,155,223,0,236,4,224,62,65,88,183,45,243,158,47, + 224,157,63,250,190,6,16,152,25,23,237,127,212,169,243,127,229,164,84,61,182,101,22,235,89,135,179,99,171,74,229,165, + 142,223,71,198,111,0,136,233,0,64,4,16,17,238,254,87,134,33,24,39,7,255,36,0,95,212,147,83,153,108,152,136, + 238,246,110,92,123,38,63,51,151,2,160,1,168,10,0,16,68,4,0,29,137,16,86,183,132,241,229,254,183,169,173,37, + 114,236,149,61,63,223,74,101,178,233,154,198,246,21,134,174,231,242,179,7,242,133,226,235,154,70,174,109,153,174,88,118, + 64,120,92,113,113,97,104,138,61,143,209,190,50,138,195,59,222,8,125,208,151,124,185,181,57,114,45,189,107,192,53,116, + 241,141,84,50,62,247,104,1,77,141,65,210,132,24,4,0,255,145,168,255,199,161,165,137,220,220,228,165,225,201,206,204, + 150,77,225,68,44,136,238,181,9,122,174,61,30,42,150,93,252,59,91,130,227,120,20,9,26,56,119,121,180,226,73,117, + 4,0,150,31,73,49,77,228,230,78,223,60,185,45,249,160,176,240,73,255,247,55,230,143,15,220,44,13,223,206,35,63, + 91,70,213,149,16,68,40,204,151,228,185,203,163,139,82,169,140,109,153,99,0,224,183,240,19,128,237,182,101,114,45,48, + 3,192,123,13,134,182,87,49,111,144,82,197,13,93,155,33,194,80,213,145,135,108,203,252,219,15,247,127,46,85,118,106, + 19,101,204,198,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Remove = { //size: 247 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,214,1,11,15,59,34,0,92,18,194,0,0,0,132,73, + 68,65,84,56,203,237,145,177,9,131,80,16,134,191,7,105,220,192,58,43,232,8,25,35,173,109,70,8,25,32,11,136, + 173,115,196,5,116,136,212,182,34,68,243,238,79,33,202,179,179,51,133,31,28,28,7,255,119,28,7,7,251,227,230,38, + 205,202,26,72,54,230,154,186,184,166,0,167,96,152,60,111,23,70,19,14,24,189,86,9,105,42,7,220,243,215,178,40, + 20,208,125,60,239,182,71,2,51,97,130,126,16,222,139,175,9,51,56,199,209,74,28,10,154,71,94,109,62,225,248,254, + 63,241,3,172,83,45,219,70,228,128,216,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Save = { //size: 911 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,10,13,55,15,158,42,216,191,0,0,0,140,116, + 69,88,116,67,111,109,109,101,110,116,0,77,101,110,117,45,115,105,122,101,100,32,105,99,111,110,10,61,61,61,61,61, + 61,61,61,61,61,10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83, + 116,101,105,110,101,114,44,32,10,104,116,116,112,58,47,47,106,105,109,109,97,99,46,109,117,115,105,99,104,97,108,108, + 46,99,122,10,10,99,114,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,71,73,77,80,44,10,104,116,116,112, + 58,47,47,119,119,119,46,103,105,109,112,46,111,114,103,103,138,199,71,0,0,2,132,73,68,65,84,56,203,157,146,77, + 72,84,97,20,134,159,185,221,241,230,207,228,76,224,181,49,205,145,178,81,108,81,81,52,38,20,184,200,22,69,20,46, + 66,40,44,130,138,169,193,86,45,42,202,69,17,84,16,6,82,180,40,10,34,176,40,40,106,91,208,34,137,68,138,166, + 69,153,84,106,134,164,232,220,155,206,253,249,78,11,97,108,178,54,189,155,243,193,225,60,156,247,61,95,224,200,217,227, + 39,63,91,21,218,216,184,51,9,84,1,91,129,134,160,38,217,208,194,159,63,22,25,206,205,187,231,207,157,224,31,10, + 52,119,116,237,141,173,172,143,85,151,155,131,171,107,202,58,170,35,133,107,109,207,39,253,45,195,235,222,231,234,195,215, + 81,226,145,55,203,186,59,239,12,255,21,144,60,125,190,219,157,26,59,236,137,198,168,31,102,218,40,99,129,30,164,173, + 101,35,203,43,22,115,249,254,11,252,161,62,98,5,227,127,155,239,36,121,44,37,95,70,6,68,68,100,224,115,90,122, + 211,3,146,186,246,68,18,7,47,72,207,171,47,210,245,244,173,180,158,186,46,239,6,135,229,119,89,150,37,169,142,164, + 232,134,238,179,180,60,198,196,196,4,225,146,114,180,192,36,133,226,0,208,247,113,20,179,68,231,251,120,134,247,3,159, + 88,178,168,16,2,0,66,65,65,1,0,186,231,130,40,193,87,138,237,39,110,204,219,177,119,112,2,215,243,185,216,243, + 146,139,61,47,1,120,124,118,31,200,108,95,3,80,162,80,190,162,235,80,35,0,237,187,119,210,152,88,199,204,140,77, + 52,164,209,148,88,207,222,214,237,0,236,105,94,129,242,21,34,50,7,16,17,34,145,48,21,101,49,46,29,88,199,205, + 187,15,136,199,170,208,8,160,17,32,81,95,205,173,123,143,104,219,92,195,142,166,245,20,21,23,229,3,0,44,203,194, + 52,77,170,163,181,57,72,227,170,229,212,198,42,185,124,251,33,109,155,107,216,181,41,129,105,154,56,142,147,179,168,3, + 40,165,176,109,27,0,211,52,49,77,147,238,163,133,28,187,218,67,214,245,217,223,82,79,251,182,45,104,154,198,212,212, + 20,182,109,19,10,133,230,0,134,97,80,89,89,153,23,222,154,134,13,60,187,178,1,0,219,182,113,28,135,233,233,233, + 121,33,235,0,253,253,253,184,174,155,215,240,60,15,93,215,115,239,63,21,137,68,242,51,240,60,143,116,58,205,200,200, + 8,153,76,6,17,65,68,48,12,131,161,161,33,66,161,80,174,90,150,133,101,89,249,87,80,74,81,92,92,68,48,24, + 204,125,18,0,215,117,17,53,11,19,53,123,62,229,251,249,22,194,225,48,165,165,165,68,163,81,0,178,217,44,64,46, + 237,120,93,28,165,20,241,186,58,148,82,44,137,70,115,150,3,169,142,228,25,224,52,255,167,206,95,147,59,51,76,213, + 34,98,109,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Search = { //size: 935 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,6,29,17,18,8,200,223,108,120,0,0,3,52,73, + 68,65,84,56,203,165,147,91,104,84,119,16,198,103,254,231,178,231,156,205,222,226,110,54,169,27,52,136,26,139,151,54, + 27,91,179,84,173,164,62,24,124,80,52,20,20,162,146,66,169,171,173,15,53,77,53,84,90,52,68,193,18,164,84,104, + 107,21,164,133,38,47,125,170,180,198,16,47,72,172,104,64,163,193,91,196,100,147,205,222,183,155,205,238,158,61,57,243, + 247,37,27,90,241,173,31,12,51,204,195,143,111,24,62,132,87,212,214,126,248,55,189,144,223,138,136,42,113,66,206,249, + 140,205,102,191,216,121,188,235,19,120,141,196,210,240,69,251,225,13,185,124,254,175,230,157,205,178,195,81,142,69,195,228, + 38,7,144,5,180,78,103,82,31,103,50,211,123,237,118,91,99,231,241,174,155,255,6,32,0,192,177,175,59,214,166,211, + 233,91,193,253,159,97,223,221,201,226,72,82,44,40,154,166,154,196,165,92,54,155,241,191,1,74,227,219,62,185,251,204, + 105,170,240,84,212,119,28,61,54,244,31,7,137,68,114,224,211,3,135,240,247,219,81,99,74,183,75,187,54,249,178,11, + 23,104,255,152,68,174,161,231,233,196,141,145,216,162,233,191,195,197,131,193,67,114,247,153,111,175,1,128,173,4,16,58, + 190,58,210,230,175,171,223,60,154,20,205,209,25,77,250,168,113,73,164,202,165,162,34,51,137,8,100,213,34,166,114,250, + 236,195,231,73,170,177,80,206,240,186,20,92,189,102,85,246,234,192,181,91,0,0,44,145,136,159,244,215,249,165,193,23, + 134,28,88,238,54,4,6,110,221,48,157,121,125,86,51,137,4,211,52,221,145,148,238,65,192,240,112,4,228,119,214,190, + 171,68,163,145,238,249,19,36,73,226,4,12,173,118,7,40,178,120,47,147,55,152,98,114,93,20,176,72,196,151,246,220, + 8,157,52,136,202,128,131,43,109,136,159,171,170,6,146,36,241,121,0,17,205,90,36,81,146,24,231,79,38,166,167,24, + 218,152,171,12,76,189,104,134,199,98,185,144,78,20,23,56,18,48,174,204,26,134,169,235,186,64,68,198,60,192,235,245, + 222,153,152,152,168,119,200,50,62,30,143,151,143,199,115,55,57,131,40,34,139,32,113,183,0,48,3,200,173,201,88,116, + 125,237,162,114,76,38,19,122,101,101,213,96,9,192,68,81,252,177,127,224,74,120,171,223,43,168,86,53,96,114,178,1, + 71,6,156,139,28,200,65,8,114,161,80,168,112,121,60,239,111,121,203,195,126,190,112,46,147,78,167,250,231,191,112,165, + 175,127,104,197,155,181,109,86,139,168,175,92,86,163,141,198,139,245,177,112,200,163,170,234,51,226,84,27,25,127,177,221, + 229,118,239,222,177,74,132,193,235,127,114,85,209,48,22,139,53,212,44,89,124,225,225,131,145,172,0,0,176,99,231,246, + 203,195,15,238,239,231,185,212,212,174,166,128,221,0,177,114,166,200,63,224,40,172,169,91,90,81,181,205,239,134,115,103, + 79,83,96,93,128,77,78,77,74,68,166,196,24,107,105,104,88,215,135,37,43,93,167,78,172,30,27,27,255,195,227,246, + 20,156,206,114,217,95,231,119,86,87,87,219,122,122,123,30,61,121,250,72,213,243,198,55,78,151,253,167,166,45,77,112, + 111,248,62,108,120,111,35,253,242,235,69,134,175,134,163,235,212,137,125,0,208,28,10,133,54,2,128,230,243,249,46,1, + 64,111,123,219,209,243,193,96,176,19,25,255,114,79,203,94,176,90,203,224,251,179,223,1,190,38,96,108,174,176,148,149, + 185,206,1,0,90,91,91,91,84,205,242,195,220,238,67,248,191,122,9,59,169,102,147,104,79,162,5,0,0,0,0,73, + 69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Settings = { //size: 611 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,9,26,12,19,57,139,99,194,72,0,0,1,240,73, + 68,65,84,56,203,165,146,75,104,19,97,20,133,191,153,248,76,138,77,20,10,130,74,176,204,198,133,182,221,69,172,46, + 52,20,98,102,235,66,112,33,84,164,168,181,45,18,82,2,21,3,67,66,160,107,65,116,101,64,138,226,194,137,141,208, + 98,87,130,210,54,137,73,23,21,130,85,105,211,151,134,32,68,68,58,51,110,102,134,49,29,235,194,179,251,185,231,156, + 123,239,185,63,252,39,4,231,35,157,81,162,128,10,200,241,88,34,247,23,77,52,157,81,108,142,216,82,84,251,175,246, + 3,168,166,153,171,248,250,181,1,205,108,180,29,233,140,98,52,26,117,35,157,81,12,247,90,195,170,69,1,196,116,70, + 137,90,100,171,171,215,219,230,102,28,5,120,240,240,62,241,88,66,6,114,0,34,160,14,222,28,50,158,62,155,48,0, + 245,246,173,17,54,215,215,144,58,37,234,245,175,247,90,179,137,221,25,21,44,49,128,96,21,111,12,12,26,154,182,37, + 232,186,110,232,186,70,97,126,78,40,188,47,2,200,59,5,43,180,116,176,17,233,187,72,185,82,97,185,246,5,32,25, + 143,37,238,254,243,140,78,188,202,191,52,74,149,18,221,39,123,40,150,11,152,19,76,2,186,171,65,48,146,58,12,212, + 172,247,149,144,78,215,9,137,163,71,142,209,108,54,121,55,247,22,183,53,60,78,241,248,112,152,190,80,39,29,1,47, + 217,153,77,142,183,127,75,46,125,94,58,215,125,170,135,128,63,192,74,109,249,242,133,240,249,249,233,169,215,85,192,0, + 16,131,145,84,23,80,123,52,38,51,91,94,100,182,188,72,199,65,31,0,230,222,114,46,255,2,73,146,56,123,186,215, + 250,100,118,30,34,80,28,31,14,51,245,166,196,150,166,35,238,243,179,81,111,218,35,154,35,203,217,39,143,57,208,238, + 231,76,168,23,96,204,105,0,192,238,93,30,246,248,14,241,243,199,47,178,249,5,128,112,171,73,46,175,82,253,88,253, + 35,108,17,96,101,227,59,251,125,1,218,246,122,120,62,243,1,32,252,105,114,116,218,73,52,77,146,107,235,171,11,64, + 210,190,66,48,146,186,4,76,56,184,219,196,59,225,55,55,226,213,246,234,188,84,188,0,0,0,0,73,69,78,68,174, + 66,96,130, +}; +const nall::vector<uint8_t> Stop = { //size: 820 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,17,23,45,13,107,192,156,192,0,0,2,193,73, + 68,65,84,56,203,109,147,187,79,83,97,24,135,159,115,233,5,109,141,198,200,224,37,134,198,64,43,120,105,106,184,9, + 169,54,136,154,152,144,184,177,16,88,252,15,92,58,56,24,105,28,28,76,28,140,11,113,208,193,187,49,184,152,80,36, + 154,176,136,193,196,14,14,40,181,212,22,74,105,161,7,225,180,231,59,159,3,165,130,242,38,95,190,228,77,158,223,123, + 249,229,85,216,18,143,194,97,61,61,49,241,68,192,85,118,8,13,198,4,92,142,66,101,51,167,252,3,63,107,244,249, + 46,93,188,118,205,173,104,26,0,82,74,16,2,105,89,124,120,248,208,252,50,51,243,94,192,149,40,88,53,129,42,252, + 194,239,243,245,70,134,134,220,243,227,227,152,249,252,182,234,78,175,151,250,142,14,62,60,125,106,38,146,201,49,1,125, + 81,176,180,145,80,200,145,157,156,124,25,56,118,172,55,50,56,184,1,175,174,130,101,109,19,16,170,202,90,58,77,32, + 18,209,87,231,230,142,44,149,74,103,6,195,225,231,90,103,38,243,230,120,99,99,207,249,129,1,119,54,30,199,170,175, + 71,143,197,32,153,68,102,179,27,179,159,56,193,222,187,119,169,36,18,24,95,191,114,60,28,214,141,84,234,232,143,68, + 34,168,245,168,234,227,254,235,215,245,204,187,119,148,11,5,212,190,62,212,150,22,148,142,14,248,254,29,117,255,126,246, + 12,15,227,218,183,15,69,74,74,227,227,252,46,20,104,14,135,245,169,207,159,3,186,162,40,32,37,229,66,97,163,213, + 145,17,112,185,112,245,246,226,190,113,3,93,81,112,122,60,152,241,56,249,59,119,176,129,117,195,64,10,129,2,168,255, + 121,37,37,226,254,125,228,212,20,206,93,187,112,122,189,88,211,211,228,98,49,132,109,99,3,54,32,171,59,82,119,244, + 187,185,25,119,40,132,174,235,56,28,14,118,7,131,212,133,66,200,42,44,202,101,196,220,220,95,1,41,68,13,86,91, + 90,240,222,186,133,211,235,101,61,30,103,117,116,20,167,199,131,239,222,61,60,237,237,152,185,28,198,183,111,200,149,21, + 0,116,41,229,134,154,97,32,44,139,186,182,54,92,85,120,113,120,24,219,52,209,128,3,253,253,212,157,58,197,250,131, + 7,160,105,216,213,162,218,5,41,187,43,197,226,225,64,91,155,86,74,36,40,189,126,77,229,231,79,22,110,222,164,156, + 201,80,94,92,36,247,234,21,107,179,179,36,111,223,70,209,52,124,126,63,233,165,37,251,199,242,114,94,137,129,83,131, + 183,39,27,26,186,91,131,65,87,42,30,103,173,88,172,45,107,235,83,28,14,26,154,154,72,23,10,226,99,58,189,96, + 67,167,54,6,34,2,79,114,197,98,151,105,24,135,2,173,173,122,105,126,158,138,105,110,131,85,135,131,6,191,159,217, + 124,94,76,254,250,149,178,161,61,10,169,218,49,109,118,226,63,120,176,251,236,233,211,46,69,8,108,203,66,90,86,237, + 79,36,147,214,167,108,118,198,134,174,40,44,110,187,198,173,34,2,122,118,178,87,133,105,27,206,69,97,121,51,247,7, + 199,77,82,246,215,134,247,20,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Application { +const nall::vector<uint8_t> Browser = { //size: 928 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,26,7,44,7,230,25,222,143,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,2,236, + 73,68,65,84,56,203,173,147,93,104,91,101,28,135,159,247,156,247,156,99,147,52,105,155,230,163,141,109,214,208,162,44, + 184,117,178,200,196,171,41,168,48,20,111,148,41,221,69,101,56,16,111,132,161,160,183,82,16,197,251,93,136,21,71,65, + 196,233,141,76,134,55,179,48,181,179,150,141,118,43,174,235,92,63,179,156,44,31,77,114,146,115,146,156,215,11,217,196, + 237,214,231,250,255,123,46,254,252,126,130,7,56,254,222,236,41,224,45,93,202,253,10,44,229,251,13,165,88,208,116,237, + 236,220,204,212,23,15,222,139,251,193,247,191,156,52,117,237,199,137,177,100,226,200,129,52,99,169,40,1,203,162,92,111, + 178,182,105,179,184,178,201,141,141,194,101,33,196,201,185,153,169,171,255,17,188,246,238,231,185,96,184,231,183,87,142,30, + 20,7,39,226,148,235,77,236,157,13,100,40,14,61,253,224,216,164,18,81,22,86,182,57,63,191,114,23,33,158,189,39, + 145,0,209,104,232,167,231,159,201,138,39,50,3,148,138,121,6,71,179,68,6,135,112,90,109,242,155,235,72,223,67,235, + 54,121,46,151,161,235,171,232,133,75,215,207,0,79,3,104,111,126,248,213,71,201,120,127,248,104,110,28,67,243,233,200, + 16,104,2,67,74,76,67,18,176,36,137,104,47,67,241,24,177,190,32,185,236,163,164,135,7,142,188,241,193,217,105,0, + 45,28,9,156,60,156,29,165,82,46,114,199,13,16,31,222,135,82,224,43,64,104,8,223,99,183,212,224,251,139,203,92, + 152,95,36,98,41,246,143,15,3,188,10,32,107,78,59,150,78,246,179,112,163,64,102,34,142,175,254,253,108,189,82,226, + 169,201,44,66,8,148,82,108,239,222,161,213,108,50,20,139,0,28,6,208,90,94,71,179,44,19,45,20,167,82,111,97, + 215,60,28,183,75,205,241,240,234,54,66,252,163,19,66,144,136,69,185,186,122,19,203,144,0,3,0,82,215,53,191,218, + 104,105,193,214,14,33,105,81,104,12,82,52,76,58,93,159,86,169,195,100,187,141,235,122,244,134,130,56,142,195,190,84, + 140,66,211,3,40,1,72,67,211,242,183,182,138,195,135,198,147,100,70,134,184,189,185,205,252,218,30,30,38,77,47,200, + 167,223,94,193,18,93,222,126,249,0,181,90,141,165,107,55,161,55,13,240,59,128,166,186,221,115,75,171,91,120,190,4, + 32,61,146,226,216,161,24,187,133,18,119,171,13,170,174,224,118,217,199,182,109,170,213,42,143,244,167,88,93,207,3,124, + 3,160,47,253,124,238,252,120,238,165,211,66,215,205,72,208,160,199,212,249,101,113,153,229,188,162,214,112,217,107,184,236, + 57,46,185,17,157,194,158,199,86,217,231,218,218,206,175,115,51,83,239,220,47,82,165,80,60,113,241,178,255,157,239,195, + 147,143,37,248,225,74,149,178,103,226,117,186,184,94,7,203,16,108,84,20,127,21,218,92,250,99,173,44,132,56,245,208, + 22,142,77,127,252,250,104,102,100,54,28,233,51,31,207,36,73,14,134,177,44,3,167,213,102,215,174,240,231,173,60,91, + 59,197,235,66,151,199,31,218,194,61,250,6,198,204,23,78,156,158,213,173,192,139,232,178,15,132,80,202,239,168,78,123, + 93,9,237,179,175,63,153,62,195,255,205,223,112,108,55,247,49,218,29,149,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Calculator = { //size: 686 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,6,6,13,47,29,93,206,74,167,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,1,250, + 73,68,65,84,56,203,157,147,193,106,83,65,20,134,191,57,51,193,94,210,214,146,54,8,90,109,11,117,97,82,72,218, + 110,196,165,175,16,74,23,69,16,116,227,86,220,27,10,238,196,39,80,240,61,164,186,44,90,219,36,205,109,192,130,138, + 74,139,168,237,197,132,18,99,114,231,184,72,188,165,139,34,118,54,195,240,207,124,115,254,255,204,152,165,229,210,67,160, + 204,217,70,217,44,45,151,244,206,221,219,103,58,253,236,233,115,220,223,197,230,214,203,83,55,182,90,71,164,211,1,237, + 118,7,107,133,161,161,115,44,46,220,4,56,6,52,155,7,167,2,62,188,223,195,90,33,58,108,209,108,30,113,253,198, + 92,162,37,128,153,153,185,83,1,83,83,57,140,49,168,42,198,24,140,49,137,102,150,150,75,26,53,219,60,184,127,239, + 191,252,175,62,122,194,165,11,153,126,5,221,110,143,242,234,99,126,117,58,125,85,21,253,7,64,68,142,45,220,90,89, + 225,213,218,11,188,135,139,147,147,124,221,223,199,251,152,145,243,99,180,126,70,168,247,4,233,17,140,8,209,225,1,34, + 134,254,13,30,23,4,1,149,173,55,92,157,157,69,85,9,195,144,124,62,143,181,150,48,12,201,229,114,136,8,141,70, + 3,197,176,56,95,36,149,74,209,237,118,169,213,43,72,187,221,198,199,30,85,77,66,2,136,227,24,48,116,58,29,188, + 247,0,120,85,172,181,232,96,78,44,92,153,154,225,245,250,58,24,195,68,54,203,206,78,3,239,99,198,50,227,188,219, + 221,5,85,198,50,19,40,80,171,213,18,72,2,248,252,233,35,197,98,161,111,161,209,32,151,187,134,115,142,122,189,206, + 124,177,136,136,80,173,214,112,206,81,40,20,146,42,55,43,27,200,32,118,156,115,120,239,241,189,30,214,90,156,115,136, + 72,210,119,17,3,244,75,79,165,82,39,187,48,121,121,154,202,230,91,192,48,158,205,178,93,175,227,172,37,61,60,204, + 118,24,98,84,25,10,2,126,15,218,60,58,58,74,20,69,39,95,226,252,194,2,0,214,90,226,233,105,12,96,68,208, + 65,128,70,132,189,189,47,124,255,241,141,195,232,96,16,114,31,80,174,86,55,206,252,157,255,0,132,92,203,16,0,89, + 204,210,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Calendar = { //size: 603 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,251,0,251,0,251,85,89,109,150,0,0,0,9,112,72,89,115,0,0,11,18,0, + 0,11,18,1,210,221,126,252,0,0,0,7,116,73,77,69,7,213,6,3,15,29,43,75,94,175,19,0,0,0,62,116, + 69,88,116,67,111,109,109,101,110,116,0,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80, + 10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83,116,101,105,110,101, + 114,39,51,239,88,0,0,1,158,73,68,65,84,56,203,157,147,177,138,26,81,20,134,191,59,115,103,28,80,80,176,16, + 123,11,5,17,130,1,21,124,5,43,9,193,98,11,193,224,110,49,181,181,189,196,128,32,90,167,77,47,250,2,98,37, + 34,193,38,33,149,133,173,144,197,217,48,222,20,50,119,103,214,221,37,155,83,205,156,123,206,119,207,255,159,25,241,225, + 99,243,27,208,228,255,98,34,129,102,247,211,221,155,59,227,241,56,159,191,12,110,101,144,216,108,54,0,8,33,254,9, + 80,171,213,0,144,0,153,76,134,82,169,116,213,44,132,120,54,39,165,228,124,62,95,0,229,119,239,41,22,139,36,147, + 201,200,4,225,230,167,32,199,113,72,165,82,44,22,11,228,75,55,62,125,14,194,52,77,12,195,0,192,243,78,24,225, + 230,201,100,66,181,90,37,159,207,227,186,174,206,151,203,101,178,217,44,167,211,9,33,4,190,239,107,96,4,208,233,116, + 88,173,86,244,251,125,102,179,153,214,57,26,141,46,122,165,196,182,109,76,211,212,0,25,6,236,118,59,218,237,54,135, + 195,1,215,117,117,161,109,219,186,198,48,140,136,36,35,236,65,46,151,99,189,94,51,24,12,24,143,199,248,190,31,209, + 44,165,68,41,133,101,89,215,19,0,244,122,61,150,203,37,158,231,209,237,118,113,28,7,203,178,104,181,90,212,235,117, + 230,243,57,141,70,131,88,44,246,188,132,233,116,170,71,12,118,45,132,96,191,223,235,13,72,41,35,18,52,32,157,78, + 107,211,2,151,149,82,40,165,16,66,160,148,194,247,125,125,150,72,36,30,1,199,227,145,225,112,120,245,13,188,246,94, + 40,20,46,128,135,135,63,108,183,91,42,149,202,139,197,225,8,12,13,124,144,219,239,155,27,224,235,253,253,239,55,255, + 145,63,127,253,184,249,11,104,130,125,246,45,41,107,239,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Chat = { //size: 422 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,6,6,13,5,59,224,168,3,114,0,0,1,51,73, + 68,65,84,56,203,149,147,65,78,132,48,24,133,223,79,155,176,109,34,18,247,19,111,97,244,30,198,149,196,3,152,56, + 25,131,58,139,137,16,96,244,4,70,99,226,17,52,46,245,2,156,132,160,48,43,23,99,169,27,74,42,3,136,127,194, + 162,180,239,235,123,253,91,130,81,81,18,28,1,120,194,248,154,163,5,80,255,169,40,9,20,239,194,230,121,14,165,20, + 148,82,189,91,187,174,11,0,224,81,18,92,1,88,232,137,120,25,14,122,222,223,59,192,100,178,219,140,57,128,197,108, + 234,143,14,29,47,195,13,0,0,32,203,178,94,17,17,129,136,224,56,78,51,222,0,12,9,77,193,104,128,41,110,67, + 180,147,78,64,151,176,237,64,159,69,85,41,143,247,217,29,3,241,207,47,31,248,95,150,187,0,70,171,137,155,185,138, + 162,0,17,65,8,49,216,74,249,45,79,24,103,119,0,20,133,209,245,177,101,209,253,108,234,163,44,75,41,132,96,67, + 151,105,123,107,231,214,243,188,179,198,130,126,3,250,50,197,203,16,159,31,197,225,203,243,235,187,94,196,24,171,108,219, + 150,0,214,105,154,126,1,88,155,93,32,51,215,170,92,157,38,241,205,91,61,103,1,144,0,170,250,83,245,255,95,0, + 165,115,93,248,243,71,0,172,22,178,122,77,213,130,72,51,210,15,141,12,145,160,100,148,198,107,0,0,0,0,73,69, + 78,68,174,66,96,130, +}; +const nall::vector<uint8_t> FileManager = { //size: 378 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,6,16,18,41,48,44,67,93,90,0,0,1,7,73, + 68,65,84,56,203,189,146,189,74,3,65,28,196,127,251,145,69,177,176,73,44,124,128,128,207,225,19,8,130,136,31,129, + 136,104,37,34,104,173,32,10,130,181,165,112,6,242,20,190,78,138,120,8,90,104,178,183,123,107,17,15,205,37,94,238, + 82,56,229,252,255,59,179,179,179,226,168,221,4,216,19,130,136,10,8,129,125,224,73,103,135,175,78,46,73,146,1,225, + 123,90,4,33,36,215,15,183,81,8,32,142,15,154,225,188,125,138,148,211,151,245,48,198,153,250,4,175,134,49,55,157, + 14,58,35,30,163,59,250,214,148,186,254,138,177,180,118,47,70,6,25,217,183,134,237,213,151,82,2,221,94,131,193,231, + 59,90,215,144,204,9,169,70,222,114,150,83,183,215,40,20,210,191,115,253,181,156,231,151,148,35,245,14,231,146,31,129, + 245,250,219,92,81,52,128,181,31,60,199,203,149,90,216,202,71,168,218,130,79,253,236,71,44,213,6,64,234,221,255,182, + 48,33,96,236,43,155,27,135,99,131,212,123,164,82,164,222,231,62,208,56,39,90,59,107,247,139,11,254,76,235,218,84, + 7,231,146,194,8,95,134,90,101,183,231,143,210,134,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Mail = { //size: 550 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,18,0, + 0,11,18,1,210,221,126,252,0,0,0,7,116,73,77,69,7,213,6,6,12,23,54,231,47,101,43,0,0,1,179,73, + 68,65,84,56,203,197,147,65,72,20,97,24,134,159,89,70,247,119,112,23,215,177,173,131,167,234,88,104,23,221,240,212, + 146,134,134,129,6,65,25,102,97,68,68,224,69,139,60,111,108,219,65,17,4,145,144,78,118,232,32,136,29,234,166,201, + 222,108,219,14,9,230,213,52,88,171,63,98,254,29,115,103,60,168,131,131,163,16,8,126,199,247,251,222,231,127,127,62, + 62,56,238,210,130,196,116,38,85,15,228,2,90,23,158,14,12,126,62,148,152,206,164,234,211,153,148,27,84,233,76,202, + 221,129,7,39,216,125,249,73,255,51,150,22,243,252,150,146,98,209,230,231,250,47,254,252,149,116,223,185,207,139,151,207, + 125,73,180,131,204,185,124,158,120,252,20,85,85,49,52,45,132,82,54,170,88,36,153,76,250,32,250,158,0,185,219,183, + 186,249,240,126,134,229,229,111,180,180,92,37,86,93,77,69,133,129,97,24,0,100,179,89,166,167,222,114,175,167,151,137, + 215,175,114,128,182,23,128,105,214,96,89,54,61,119,31,120,166,221,42,20,10,152,166,137,8,235,68,34,81,79,247,1, + 132,16,52,54,54,240,110,102,154,75,201,203,0,88,150,133,82,10,165,20,139,95,191,208,126,173,3,33,68,48,0,224, + 68,60,78,226,98,130,55,147,147,156,61,115,26,128,242,176,206,202,202,15,58,175,119,162,135,252,155,215,131,86,25,141, + 68,49,99,149,52,95,105,246,180,209,145,33,202,117,13,219,182,17,84,122,122,104,159,219,117,153,155,155,229,198,205,46, + 79,114,74,155,60,124,244,152,143,243,243,40,101,249,198,247,1,62,45,44,208,218,214,198,230,134,141,235,56,148,254,109, + 160,161,225,148,28,234,206,159,227,251,234,218,193,95,144,82,210,144,104,218,110,232,97,223,96,25,32,140,8,53,39,107, + 145,82,6,2,134,199,198,71,251,254,227,142,134,143,228,26,183,0,252,253,172,100,78,184,216,168,0,0,0,0,73,69, + 78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Monitor = { //size: 611 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,19,17,58,52,159,194,36,103,0,0,1,240,73, + 68,65,84,56,203,165,147,61,104,20,65,24,134,159,221,153,157,221,189,194,20,34,18,209,75,97,12,66,208,72,2,1, + 33,96,97,115,96,17,36,106,180,17,82,88,137,193,70,17,15,46,133,164,176,178,49,130,149,86,134,147,72,136,88,156, + 66,42,27,65,68,61,73,180,9,130,7,241,206,52,10,130,119,59,127,22,49,49,33,39,74,124,225,101,186,103,158,225, + 251,38,40,149,138,15,128,115,108,35,222,251,105,74,165,162,111,181,154,190,217,106,250,191,197,57,231,51,157,173,183,84, + 42,122,185,70,155,184,59,79,185,82,253,167,155,71,11,135,185,112,162,7,0,9,16,69,138,114,165,138,234,0,37,99, + 136,20,103,142,46,67,16,50,251,166,11,156,7,60,24,139,54,134,114,165,202,248,233,62,0,194,141,100,21,167,68,105, + 202,217,161,58,23,135,7,17,74,146,38,9,105,46,69,37,41,34,151,144,36,9,0,214,152,223,6,107,17,42,70,36, + 49,253,61,123,8,115,5,250,187,27,168,232,19,143,23,14,32,188,3,35,201,66,13,128,177,118,171,65,148,40,70,6, + 107,236,219,213,193,203,165,6,93,249,83,136,72,146,36,49,81,162,16,113,132,138,213,159,13,78,14,212,8,3,137,200, + 21,224,219,44,65,48,130,144,130,171,199,159,179,80,223,141,179,14,235,44,83,111,3,140,109,3,184,60,122,157,128,128, + 143,181,25,222,47,127,37,191,23,14,229,119,114,164,211,48,216,55,142,247,0,158,169,251,183,218,3,110,207,220,68,40, + 129,148,17,66,10,62,55,230,232,221,63,202,195,215,53,204,247,59,88,99,177,198,254,122,130,221,10,120,242,174,155,40, + 85,168,88,17,197,10,33,63,112,176,243,25,190,89,35,12,2,158,46,245,210,252,145,1,139,237,13,96,117,222,22,71, + 232,29,206,57,46,61,234,192,249,29,104,109,208,86,99,113,171,6,27,1,90,103,140,13,15,112,111,238,213,38,220,226, + 60,192,139,182,155,184,242,101,101,179,193,149,243,67,92,27,59,134,214,25,89,43,67,27,141,214,107,231,134,26,77,163, + 81,95,135,73,96,122,114,242,198,246,127,227,255,230,39,112,67,0,83,217,168,244,129,0,0,0,0,73,69,78,68,174, + 66,96,130, +}; +const nall::vector<uint8_t> Terminal = { //size: 668 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,18,21,37,27,70,252,216,25,0,0,2,41,73, + 68,65,84,56,203,125,147,207,75,84,81,20,199,63,119,124,51,42,100,65,134,209,194,192,18,10,87,174,92,181,168,69, + 203,54,237,130,210,106,145,186,8,23,65,96,173,130,54,181,14,74,176,69,98,130,254,1,181,45,37,8,194,162,52,80, + 35,157,177,24,43,29,125,142,153,239,221,95,167,197,27,103,70,45,15,28,238,189,220,115,63,247,123,14,231,168,161,231, + 131,7,141,177,253,214,218,238,56,142,27,140,49,84,220,98,108,245,57,113,103,221,122,20,199,143,181,214,15,2,165,212, + 253,163,77,199,122,78,182,180,166,51,181,117,128,128,240,79,243,222,177,94,44,146,95,202,55,142,79,188,190,157,91,204, + 166,3,224,250,137,150,214,244,149,174,78,166,63,77,179,159,137,36,228,211,109,167,232,237,233,205,228,22,179,61,129,136, + 212,41,149,226,203,220,28,163,47,31,225,197,33,34,120,113,120,239,17,73,220,121,65,196,225,189,163,243,66,63,169,148, + 66,68,14,5,21,121,194,212,199,89,192,225,189,148,64,201,227,109,144,23,193,121,11,128,117,201,90,5,240,52,54,53, + 36,193,222,227,177,120,239,240,37,64,108,182,8,215,151,9,55,11,0,56,231,118,2,68,132,169,15,51,244,245,222,229, + 217,200,19,150,11,121,4,193,57,75,33,252,73,20,109,38,129,74,37,31,238,1,120,161,190,33,195,171,55,47,184,209, + 213,71,97,109,153,193,145,135,172,21,126,65,141,165,254,64,109,9,64,41,133,93,0,47,158,217,233,121,86,127,252,161, + 163,253,28,153,160,150,247,147,159,17,239,203,143,80,149,237,158,20,16,32,112,220,236,190,197,240,216,0,111,39,39,8, + 210,10,168,41,41,87,59,20,184,221,69,4,248,58,251,141,75,87,47,130,8,40,120,55,62,83,190,211,58,230,204,249, + 246,242,217,57,191,171,6,128,243,46,169,145,74,1,208,113,182,173,74,186,66,165,82,251,40,16,40,174,110,253,191,13, + 171,242,223,81,3,165,148,6,169,111,62,222,204,194,194,66,185,93,247,179,198,35,135,137,226,8,165,212,239,0,212,112, + 54,55,127,109,108,108,52,216,216,40,18,134,33,97,184,70,20,69,24,107,176,214,98,183,39,209,90,172,53,104,163,89, + 89,41,104,224,105,32,226,239,228,151,190,147,205,205,95,54,198,100,180,214,149,81,54,166,12,217,30,101,173,53,70,155, + 216,88,59,36,34,247,254,2,215,162,130,23,152,77,245,29,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> TextEditor = { //size: 574 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,9,22,18,55,41,59,82,2,72,0,0,1,203,73, + 68,65,84,56,203,165,147,77,104,19,65,20,199,127,51,221,163,72,22,34,45,226,177,224,41,160,88,43,1,15,130,21, + 132,120,236,69,208,182,39,175,165,23,21,60,138,32,197,32,245,34,126,128,154,22,138,49,189,91,26,17,77,92,16,237, + 193,98,211,141,27,76,253,192,213,108,235,16,21,90,145,205,120,48,67,179,109,106,43,190,203,255,13,204,251,207,111,102, + 222,131,255,12,97,146,226,93,250,128,25,224,216,86,122,120,136,188,169,147,0,151,71,47,157,1,102,14,30,119,216,142, + 182,18,88,77,189,1,240,237,249,57,182,163,87,79,74,221,172,59,45,141,211,222,84,64,89,21,88,221,147,167,172,10, + 252,232,122,216,86,95,76,75,6,199,138,28,233,31,6,24,55,4,196,227,113,196,137,165,63,139,125,77,101,77,125,223, + 39,127,79,50,116,237,25,31,158,140,51,183,16,132,64,135,213,122,31,165,20,245,122,125,195,75,7,65,128,155,73,173, + 21,123,203,124,45,77,117,0,61,17,3,219,182,177,109,59,82,236,251,62,110,38,197,224,88,145,197,199,25,94,149,151, + 81,165,28,64,207,200,100,99,246,175,4,230,228,129,116,129,197,124,134,185,183,10,85,202,241,115,255,69,206,159,189,48, + 11,136,77,9,180,214,20,210,189,12,92,121,138,55,125,135,202,231,239,168,249,7,188,239,26,166,179,205,55,70,8,180, + 214,100,179,89,126,201,67,204,59,14,239,62,213,89,122,61,5,189,105,118,173,172,0,218,52,161,110,75,16,134,33,187, + 63,166,121,244,165,155,251,185,28,221,242,37,59,251,110,145,76,38,113,93,151,55,149,5,140,139,92,79,80,173,86,241, + 60,143,145,201,6,71,59,43,172,238,72,16,30,24,37,145,72,96,89,22,150,101,69,186,120,3,65,44,22,67,107,77, + 173,86,67,107,141,148,18,173,53,66,8,132,16,173,219,27,17,3,165,20,142,227,108,58,117,198,100,125,24,131,137,155, + 183,175,159,250,135,41,158,48,201,111,90,157,232,152,121,9,252,18,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Device { +const nall::vector<uint8_t> Clock = { //size: 897 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,9,15,8,58,5,128,132,46,85,0,0,3,14,73, + 68,65,84,56,203,101,146,75,76,92,101,28,197,127,223,119,239,188,152,185,119,96,34,8,210,202,35,88,29,108,48,150, + 190,226,162,177,59,220,152,138,193,186,32,26,54,38,68,87,181,53,38,44,77,99,26,31,137,198,68,77,172,53,177,139, + 62,240,17,77,76,163,46,176,5,77,85,40,5,58,88,43,218,17,233,76,167,204,12,195,204,189,195,12,119,190,207,141, + 109,40,158,228,236,206,57,255,71,142,96,19,142,28,24,25,210,146,23,5,226,97,148,14,8,67,122,90,138,27,85,181, + 126,230,157,207,94,127,101,179,94,108,48,246,104,248,116,247,190,71,123,182,247,198,9,71,194,8,1,90,67,113,181,196, + 204,84,130,75,151,230,211,131,195,231,142,245,60,146,10,34,117,146,80,242,180,185,193,124,97,112,120,192,46,27,138,85, + 159,131,40,190,118,103,138,221,113,140,120,224,65,26,59,83,205,141,205,149,55,61,189,115,213,208,191,172,8,183,93,73, + 0,141,62,62,56,60,96,223,88,43,208,254,80,136,104,245,237,187,214,180,235,45,182,110,107,161,119,111,142,104,195,46, + 131,192,187,13,200,167,163,192,14,121,228,192,200,208,238,125,59,118,150,180,71,91,87,35,45,91,226,155,207,68,74,137, + 16,2,51,16,67,178,68,165,116,2,167,52,19,4,253,131,4,6,182,247,198,89,46,103,105,109,109,166,144,255,135,248, + 227,167,72,103,125,119,63,75,8,42,94,31,158,232,39,149,172,114,242,195,7,170,120,242,156,169,209,123,194,145,48,150, + 23,66,41,133,207,103,81,118,139,132,234,44,70,94,218,134,223,222,203,115,109,57,108,219,66,200,24,210,127,16,195,187, + 201,194,212,199,209,161,23,250,131,18,168,23,2,154,154,26,200,23,242,40,165,168,41,141,227,20,57,250,222,239,68,98, + 221,76,76,76,160,148,66,107,133,97,26,152,134,4,165,5,208,101,2,43,90,19,43,187,85,58,58,218,169,84,214,80, + 74,81,44,22,233,238,238,230,229,195,175,114,237,218,85,106,181,26,82,74,180,82,104,13,72,52,176,32,5,226,162,83, + 114,88,252,59,141,82,10,207,243,240,60,143,67,135,14,147,72,36,200,100,210,88,150,69,173,86,195,178,108,202,110,25, + 167,228,128,207,112,63,57,253,150,35,129,179,115,147,243,216,134,133,83,114,241,249,252,140,141,141,49,58,58,74,42,181, + 116,39,48,28,142,160,53,44,95,207,50,55,57,79,133,218,12,128,124,227,203,163,39,126,62,63,53,217,24,182,25,255, + 254,87,180,214,244,245,61,65,58,157,98,173,82,65,107,77,32,16,192,52,77,242,153,28,238,178,203,197,31,167,171,95, + 77,156,121,6,192,0,232,188,183,107,110,97,54,249,236,254,253,143,249,255,252,99,145,92,33,207,253,109,91,8,6,130, + 4,131,33,252,190,0,55,255,202,144,191,190,194,201,15,206,234,217,165,217,247,167,230,127,154,3,178,6,192,76,114,58, + 239,55,253,87,150,174,102,246,52,53,196,162,109,45,173,120,69,143,74,126,141,114,182,204,173,228,45,46,143,207,242,245, + 231,223,174,143,255,118,225,248,249,233,239,190,1,210,64,78,108,232,74,61,208,249,228,174,254,231,239,187,103,235,83,117, + 254,186,22,41,164,169,209,202,93,119,139,233,66,58,241,197,248,169,143,128,20,112,5,88,4,180,224,255,136,252,23,118, + 155,26,40,3,171,64,22,40,0,234,182,248,95,201,36,100,6,22,194,54,223,0,0,0,0,73,69,78,68,174,66,96, + 130, +}; +const nall::vector<uint8_t> Display = { //size: 662 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,19,73,68,65,84,56,141,165,147,203,106,20,65,20,134,191,83,85, + 115,109,72,50,32,6,98,18,35,38,11,183,222,54,186,112,99,6,29,240,25,124,4,55,130,184,81,80,4,241,49,124, + 131,108,92,8,9,17,34,226,222,96,188,129,38,16,131,97,72,156,233,234,233,158,238,58,46,58,17,19,3,65,60,155, + 42,170,234,255,207,119,206,161,164,221,110,243,63,225,58,157,206,29,17,121,168,170,181,127,17,138,136,87,213,187,78,85, + 31,183,111,92,143,154,141,38,121,174,199,103,116,130,181,134,110,183,91,95,90,124,245,196,169,106,109,116,116,132,249,155, + 207,73,233,3,160,122,132,209,222,81,77,34,94,190,184,205,200,232,40,64,195,237,223,167,161,207,133,171,99,136,200,30, + 34,128,148,171,0,90,238,223,44,111,179,250,238,61,83,83,147,37,81,154,166,128,160,226,136,211,80,10,20,68,228,128, + 73,54,204,217,238,254,4,28,103,103,103,49,18,74,3,239,61,33,20,24,99,24,228,82,102,43,155,4,148,194,205,31, + 59,196,62,5,160,97,90,124,88,91,99,122,122,146,36,73,112,73,146,80,20,1,140,35,201,203,108,138,32,64,156,164, + 236,244,18,84,29,149,250,94,181,137,101,122,230,52,21,103,240,222,227,226,56,70,131,98,76,133,65,112,251,0,36,233, + 144,108,104,112,181,232,224,248,172,229,243,199,79,204,205,205,210,239,247,75,2,69,17,107,73,131,3,5,69,81,107,169, + 216,35,134,97,135,76,156,154,192,24,202,18,188,247,0,24,227,176,213,232,111,197,161,24,154,62,69,81,160,8,113,28, + 227,66,40,187,217,106,56,178,205,193,177,6,81,213,33,70,49,34,37,129,115,174,183,254,109,163,245,236,209,249,99,197, + 191,41,210,156,245,245,13,128,29,233,116,58,183,106,181,218,3,17,141,64,12,48,83,169,56,87,169,86,197,26,3,64, + 17,2,89,150,105,62,204,135,192,87,208,160,202,174,247,201,125,151,231,249,66,158,231,11,0,170,26,181,78,140,189,157, + 111,183,207,93,186,120,153,241,147,227,168,42,91,91,223,89,121,189,162,75,203,75,171,73,111,112,37,203,50,191,79,35, + 135,191,179,49,102,164,222,172,63,109,70,205,107,214,154,51,128,22,161,248,50,240,131,197,222,110,255,158,136,196,127,190, + 255,5,119,143,242,70,185,147,13,30,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Joypad = { //size: 812 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,172,0,77,0,0,52,214,215,123,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,7,15,10,39,178,201,163,153,0,0,0,140,116, + 69,88,116,67,111,109,109,101,110,116,0,77,101,110,117,45,115,105,122,101,100,32,105,99,111,110,10,61,61,61,61,61, + 61,61,61,61,61,10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83, + 116,101,105,110,101,114,44,32,10,104,116,116,112,58,47,47,106,105,109,109,97,99,46,109,117,115,105,99,104,97,108,108, + 46,99,122,10,10,99,114,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,71,73,77,80,44,10,104,116,116,112, + 58,47,47,119,119,119,46,103,105,109,112,46,111,114,103,103,138,199,71,0,0,2,33,73,68,65,84,56,203,149,146,203, + 107,83,65,20,198,127,147,220,228,38,214,210,164,177,54,245,209,135,160,184,73,176,20,255,130,130,123,17,138,136,130,168, + 32,88,8,193,133,173,15,180,221,136,46,68,10,10,130,72,22,93,213,186,19,68,208,133,187,34,84,179,19,68,20,42, + 21,53,53,183,105,244,230,117,111,230,184,184,105,154,66,178,232,129,3,195,240,205,55,191,249,230,40,58,212,199,179,132, + 255,170,221,51,97,41,95,2,124,235,42,178,96,80,191,58,62,95,40,181,234,84,167,195,117,124,223,250,14,237,141,27, + 225,16,162,53,142,93,102,237,251,186,181,161,122,6,79,204,231,237,77,173,175,157,129,70,165,99,67,177,184,175,43,140, + 235,247,99,21,107,216,174,143,129,35,253,189,192,253,86,173,175,195,11,82,129,93,97,252,166,137,17,12,16,12,26,252, + 94,181,136,14,198,137,200,198,153,86,161,145,74,79,206,0,119,90,55,203,86,6,167,84,193,202,217,116,71,187,40,230, + 255,225,214,28,220,170,67,69,153,209,84,250,178,52,164,179,42,149,158,148,185,135,143,182,93,255,235,229,61,170,203,115, + 88,185,34,249,181,18,162,96,223,240,30,162,177,46,234,135,47,112,240,212,109,108,219,230,198,173,41,12,0,173,53,133, + 66,97,11,235,248,57,114,111,30,211,63,212,199,200,104,15,134,25,160,248,243,15,185,85,135,3,231,47,98,89,22,65, + 51,184,149,129,104,241,90,188,86,129,16,3,215,151,88,212,167,249,186,244,133,207,239,62,241,170,52,206,254,155,239,81, + 129,16,34,2,141,71,120,4,162,209,34,32,226,125,172,0,134,137,27,234,101,228,193,42,43,43,43,228,223,190,134,128, + 137,214,26,192,51,105,18,136,96,189,184,198,143,233,97,214,23,167,26,68,26,183,238,182,36,35,72,93,35,186,209,13, + 3,163,153,252,242,2,82,43,81,90,94,160,251,228,93,0,142,37,71,121,250,236,73,115,93,23,221,68,111,230,181,25, + 98,104,108,130,202,135,231,132,198,38,208,90,163,68,72,36,146,36,18,73,68,20,74,137,135,223,48,216,70,96,154,38, + 71,175,100,128,76,219,169,178,109,111,114,203,229,50,0,149,74,101,59,65,54,155,197,117,93,118,82,74,169,45,131,72, + 36,210,68,2,168,86,171,0,212,106,181,142,6,142,227,120,70,237,70,121,7,53,251,31,168,192,0,159,97,230,172,204, + 0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Keyboard = { //size: 587 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,1,200,73,68,65,84,56,141,181,146,177,107,83,81,20,198,127,247,222, + 115,95,95,8,73,159,136,180,209,38,177,21,7,165,21,26,16,204,228,34,102,8,8,34,212,168,127,72,193,191,160,131, + 45,174,29,178,184,180,116,17,212,12,25,4,23,137,32,168,56,85,227,146,162,85,112,145,212,190,151,52,125,185,14,109, + 53,29,164,193,226,7,151,115,46,231,124,223,189,231,240,169,82,169,196,113,160,15,146,122,189,174,142,37,48,191,48,159, + 30,134,80,169,84,252,193,187,58,24,161,88,156,157,242,60,223,3,239,187,136,216,100,210,88,99,196,199,152,139,190,245, + 175,2,87,28,76,3,30,74,189,72,38,82,229,106,181,26,203,31,45,127,195,57,123,201,250,186,108,69,143,59,103,50, + 32,99,86,108,216,239,179,174,148,187,15,242,174,213,106,253,204,159,157,104,110,111,255,40,0,175,127,11,52,26,141,93, + 224,205,254,249,219,247,131,252,228,196,50,142,157,173,173,206,251,67,59,56,10,115,119,230,174,163,226,183,202,169,200,104, + 175,80,171,213,186,0,114,20,113,239,229,91,151,193,61,82,112,111,101,101,237,249,96,77,45,173,45,37,78,118,131,166, + 159,24,57,163,181,70,27,141,86,123,209,104,131,214,10,173,13,206,57,0,246,123,94,61,88,120,88,4,144,157,86,120, + 45,83,184,112,106,102,122,6,107,61,68,4,43,22,99,4,173,13,56,71,223,245,137,162,136,48,10,49,90,211,104,188, + 156,173,84,110,158,95,93,125,220,20,17,239,118,144,62,225,133,97,135,205,175,159,72,37,211,160,0,20,74,41,218,237, + 54,249,92,142,56,142,249,178,249,153,108,54,79,106,52,144,245,15,31,111,0,139,98,180,46,7,65,0,206,145,61,157, + 99,183,31,31,154,127,52,157,166,215,235,1,138,169,201,115,116,186,93,50,99,227,102,196,179,119,129,69,137,227,120,227, + 233,179,39,90,169,225,157,236,156,3,199,55,24,112,226,191,98,104,31,252,55,129,95,252,113,137,228,164,151,154,151,0, + 0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Microphone = { //size: 703 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,234,0,234,0,234,127,141,58,17,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,11,3,22,42,33,208,235,186,119,0,0,2,76,73, + 68,65,84,56,203,125,147,95,72,83,97,24,198,127,147,205,182,83,179,72,234,44,200,180,11,239,148,4,217,148,88,151, + 94,118,37,178,65,116,209,77,105,119,65,212,141,12,138,254,152,55,117,227,134,32,212,244,106,30,70,187,216,31,208,139, + 188,137,8,141,109,72,77,93,218,137,153,108,122,108,24,56,143,121,56,235,34,119,218,104,250,192,199,247,247,121,222,231, + 123,191,247,51,113,136,1,79,255,35,192,199,209,152,3,178,82,40,124,187,122,209,84,33,187,156,46,95,111,239,85,186, + 174,116,213,176,138,197,34,0,91,202,22,35,47,158,1,220,147,66,225,87,149,253,134,195,222,231,118,95,163,245,82,43, + 197,98,209,104,138,162,160,170,42,11,11,243,172,173,174,242,224,254,67,128,151,213,1,204,149,129,67,188,128,215,235,5, + 32,22,139,17,143,199,25,27,27,51,14,90,173,39,176,9,86,132,147,2,245,4,30,139,162,232,243,251,253,104,154,134, + 162,40,184,221,110,186,187,187,255,94,126,238,29,0,171,107,95,145,191,203,117,5,124,51,51,51,140,142,142,26,14,162, + 209,40,129,64,160,198,129,165,209,66,211,105,59,117,147,24,124,61,229,91,89,89,65,211,52,44,22,11,130,32,96,54, + 155,89,94,94,70,150,191,241,99,99,131,66,33,207,230,102,129,125,245,55,246,38,251,155,233,144,116,235,72,7,137,68, + 130,137,137,137,154,104,103,206,158,198,227,241,146,74,37,153,159,255,116,3,48,4,158,244,245,245,13,183,183,183,163,235, + 58,249,124,158,142,142,14,130,193,32,187,187,187,200,178,76,38,147,225,195,199,247,164,82,73,50,95,150,48,97,106,168, + 206,193,240,236,236,172,225,32,18,137,144,72,36,24,31,31,199,106,181,26,14,218,46,183,145,74,166,41,151,203,216,237, + 167,226,53,207,216,211,211,131,36,73,0,100,179,89,68,81,100,114,114,210,32,71,99,81,28,162,131,240,91,9,193,38, + 80,218,43,93,175,17,40,108,230,17,207,59,72,167,211,0,168,170,202,226,226,34,154,166,161,235,58,7,218,1,219,63, + 21,0,154,155,155,41,173,151,106,11,201,31,240,51,120,103,136,206,206,78,116,93,167,92,46,163,235,58,154,166,177,243, + 107,135,204,210,103,82,169,36,192,158,211,233,178,229,214,115,255,4,164,80,216,52,116,119,112,255,249,200,211,70,142,199, + 18,224,0,108,255,149,178,178,189,53,221,114,177,133,220,122,14,41,20,190,121,148,194,128,167,127,170,238,95,0,34,78, + 167,235,92,197,218,49,136,84,79,254,0,227,216,1,121,79,52,137,54,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Mouse = { //size: 720 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,8,13,24,4,51,189,102,0,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,2,28, + 73,68,65,84,56,203,141,144,205,75,84,81,24,198,127,247,220,201,171,115,239,117,162,146,92,40,217,31,208,166,85,208, + 252,5,17,148,182,9,114,178,77,66,187,208,106,22,5,35,76,16,238,91,180,107,51,109,98,80,35,218,181,9,68,87, + 34,81,249,17,129,76,14,51,166,57,141,227,215,124,220,243,158,22,126,52,234,72,190,155,195,251,156,231,252,206,195,99, + 113,104,210,233,116,39,48,80,46,151,111,27,99,60,192,120,190,251,170,251,102,207,147,122,223,216,187,209,235,91,155,91, + 253,138,163,115,105,187,188,29,243,124,247,123,44,22,243,61,223,237,43,254,89,187,150,74,165,150,82,111,82,217,209,177, + 145,27,187,190,23,97,55,60,109,29,126,157,76,38,95,182,182,250,189,197,226,218,38,240,49,145,72,244,213,165,187,80, + 171,85,223,27,216,106,110,118,230,122,186,111,221,179,158,39,135,18,74,169,33,108,11,165,20,149,237,128,104,52,74,46, + 159,101,97,33,67,147,99,163,131,0,9,164,168,148,250,240,244,89,162,183,254,195,80,40,20,26,186,223,255,192,216,182, + 109,133,195,97,134,135,135,209,90,227,52,181,96,97,49,240,240,49,165,82,137,194,234,239,200,200,72,250,14,112,0,160, + 0,42,213,170,245,115,113,113,95,204,229,114,84,42,149,127,123,62,143,215,26,177,26,244,197,145,18,227,241,56,249,124, + 158,108,54,75,60,30,231,127,19,170,95,86,86,86,104,107,107,99,112,112,240,128,118,98,192,106,161,192,106,161,128,239, + 251,116,118,116,48,51,59,123,178,4,27,165,117,206,157,57,187,47,214,130,26,203,191,150,15,104,27,165,245,227,1,158, + 231,238,68,181,192,194,194,24,65,139,32,70,16,173,209,34,180,159,111,231,184,18,167,196,24,180,209,136,104,180,14,208, + 162,17,17,68,11,34,6,35,178,231,159,106,4,152,213,90,99,43,155,32,16,180,214,232,96,23,38,130,136,208,116,202, + 217,243,79,55,2,124,154,159,159,195,243,60,90,90,154,177,148,66,139,160,245,78,124,215,117,137,156,142,48,51,243,13, + 224,71,163,14,222,126,253,242,185,207,113,156,104,87,215,69,60,207,195,0,24,195,206,97,200,100,22,88,90,202,1,188, + 110,4,168,85,171,213,187,147,19,227,143,38,39,198,47,3,87,26,116,149,1,174,2,107,135,47,254,2,161,171,0,195, + 167,31,206,166,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Network = { //size: 408 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,18,0, + 0,11,18,1,210,221,126,252,0,0,0,7,116,73,77,69,7,214,2,16,22,3,20,11,54,9,17,0,0,1,37,73, + 68,65,84,56,203,157,146,61,75,195,80,20,134,159,155,92,242,63,164,46,221,2,226,238,32,226,38,82,255,131,17,10, + 34,56,74,196,42,232,228,80,63,210,95,32,4,99,5,255,134,131,110,46,130,56,152,22,170,129,214,170,225,82,18,7, + 13,26,242,97,240,29,207,121,207,203,121,206,189,130,2,181,246,182,61,160,65,185,58,178,164,217,88,152,95,164,86,55, + 115,155,131,167,7,188,174,107,149,5,80,171,155,44,55,47,48,140,180,77,169,9,87,206,10,0,165,1,66,8,12,67, + 98,206,78,3,49,32,0,184,189,190,39,138,190,60,178,140,245,180,189,207,220,20,168,151,30,143,98,134,247,15,197,235, + 56,76,121,100,69,86,122,207,111,223,21,29,128,56,142,127,16,170,176,70,163,97,170,254,123,131,74,172,238,225,82,102, + 179,204,17,117,93,163,63,24,231,178,58,71,7,121,132,118,42,224,230,174,15,177,200,101,93,91,109,166,38,53,77,227, + 196,105,183,100,98,82,106,130,49,28,101,110,144,40,8,130,220,35,203,132,231,242,184,81,248,10,0,238,249,89,97,64, + 199,235,186,214,31,127,222,182,183,118,118,139,2,172,141,245,77,194,48,204,157,76,88,129,194,0,124,223,231,191,146,101, + 124,85,244,9,241,192,132,130,214,14,135,66,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Optical = { //size: 720 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,5,17,7,21,115,1,202,165,0,0,0,140,116, + 69,88,116,67,111,109,109,101,110,116,0,77,101,110,117,45,115,105,122,101,100,32,105,99,111,110,10,61,61,61,61,61, + 61,61,61,61,61,10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83, + 116,101,105,110,101,114,44,32,10,104,116,116,112,58,47,47,106,105,109,109,97,99,46,109,117,115,105,99,104,97,108,108, + 46,99,122,10,10,99,114,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,71,73,77,80,44,10,104,116,116,112, + 58,47,47,119,119,119,46,103,105,109,112,46,111,114,103,103,138,199,71,0,0,1,197,73,68,65,84,56,203,157,146,77, + 107,19,81,20,134,159,51,153,102,22,195,224,100,96,22,83,157,44,252,248,3,69,212,141,40,110,10,34,234,90,93,184, + 149,72,200,63,208,130,80,68,132,88,104,69,65,17,17,68,255,129,74,214,217,104,73,180,38,168,203,102,25,33,208,132, + 4,146,185,199,197,164,205,4,233,34,61,171,195,185,231,62,239,123,238,61,82,174,148,30,2,15,56,90,172,81,174,148, + 244,40,209,239,247,181,92,41,169,13,96,140,161,215,235,45,36,157,119,242,0,216,0,106,20,53,10,178,0,65,153,1, + 140,26,140,42,232,20,50,61,76,211,255,10,233,125,213,140,3,85,140,73,0,65,208,131,78,157,245,131,128,152,140,129, + 44,96,223,133,0,70,1,145,153,160,234,1,216,72,150,152,29,193,24,52,209,84,83,4,85,69,84,81,217,87,19,68, + 20,213,67,70,112,28,135,229,227,203,135,190,215,96,48,0,96,56,28,2,48,26,141,230,29,52,26,13,198,227,241,66, + 223,232,121,94,10,48,137,33,159,207,243,230,237,171,133,0,151,46,94,73,1,98,9,237,118,11,128,167,79,170,76,38, + 19,70,163,33,221,191,93,154,205,6,182,189,196,141,235,55,169,213,106,4,65,64,20,69,172,63,126,68,16,4,83,128, + 8,190,239,19,134,33,219,219,95,89,89,57,139,239,23,240,253,2,167,79,157,1,160,94,175,227,186,46,97,24,242,249, + 203,39,28,199,193,117,93,0,114,231,47,156,147,223,127,126,93,222,219,235,179,243,243,7,190,239,83,140,139,0,116,58, + 29,186,221,46,158,231,17,69,17,31,62,190,167,213,222,33,73,18,154,223,27,136,200,218,220,242,150,238,223,187,150,179, + 173,103,241,137,248,228,234,234,85,138,113,140,101,229,216,237,236,154,23,47,183,44,160,5,172,111,84,55,223,101,246,139, + 108,110,221,190,115,107,169,16,28,123,110,89,214,221,185,213,87,125,45,34,91,27,213,205,111,217,250,63,189,144,236,196, + 0,156,143,39,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Printer = { //size: 481 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,17,0, + 0,11,17,1,127,100,95,145,0,0,0,7,116,73,77,69,7,213,8,18,15,53,11,122,248,175,234,0,0,1,110,73, + 68,65,84,56,203,165,147,205,78,34,81,16,133,191,91,176,224,33,122,235,204,138,16,34,179,49,242,24,227,248,48,218, + 254,60,129,154,209,103,16,120,2,122,199,154,37,59,113,167,38,36,205,95,104,18,187,105,238,45,87,32,61,252,77,244, + 38,149,155,186,73,157,58,85,231,92,248,230,49,171,73,189,81,187,2,252,255,168,187,62,249,253,231,98,237,181,222,168, + 105,146,36,59,35,142,99,173,55,106,186,168,201,111,130,111,183,219,91,91,87,42,149,76,190,17,160,88,44,126,206,104, + 76,230,86,213,221,0,206,57,58,157,14,0,34,178,6,84,46,151,247,51,240,60,15,17,193,24,179,22,123,25,168,42, + 173,86,107,217,81,68,168,86,171,187,101,60,247,207,174,0,191,80,40,240,227,224,39,206,185,12,253,213,241,140,49,116, + 159,159,136,227,24,224,122,193,192,191,240,47,177,214,146,166,233,94,19,76,38,199,136,8,247,15,127,125,89,93,82,183, + 219,37,73,18,130,32,64,85,9,195,144,209,104,196,96,48,96,56,28,210,239,247,233,245,122,52,155,77,222,94,95,178, + 59,136,162,136,248,253,157,241,120,76,169,84,34,12,67,0,210,52,93,82,7,176,214,50,232,135,196,201,44,11,32,34, + 76,162,136,32,104,50,157,78,1,152,207,231,136,49,56,103,153,91,139,72,142,124,46,199,209,113,117,179,10,214,90,14, + 43,191,254,49,140,226,156,98,173,69,68,150,242,46,150,188,4,152,205,102,120,158,183,213,113,11,21,68,4,85,197,57, + 151,1,120,188,189,187,57,253,194,111,126,252,0,186,104,203,229,25,65,188,29,0,0,0,0,73,69,78,68,174,66,96, + 130, +}; +const nall::vector<uint8_t> Speaker = { //size: 592 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,1,226,73,68,65,84,56,141, + 165,147,191,79,83,81,20,199,63,231,246,245,165,68,168,3,193,201,63,64,99,66,4,139,128,113,100,241,71,88,40,88, + 162,46,36,242,106,58,233,0,127,132,49,93,173,12,13,137,160,169,105,2,196,133,196,168,131,131,137,16,23,69,172,147, + 58,176,184,152,247,76,244,93,222,61,14,198,218,22,140,65,191,227,57,159,156,123,190,223,123,175,168,42,255,35,243,167, + 70,126,58,159,11,130,32,253,79,3,10,133,137,193,20,242,56,142,227,212,129,7,20,10,19,131,105,63,243,84,85,179, + 173,245,161,224,94,112,122,118,121,172,147,247,46,77,79,134,64,198,243,188,175,168,222,73,251,153,235,51,51,51,217,202, + 221,74,210,10,58,167,239,141,104,53,23,60,236,223,168,76,126,105,110,32,72,166,124,187,236,205,207,205,31,86,152,43, + 149,74,217,209,145,51,120,158,7,64,110,118,169,56,114,109,233,232,230,194,213,39,10,235,104,124,179,205,130,162,244,245, + 29,225,248,177,19,168,170,12,156,60,69,38,211,133,136,0,32,66,111,34,148,1,68,101,69,144,209,61,25,188,217,122, + 205,187,198,91,0,26,141,109,182,183,183,176,214,2,144,114,44,2,99,34,136,26,247,10,116,72,4,105,102,0,16,134, + 97,115,101,187,107,81,126,191,141,93,163,137,168,164,0,172,209,196,79,164,45,120,3,16,70,33,97,20,162,170,216,216, + 98,99,219,4,4,83,64,244,153,42,234,37,169,1,96,83,91,78,48,0,81,20,177,179,179,3,192,135,79,31,137,109, + 220,26,191,167,164,111,252,132,245,130,194,139,182,107,84,85,173,215,235,137,136,88,35,102,113,117,117,229,242,248,197,241, + 238,95,192,203,133,43,183,0,134,139,247,71,129,60,98,250,59,45,244,168,106,183,115,174,123,121,233,65,209,126,79,206, + 173,61,90,139,156,115,109,94,93,226,134,65,139,27,149,233,207,173,117,217,239,51,77,77,77,157,197,184,245,67,93,61, + 189,213,106,245,219,30,160,51,196,78,213,106,181,231,56,115,222,247,253,100,191,254,95,55,56,136,126,0,228,148,200,42, + 201,231,90,24,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Storage = { //size: 603 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,5,15,53,8,235,207,124,119,0,0,0,140,116, + 69,88,116,67,111,109,109,101,110,116,0,77,101,110,117,45,115,105,122,101,100,32,105,99,111,110,10,61,61,61,61,61, + 61,61,61,61,61,10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83, + 116,101,105,110,101,114,44,32,10,104,116,116,112,58,47,47,106,105,109,109,97,99,46,109,117,115,105,99,104,97,108,108, + 46,99,122,10,10,99,114,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,71,73,77,80,44,10,104,116,116,112, + 58,47,47,119,119,119,46,103,105,109,112,46,111,114,103,103,138,199,71,0,0,1,80,73,68,65,84,56,203,165,147,77, + 110,194,48,16,133,191,160,64,164,32,203,201,38,106,36,246,112,55,36,196,13,218,222,144,21,39,64,44,216,65,108,16, + 249,153,233,34,224,40,237,162,85,153,133,237,25,207,123,126,51,182,225,69,139,54,219,245,7,240,254,79,252,39,155,237, + 90,255,99,206,57,221,108,215,26,3,136,8,231,243,25,85,133,40,2,213,177,76,64,159,67,4,160,204,102,51,0,98, + 0,21,165,19,233,179,69,6,0,16,17,33,170,125,140,168,199,247,206,64,32,42,72,39,68,15,144,2,168,62,0,202, + 83,24,170,61,177,208,171,13,10,84,201,243,140,211,233,244,167,206,101,89,70,215,117,0,76,158,65,231,28,69,81,252, + 10,46,138,130,186,174,131,31,154,232,189,15,9,0,215,235,149,170,170,0,48,198,144,166,41,147,201,132,203,229,130,247, + 30,99,204,64,144,36,9,139,197,98,116,146,181,22,107,45,0,222,123,234,186,230,118,187,253,80,20,3,236,118,59,154, + 166,25,109,180,109,75,28,199,97,253,221,242,60,31,247,160,109,91,246,251,61,199,227,145,170,170,80,85,84,149,36,73, + 56,28,14,24,99,194,236,156,195,57,55,16,168,42,34,194,124,158,50,157,78,195,35,1,104,154,6,149,158,76,69,250, + 220,199,13,132,18,178,44,195,90,75,89,150,0,220,239,119,128,208,237,229,106,137,136,176,92,173,16,17,222,202,50,148, + 252,250,103,122,213,190,0,151,85,237,38,182,108,181,11,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Edit { +const nall::vector<uint8_t> Clear = { //size: 773 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,151,73,68,65,84,56,141, + 149,146,75,104,148,103,20,134,159,239,155,153,232,76,18,155,219,72,66,147,72,188,213,168,20,43,38,139,10,210,130,139, + 74,75,118,130,151,133,139,209,141,130,34,252,11,5,93,24,23,6,28,144,82,16,132,142,198,133,96,75,117,161,11,233, + 141,22,49,45,180,105,52,49,138,49,141,154,113,70,73,147,201,101,204,63,243,79,254,255,251,142,43,69,99,33,248,172, + 207,251,112,206,203,81,71,190,96,115,56,196,5,17,162,198,178,247,212,13,249,145,247,64,135,52,223,175,109,142,173,218, + 176,162,188,49,164,185,122,116,155,218,250,94,2,96,113,69,84,179,180,42,194,199,45,177,88,72,115,246,244,126,165,83, + 73,213,153,74,170,218,5,5,86,232,28,124,82,116,125,35,212,215,148,17,93,172,234,171,26,233,5,142,3,75,23,20, + 136,240,141,235,153,139,183,6,243,238,76,201,167,169,157,202,149,173,27,55,196,227,77,47,128,186,133,4,74,68,0,232, + 218,167,78,196,87,114,252,147,182,207,85,115,75,59,61,167,187,189,233,127,198,114,236,84,147,198,200,37,17,206,39,28, + 25,255,95,65,42,169,118,105,173,190,253,116,115,71,180,174,174,129,127,191,254,155,167,87,31,178,254,236,118,106,215,85, + 145,30,237,247,238,223,253,67,140,245,190,51,70,142,37,28,201,206,23,236,209,154,100,83,125,107,57,151,36,106,38,93, + 182,116,111,101,81,141,6,21,133,80,53,126,80,206,189,193,95,253,129,254,223,13,226,255,96,12,41,224,230,235,19,82, + 73,181,40,114,142,59,21,205,181,171,58,46,31,14,105,253,28,66,13,96,198,192,100,177,65,30,207,182,224,205,213,144, + 201,12,200,227,145,1,119,106,50,91,212,175,86,73,56,82,242,119,211,85,123,176,177,164,35,101,96,103,33,24,1,147, + 5,243,31,94,225,25,179,185,235,204,140,157,35,94,141,218,212,254,85,133,86,74,194,111,53,82,193,207,217,76,90,91, + 171,80,254,8,34,62,254,156,135,87,154,165,88,152,161,80,152,70,68,208,225,74,210,79,122,3,148,252,166,223,204,39, + 28,121,230,207,77,143,164,211,119,153,113,99,76,76,140,146,203,165,153,204,101,112,221,41,68,132,88,245,54,10,69,205, + 208,131,254,146,49,56,111,9,0,2,35,135,250,122,127,41,250,172,198,117,61,138,197,60,214,6,232,112,13,149,241,29, + 228,221,152,220,186,121,37,111,76,240,101,194,145,204,235,18,223,164,251,140,234,89,253,81,123,219,242,21,173,17,47,255, + 39,101,177,53,232,200,50,30,13,247,4,67,67,125,227,214,242,89,194,145,135,0,225,119,210,128,49,116,12,61,248,235, + 118,229,146,134,15,63,168,106,211,163,163,247,252,225,225,159,2,107,188,235,214,114,32,225,200,196,59,159,56,159,84,82, + 45,83,138,62,165,16,224,154,181,156,76,56,242,120,254,220,75,126,7,67,8,40,132,18,218,0,0,0,0,73,69,78, + 68,174,66,96,130, +}; +const nall::vector<uint8_t> Copy = { //size: 498 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,26,20,8,47,131,20,52,155,0,0,1,127,73, + 68,65,84,56,203,149,147,75,75,2,81,24,134,223,35,51,99,218,128,253,10,207,8,221,22,253,143,8,90,182,136,160, + 117,23,240,66,182,176,69,145,118,219,68,68,68,27,177,54,5,254,4,49,179,54,129,101,48,163,191,160,154,48,5,55, + 205,237,180,105,116,70,71,177,111,245,157,195,121,31,222,247,227,59,228,232,36,51,175,235,250,44,70,40,193,207,189,109, + 174,197,239,156,119,156,97,24,211,241,232,214,40,122,164,15,246,38,1,184,1,118,211,106,53,193,24,235,19,17,66,0, + 0,161,208,132,39,148,115,30,106,181,26,94,171,149,133,198,119,99,102,144,139,253,204,110,202,238,121,158,191,117,1,36, + 73,66,177,84,152,250,71,164,69,23,64,81,148,78,140,86,171,57,84,108,71,114,1,40,165,40,150,10,157,179,44,203, + 158,226,72,36,210,63,3,198,24,100,89,118,13,210,249,112,80,185,0,148,82,148,202,197,161,14,122,161,156,45,182,44, + 6,69,25,205,65,48,56,142,118,187,221,5,232,186,14,198,24,194,97,138,242,83,105,168,3,74,37,152,166,129,202,75, + 165,11,208,180,31,4,2,99,176,44,54,212,238,229,213,5,30,30,239,221,17,4,158,175,158,157,159,186,22,135,49,203, + 211,182,40,138,88,89,94,133,101,153,80,191,84,228,174,179,224,54,214,163,121,0,121,199,114,108,27,134,225,235,21,59, + 75,85,85,228,110,178,0,240,236,243,26,146,166,233,240,251,253,16,4,1,162,40,130,16,130,122,189,14,128,224,227,243, + 221,22,167,18,177,228,28,233,21,31,30,167,179,166,105,46,121,125,172,191,42,0,40,36,98,201,29,0,248,5,66,89, + 166,3,21,136,247,216,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Cut = { //size: 807 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,28,22,29,49,104,65,100,94,0,0,2,180,73, + 68,65,84,56,203,133,147,93,72,147,81,24,199,159,115,222,119,175,175,219,212,125,165,219,108,248,21,104,120,209,85,16, + 116,97,148,73,87,69,222,100,34,17,104,105,150,88,168,105,129,144,4,149,165,125,129,136,16,148,24,232,16,244,74,144, + 36,186,12,2,181,48,109,51,54,242,99,239,54,117,155,238,117,95,239,118,206,219,77,206,97,90,231,238,252,255,15,63, + 254,207,243,156,131,32,229,60,235,125,114,14,0,222,243,60,239,109,186,121,187,116,143,215,207,178,236,165,59,205,173,186, + 84,29,167,94,24,134,25,187,213,216,172,141,70,163,203,125,253,175,59,83,61,5,171,184,112,230,116,185,230,197,171,158, + 79,7,2,8,33,252,79,135,29,215,213,214,87,16,66,142,237,232,79,123,30,151,153,115,205,166,237,144,136,40,165,39, + 14,4,96,140,67,75,75,191,128,79,75,67,177,88,172,116,39,5,203,178,83,133,133,133,224,113,123,40,165,212,241,175, + 4,21,54,155,13,86,93,43,168,174,182,190,56,145,72,156,234,121,222,61,80,82,82,162,64,128,193,225,116,0,0,88, + 15,4,220,109,189,247,25,99,188,188,184,104,7,62,141,71,146,36,29,215,235,244,215,100,10,176,190,177,70,1,96,162, + 173,165,227,225,129,0,0,0,74,105,229,194,143,5,121,109,205,3,141,55,154,84,241,68,28,137,98,16,230,230,230,36, + 0,232,218,91,255,23,160,173,165,99,26,99,60,100,95,180,209,96,112,11,107,52,26,16,220,130,44,203,242,187,182,150, + 142,233,255,2,254,164,152,154,157,153,198,78,167,3,210,57,30,50,223,14,70,16,66,111,246,171,69,123,133,49,163,177, + 151,80,122,61,190,185,169,38,229,101,50,51,249,17,21,24,115,64,32,116,11,33,52,80,233,241,180,239,11,24,51,153, + 58,227,126,255,131,163,38,19,36,40,69,222,173,77,217,23,222,30,102,101,84,85,144,157,195,240,28,71,37,89,6,231, + 250,58,40,178,178,174,86,186,221,67,201,22,198,205,230,26,201,231,235,42,54,26,233,194,202,202,84,48,18,150,2,65, + 17,215,196,105,77,148,35,58,150,193,52,16,18,19,142,213,213,15,71,244,122,18,243,249,6,199,205,230,221,151,58,106, + 48,8,243,69,69,100,132,97,238,3,0,204,88,44,33,171,82,153,216,241,71,24,134,124,201,53,7,1,0,134,49,110, + 255,150,159,79,70,13,6,97,119,136,177,152,94,146,36,82,69,200,163,9,149,234,165,130,101,121,132,177,61,57,105,142, + 155,81,243,233,170,201,140,140,190,203,148,118,131,44,83,32,196,176,11,224,56,65,173,84,50,95,243,242,98,38,157,174, + 105,94,16,188,138,204,204,43,201,143,164,213,54,124,119,185,54,14,31,58,212,48,107,177,196,8,165,24,48,14,0,0, + 48,0,0,213,90,173,207,229,247,159,244,75,18,27,0,144,57,181,250,236,69,65,72,238,220,42,138,238,234,236,108,143, + 55,16,200,241,135,195,26,95,36,226,83,168,84,231,173,162,232,254,13,160,243,58,7,220,52,193,60,0,0,0,0,73, + 69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Delete = { //size: 680 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,141,0,142,0,139,33,244,163,126,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,214,6,19,15,29,9,72,179,203,198,0,0,0,15,116, + 69,88,116,67,111,109,109,101,110,116,0,105,100,32,108,111,103,111,134,198,119,185,0,0,2,26,73,68,65,84,56,203, + 165,144,191,79,19,113,24,198,159,251,165,119,45,180,165,215,214,90,42,20,162,12,180,14,110,110,80,40,131,236,154,56, + 105,106,127,128,17,77,77,220,26,233,96,82,7,147,66,212,52,197,70,5,55,39,117,49,49,182,22,249,3,100,48,186, + 181,139,169,24,19,56,174,114,87,238,122,119,14,114,23,67,137,81,124,167,247,251,230,121,62,239,251,124,9,236,213,226, + 253,194,59,89,150,198,241,23,197,113,182,218,141,185,76,20,0,104,115,40,203,210,248,108,250,26,20,69,177,132,134,97, + 116,153,13,195,192,147,229,178,181,136,14,77,231,231,1,228,0,29,146,36,65,16,132,46,163,249,102,24,6,36,73,2, + 0,66,211,121,3,64,142,6,144,203,102,46,160,190,186,4,81,20,209,108,54,15,52,3,0,69,81,32,8,2,162,40, + 34,155,73,225,78,225,121,206,138,240,177,209,130,32,8,104,52,26,127,140,96,106,135,199,246,34,152,195,186,28,68,252, + 110,165,75,76,16,7,33,130,86,103,1,34,103,99,56,76,89,128,216,25,254,255,0,159,190,136,255,100,28,13,58,126, + 69,12,157,203,215,64,96,236,80,235,13,172,90,95,52,119,253,170,113,249,82,92,125,84,46,41,147,147,83,204,218,218, + 123,38,26,157,208,170,213,10,25,139,77,105,181,90,149,154,136,198,244,183,149,55,228,226,194,3,170,43,2,203,178,170, + 218,81,183,121,175,71,107,181,126,16,67,161,225,94,93,55,228,193,193,33,90,211,116,201,225,112,248,105,134,217,228,56, + 155,237,247,35,72,179,225,121,126,135,36,201,215,54,155,13,35,167,70,32,237,238,40,3,3,39,116,151,203,41,187,251, + 220,109,0,136,132,195,71,189,94,175,218,5,40,44,220,43,1,208,34,225,211,23,125,30,223,177,141,111,95,125,0,100, + 158,247,144,36,73,212,123,29,61,157,254,254,32,88,150,211,237,118,187,84,44,62,76,239,191,32,113,51,115,139,95,94, + 121,172,3,248,188,181,181,41,240,110,222,239,114,58,233,93,165,205,172,175,127,56,9,0,43,207,158,58,211,169,217,182, + 218,81,206,239,7,148,75,75,69,248,253,199,143,36,19,233,209,100,34,221,167,40,10,94,190,122,209,67,81,116,224,74, + 60,73,164,146,51,68,32,16,152,185,61,159,253,206,178,220,134,9,248,9,228,204,195,8,165,247,44,101,0,0,0,0, + 73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Find = { //size: 617 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,240,0,240,0,239,52,6,103,27,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,5,16,15,5,37,253,173,47,0,0,1,246,73, + 68,65,84,56,203,157,146,77,107,19,81,24,133,159,59,201,36,77,154,102,134,74,82,10,10,181,93,104,26,69,20,193, + 133,184,20,10,85,119,226,38,191,192,111,169,244,31,136,182,36,65,68,20,116,89,119,85,16,197,77,168,59,65,236,162, + 84,40,164,137,86,171,150,80,53,141,205,71,39,77,50,51,215,69,72,73,66,82,170,103,119,15,239,61,239,225,188,71, + 60,121,250,120,49,247,39,119,140,61,64,85,213,231,19,183,38,47,182,144,211,209,187,150,220,35,238,77,223,145,237,162, + 78,41,235,92,62,191,185,235,118,77,211,59,242,78,33,196,206,35,153,76,118,28,10,133,66,93,133,119,28,180,15,102, + 50,25,102,95,204,2,144,152,75,0,208,180,107,119,7,223,190,175,146,74,167,57,122,106,140,109,197,139,105,43,184,100, + 133,212,252,107,38,110,223,140,196,162,247,159,53,254,40,237,14,52,93,35,149,78,115,232,228,24,159,11,94,6,7,2, + 140,28,8,82,18,62,180,209,113,252,154,62,115,237,198,149,227,93,29,36,230,18,12,135,79,179,82,112,115,233,204,16, + 190,30,21,211,182,81,29,10,239,150,37,193,35,227,54,75,111,22,0,1,160,116,10,75,122,3,12,13,232,88,182,100, + 219,52,169,212,44,202,85,139,126,159,155,95,101,181,37,9,69,74,137,148,118,75,48,110,183,11,132,160,92,181,168,214, + 36,155,91,53,220,170,131,253,253,30,164,16,45,93,112,2,182,105,154,45,78,108,99,131,53,163,138,223,163,162,247,185, + 176,45,137,223,227,228,211,70,129,125,61,150,157,107,114,174,212,43,234,66,211,116,52,77,231,194,185,243,164,23,222,18, + 236,19,124,249,153,39,155,43,145,55,42,124,92,89,167,84,174,144,91,122,229,44,21,139,63,26,2,34,26,159,154,177, + 44,43,210,124,13,195,48,112,56,84,78,156,141,176,188,86,100,203,84,24,236,149,172,47,190,100,248,224,8,0,31,230, + 223,167,30,62,120,116,88,116,107,216,213,235,151,167,2,129,224,100,51,231,235,245,17,30,13,243,59,155,173,247,101,245, + 43,130,127,68,44,30,149,13,145,255,18,0,148,88,60,106,1,148,13,131,191,6,140,246,211,127,51,231,46,0,0,0, + 0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Paste = { //size: 561 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213, + 10,14,0,28,21,175,226,241,24,0,0,1,208,73,68,65,84,56,203,149,147,177,107,83,81,20,198,127,247,189,52,130, + 36,49,141,212,148,12,133,34,6,92,92,180,106,98,4,209,18,112,118,208,33,56,20,69,109,29,196,197,65,151,130,56, + 8,142,250,15,52,131,187,155,168,75,213,46,186,56,41,145,82,168,209,72,66,94,111,108,208,70,239,57,14,161,49,47, + 109,32,126,219,253,206,61,63,206,249,224,24,6,84,42,149,140,239,123,207,157,147,217,126,223,247,189,23,206,73,177,92, + 46,107,191,111,0,110,206,154,43,6,30,42,140,43,30,118,242,18,185,220,17,60,207,0,32,162,172,172,124,96,95,237, + 41,6,1,104,170,234,173,199,47,89,50,243,103,137,248,158,9,46,156,57,24,251,210,201,240,46,200,210,180,29,166,167, + 167,48,102,27,32,172,173,173,147,76,68,57,154,252,204,164,191,206,179,215,171,86,84,83,17,32,230,121,102,44,26,241, + 121,95,207,178,120,255,17,65,16,80,169,84,66,171,205,205,29,34,149,74,113,239,238,109,46,102,190,33,170,49,32,26, + 233,255,212,222,130,68,34,129,170,48,51,115,108,48,30,226,241,56,91,127,192,169,233,121,61,128,106,40,27,150,223,188, + 13,189,11,249,28,187,41,194,16,157,62,149,231,31,92,16,113,195,1,186,75,97,123,2,85,69,69,200,157,60,254,127, + 19,20,242,57,68,4,17,65,85,176,214,50,49,145,30,13,208,223,40,210,109,110,253,104,141,62,129,136,235,65,170,95, + 171,52,26,245,29,33,135,1,3,53,231,186,128,86,203,210,168,215,41,22,207,15,219,20,111,216,4,214,110,80,251,94, + 67,68,122,254,245,249,171,92,158,90,30,190,194,222,49,165,25,52,73,167,51,164,211,25,178,217,195,88,187,129,170,112, + 99,225,90,175,217,55,26,2,108,138,232,239,246,47,183,231,68,242,35,15,22,239,240,211,237,140,166,176,255,19,171,237, + 3,0,36,181,138,49,102,83,85,59,6,96,225,92,247,26,49,140,51,130,84,187,215,248,228,21,75,127,1,79,230,225, + 152,120,105,196,218,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Redo = { //size: 591 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,214,7,26,10,39,21,63,184,237,33,0,0,1,220,73, + 68,65,84,56,203,157,147,77,107,19,81,24,133,159,59,95,77,140,164,66,76,99,131,31,109,54,213,118,211,210,42,126, + 84,99,13,66,169,56,110,68,43,130,184,26,112,173,59,193,191,224,126,86,221,117,41,68,10,133,138,197,82,186,106,164, + 168,27,193,77,117,33,41,98,76,38,77,154,201,100,198,205,24,39,157,65,130,103,249,94,158,195,185,231,190,23,250,144, + 110,106,158,110,106,211,81,103,18,253,107,91,55,181,194,127,27,60,126,96,0,188,209,77,109,46,56,23,17,113,7,128, + 60,176,8,76,1,147,1,3,150,150,77,128,27,69,195,94,15,25,232,166,118,1,120,62,39,180,84,182,112,117,88,77, + 141,230,16,2,85,142,97,217,63,41,125,91,225,202,232,189,30,19,17,128,23,128,23,143,242,249,243,242,80,78,170,217, + 101,188,218,167,158,116,31,155,53,128,174,201,185,61,123,86,248,240,4,240,242,225,181,235,55,99,153,51,88,149,117,44, + 79,35,238,218,0,12,58,13,54,219,206,223,226,132,196,165,145,187,44,45,155,40,254,236,233,157,179,227,147,177,116,150, + 250,175,119,36,90,13,18,52,24,110,85,120,69,2,71,234,237,58,61,120,178,123,13,5,96,64,213,102,143,143,77,167, + 227,214,123,178,251,85,118,164,4,154,34,168,29,137,51,238,67,23,21,48,235,22,153,99,167,217,92,253,208,237,64,1, + 232,184,110,70,200,130,84,195,98,171,84,247,214,90,149,208,235,76,92,62,17,130,187,123,224,116,156,228,209,198,87,182, + 119,118,89,107,181,45,224,25,48,85,52,108,81,52,108,1,240,54,57,20,130,129,110,7,236,55,171,238,74,93,72,192, + 253,162,97,175,30,78,224,195,51,69,195,46,69,110,162,170,200,7,128,23,5,251,10,193,193,4,27,205,189,178,90,144, + 189,24,166,54,127,216,228,207,53,162,36,3,140,221,150,221,47,7,237,250,173,153,220,143,212,110,249,148,208,213,173,207, + 175,59,118,63,127,36,184,137,35,192,2,80,5,54,158,36,221,239,2,188,249,69,167,243,47,131,223,215,75,186,5,94, + 207,53,222,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Replace = { //size: 776 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,214,1,6,22,4,3,245,118,104,130,0,0,2,149,73, + 68,65,84,56,203,173,147,77,108,12,97,24,199,127,51,179,179,181,72,183,204,44,193,129,86,208,137,224,160,137,131,160, + 184,52,113,32,82,73,137,175,99,75,138,90,65,164,68,16,130,138,34,113,173,68,19,196,54,18,209,131,75,125,180,68, + 72,137,143,157,165,69,98,91,149,212,110,119,103,63,186,93,187,59,175,3,59,105,47,78,254,201,147,60,239,155,252,127, + 121,158,55,255,87,98,156,246,29,104,212,52,77,139,20,207,209,104,84,191,218,122,45,202,63,36,21,27,255,161,3,107, + 75,189,101,93,75,86,212,136,20,83,37,85,140,137,190,151,15,164,132,21,95,119,169,165,245,209,63,1,141,251,247,106, + 186,238,139,44,172,170,97,32,237,97,229,226,89,152,225,24,233,100,2,43,212,137,203,165,160,40,178,99,82,85,53,224, + 111,58,188,5,192,5,160,235,190,72,249,226,149,124,177,74,168,91,93,206,36,183,130,170,200,116,135,4,51,150,108,96, + 248,125,39,199,142,54,59,128,243,23,207,214,22,123,151,115,59,217,199,188,233,165,20,108,65,54,87,32,155,179,241,149, + 150,240,117,104,12,9,176,172,56,0,94,111,25,37,111,142,115,121,171,44,128,29,206,92,106,33,193,224,112,130,112,36, + 67,60,157,103,142,230,193,45,23,208,167,216,0,132,66,33,0,90,183,41,236,186,210,67,117,237,126,128,155,50,64,194, + 138,175,235,123,221,197,204,82,9,115,96,132,145,212,24,47,204,239,196,82,25,162,239,239,179,105,227,38,12,195,160,173, + 65,99,247,213,103,12,62,109,231,157,57,88,0,144,1,166,149,77,239,170,40,159,79,248,213,61,42,124,37,244,132,126, + 146,28,205,50,252,186,3,93,211,24,77,143,58,230,129,39,55,121,215,31,101,196,236,80,128,42,233,204,153,83,98,238, + 188,114,124,186,78,208,12,146,74,167,156,103,89,182,116,25,213,107,170,105,107,208,216,121,169,155,112,79,59,111,63,69, + 137,153,1,128,170,166,91,118,175,11,112,204,7,155,252,88,86,220,217,23,248,99,110,121,74,255,195,54,62,126,79,18, + 51,3,252,90,84,207,145,147,215,123,1,73,110,110,62,33,5,205,32,249,194,47,187,104,50,12,3,195,48,168,172,172, + 228,155,188,130,224,243,231,244,15,89,196,130,119,169,59,253,2,219,51,219,201,144,12,224,63,120,72,2,16,194,97,32, + 132,224,198,30,157,207,63,162,220,9,4,136,124,232,96,85,125,7,147,180,5,228,114,185,98,4,132,60,46,149,118,62, + 159,159,0,104,186,101,179,126,230,103,106,54,239,102,121,195,99,196,228,57,36,147,73,114,185,60,128,50,49,72,128,170, + 186,241,122,221,14,32,147,201,144,72,36,200,102,179,40,138,130,170,170,127,203,5,96,79,0,40,138,114,251,66,203,185, + 237,66,136,9,83,20,75,146,156,127,135,199,227,105,7,114,252,15,253,6,121,205,27,12,206,189,173,89,0,0,0,0, + 73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Undo = { //size: 650 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,214,7,26,10,14,0,22,35,150,33,0,0,2,23,73, + 68,65,84,56,203,149,147,79,104,146,97,28,199,191,207,243,190,207,212,229,254,232,198,26,210,136,214,193,242,16,20,132, + 65,131,21,4,66,176,67,120,8,130,98,68,80,93,59,140,60,120,40,199,140,29,34,186,116,169,88,65,16,52,233,80, + 44,22,193,82,140,90,118,138,148,180,104,13,114,19,92,190,58,231,134,239,235,243,60,29,194,165,155,150,125,111,207,23, + 190,159,231,121,126,207,247,1,154,40,58,5,137,22,164,110,53,230,238,161,151,41,200,162,69,209,218,133,223,199,108,76, + 65,214,237,13,181,154,255,115,2,191,143,217,60,78,35,231,246,134,128,194,213,205,107,232,164,39,195,5,205,128,182,197, + 195,201,236,197,241,9,189,84,11,32,91,195,70,110,28,42,213,0,139,23,144,21,112,46,1,136,242,155,217,199,95,25, + 5,121,149,40,120,2,65,227,71,21,160,248,125,172,221,227,52,86,221,222,16,140,159,215,65,40,69,185,12,128,47,66, + 95,79,65,91,137,65,202,146,58,232,58,209,103,182,40,189,54,228,79,15,236,171,188,142,68,197,50,0,40,19,23,132, + 94,13,83,170,252,166,170,12,82,74,8,193,33,132,128,224,107,40,175,167,96,178,152,200,142,174,93,157,157,98,237,208, + 238,253,250,163,72,84,24,244,101,146,217,231,67,94,176,142,147,0,0,206,117,44,124,251,136,197,239,113,164,211,95,234, + 6,86,212,226,176,247,187,96,110,103,7,134,157,221,225,237,51,24,25,195,66,226,38,246,184,174,64,240,98,93,88,20, + 239,34,147,101,40,235,28,61,142,75,248,244,118,186,116,252,108,218,170,2,64,32,104,104,240,49,59,48,153,115,143,140, + 1,0,98,51,119,234,223,203,66,224,58,114,25,133,204,3,152,204,58,8,145,106,93,15,2,65,67,155,77,50,251,252, + 179,201,205,204,208,40,200,208,40,8,128,131,165,188,60,149,152,187,253,190,111,224,28,184,232,0,145,210,132,191,213,184, + 81,149,195,247,225,120,55,77,229,234,242,13,17,121,104,147,219,154,88,187,115,35,127,248,60,150,20,97,149,27,197,56, + 132,106,207,55,5,52,131,68,167,48,216,237,56,44,180,236,18,0,220,106,248,153,254,161,163,93,59,247,206,124,142,61, + 169,28,59,163,93,251,111,128,108,235,183,166,62,60,127,65,117,237,105,213,251,5,5,22,226,37,43,190,36,20,0,0, + 0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Emblem { +const nall::vector<uint8_t> Archive = { //size: 540 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,6,16,18,24,9,181,27,210,224,0,0,1,169,73, + 68,65,84,56,203,173,146,49,104,84,65,16,134,191,217,219,221,119,119,201,61,98,12,65,174,16,17,4,145,32,73,35, + 138,77,196,198,82,9,40,135,141,88,40,150,17,11,59,175,72,41,30,164,17,148,20,177,9,104,21,44,4,69,15,181, + 20,244,154,136,98,108,140,152,34,42,81,162,225,93,222,219,177,120,57,21,35,120,81,167,153,217,129,255,155,217,153,129, + 127,52,1,104,212,204,48,240,108,147,218,145,241,153,208,146,70,205,52,129,209,179,87,23,244,253,252,99,21,91,54,160, + 0,24,35,185,23,72,62,47,98,74,3,25,105,34,47,158,222,51,115,15,167,1,234,22,224,244,229,86,150,44,191,49, + 179,147,167,196,59,7,192,218,90,27,31,69,8,130,115,14,83,112,248,184,90,56,118,241,14,75,111,159,179,251,192,24, + 175,91,247,71,45,176,67,140,152,144,165,98,10,158,52,228,253,69,189,3,0,84,250,171,32,6,128,234,174,125,180,87, + 222,17,40,80,217,178,13,13,217,176,5,250,146,149,15,188,124,114,155,147,23,166,64,179,13,159,85,5,80,8,109,210, + 143,175,72,86,63,225,138,49,0,22,40,62,186,57,33,135,143,158,131,244,11,100,171,160,1,213,12,66,138,106,200,125, + 88,7,107,96,207,222,253,60,152,189,14,104,209,2,126,112,251,144,98,140,224,43,64,229,199,122,80,36,175,189,254,166, + 51,95,134,70,14,178,48,215,140,164,81,51,151,128,250,95,158,65,189,115,7,122,228,196,121,150,231,155,93,169,226,157, + 135,184,123,235,10,227,51,65,108,39,233,163,50,61,241,214,174,0,206,71,223,227,159,0,37,136,251,187,2,152,168,184, + 17,224,74,61,216,46,1,169,251,93,7,113,149,224,123,255,32,205,247,17,130,252,2,176,229,107,211,19,199,207,108,102, + 252,95,19,189,193,255,176,111,224,210,135,204,19,41,165,180,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Audio = { //size: 688 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,45,73,68,65,84,56,141,165,146,63,104,83,113,16,199,63,247,123, + 239,165,125,201,139,173,182,52,181,162,130,72,139,184,57,84,193,81,232,32,69,28,44,22,43,213,65,176,168,139,131,139, + 130,116,18,156,156,85,4,7,55,209,81,23,5,65,28,28,212,69,7,161,96,165,54,109,109,211,166,77,94,146,247,239, + 119,14,117,146,196,165,55,222,113,31,190,119,124,68,85,217,73,153,29,109,3,110,187,230,165,27,123,159,138,232,49,85, + 12,136,3,8,162,70,21,71,20,163,130,128,56,40,171,109,1,89,166,231,199,199,79,117,15,244,13,179,43,216,71,193, + 239,195,243,2,140,113,200,178,136,86,84,165,222,92,230,209,147,7,253,109,1,0,131,3,251,201,251,62,65,16,80,44, + 148,8,252,33,114,94,145,86,84,161,22,46,144,247,3,16,180,35,160,90,155,39,177,91,196,73,141,122,163,76,87,174, + 7,193,33,73,67,162,100,147,40,222,0,171,210,17,144,164,13,94,188,124,95,111,54,50,81,139,108,255,3,81,85,227, + 229,76,58,49,49,230,91,181,157,1,160,108,85,211,32,197,61,136,155,196,110,230,165,41,205,164,133,159,20,163,116,83, + 85,81,254,147,64,213,34,34,60,127,88,94,208,127,100,153,154,41,97,53,67,173,74,71,15,172,166,128,232,236,44,210, + 118,110,83,64,59,139,100,109,138,8,188,235,32,155,181,9,86,255,158,48,53,51,112,218,245,204,109,207,20,142,231,186, + 242,226,122,110,166,196,136,160,195,101,100,242,106,105,172,203,53,247,242,249,222,67,34,226,56,174,177,86,99,80,196,189, + 120,109,240,130,231,57,143,207,158,57,151,31,57,124,146,176,185,196,74,229,147,179,81,155,67,21,66,51,120,179,191,183, + 231,238,244,228,173,194,158,221,67,132,205,21,150,42,31,217,10,231,0,196,117,140,92,25,57,90,200,71,250,149,239,63, + 23,105,69,235,52,163,53,204,118,56,5,123,103,244,196,129,194,239,173,183,44,87,83,154,113,133,36,9,49,198,67,21, + 227,42,250,225,199,92,99,180,216,83,46,248,254,10,105,170,132,245,140,122,173,129,181,214,184,142,172,46,150,127,21,115, + 221,137,136,24,162,86,68,101,189,65,101,173,145,0,70,84,149,233,235,165,251,32,151,179,76,251,68,36,113,92,153,71, + 245,115,26,235,43,208,111,142,103,158,101,153,30,49,70,98,133,204,49,242,37,77,236,27,140,121,253,7,117,49,14,53, + 175,233,38,194,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Binary = { //size: 560 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,4,22,20,7,56,114,185,172,74,0,0,1,189,73, + 68,65,84,56,203,181,147,205,78,19,97,20,134,159,239,155,111,102,164,77,72,40,130,164,96,59,13,144,9,198,40,104, + 32,97,163,27,72,240,6,184,0,55,77,220,176,96,227,206,112,1,46,154,184,97,195,5,52,222,128,209,149,113,229,66, + 170,9,218,81,204,12,161,105,11,180,252,101,250,135,40,46,148,102,20,102,118,188,201,89,62,79,78,242,158,3,33,89, + 92,90,157,156,89,120,122,182,184,180,58,73,68,100,24,236,57,238,250,243,103,143,241,28,119,61,74,34,163,224,98,105, + 135,137,123,118,164,68,134,193,155,149,26,186,210,184,51,62,76,98,100,40,84,34,47,93,123,119,31,93,73,116,77,131, + 51,232,49,12,44,59,115,169,68,252,15,151,234,135,8,4,66,128,16,130,79,197,18,166,161,56,61,253,201,23,183,138, + 231,184,88,118,102,42,159,203,22,0,100,16,174,30,28,163,107,26,186,250,51,237,246,15,248,5,137,222,56,183,70,147, + 12,247,247,5,55,153,3,80,231,112,237,184,129,174,52,132,16,8,4,141,86,135,218,190,207,221,137,155,92,51,21,239, + 222,111,34,17,164,7,250,1,240,28,247,53,32,164,101,103,230,151,87,214,184,222,27,167,213,58,193,111,180,249,238,237, + 178,181,93,167,92,57,164,217,232,80,174,28,161,164,36,102,26,108,237,213,241,28,151,212,88,234,62,128,204,231,178,111, + 44,59,51,181,188,178,198,200,96,31,27,197,50,123,53,31,223,239,48,150,30,36,149,76,208,106,158,16,51,13,156,114, + 181,11,191,124,241,228,67,183,133,124,46,91,56,151,60,122,120,155,184,105,16,55,13,142,14,154,72,33,80,66,242,209, + 43,93,128,255,169,49,40,121,48,59,78,204,52,24,77,15,96,234,138,183,27,223,240,28,151,164,117,99,58,8,119,107, + 12,59,166,175,197,29,94,21,62,95,168,46,82,16,148,252,173,44,20,142,76,224,27,231,184,202,252,6,31,155,240,68, + 82,120,70,77,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> File = { //size: 741 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,0,18,116,69,88,116,84,105,116,108,101,0,80,97,112,101,114,32,83, + 104,101,101,116,115,185,175,145,249,0,0,0,23,116,69,88,116,65,117,116,104,111,114,0,76,97,112,111,32,67,97,108, + 97,109,97,110,100,114,101,105,223,145,26,42,0,0,0,39,116,69,88,116,68,101,115,99,114,105,112,116,105,111,110,0, + 119,105,116,104,32,97,32,72,85,71,69,32,104,101,108,112,32,102,114,111,109,32,74,97,107,117,98,134,84,7,179,0, + 0,1,238,73,68,65,84,56,141,133,147,77,107,83,65,20,134,159,51,247,166,26,80,209,104,177,181,136,27,107,55,138, + 127,64,68,220,248,1,42,184,240,71,40,226,170,11,23,130,63,65,20,44,85,132,46,42,22,63,176,208,160,155,254,27, + 181,177,109,154,144,80,53,201,153,153,227,226,222,155,220,166,130,7,14,51,12,243,62,231,61,51,28,49,51,234,95,87, + 111,136,200,98,8,241,52,24,102,134,25,128,1,252,1,89,143,49,60,191,123,231,222,58,227,97,102,172,174,125,252,190, + 211,106,90,140,113,95,14,6,125,219,104,252,176,181,47,171,191,87,62,188,125,156,193,71,233,0,250,253,254,204,177,163, + 53,118,127,237,210,233,182,217,105,111,179,213,108,176,241,243,27,155,219,13,186,157,14,55,175,221,170,78,158,152,124,178, + 252,110,105,190,108,192,1,168,122,0,66,80,124,240,132,16,178,140,17,245,202,86,115,19,231,28,87,46,95,173,30,152, + 56,248,244,205,210,171,75,99,0,5,216,39,142,49,16,99,36,196,192,251,79,43,212,235,117,46,156,191,88,197,108,126, + 15,192,171,2,150,139,125,46,204,196,209,34,83,211,83,204,205,205,50,115,230,20,206,57,233,245,122,215,95,188,124,150, + 236,113,96,249,131,154,25,6,8,130,147,81,86,171,85,142,28,62,196,236,217,115,168,250,68,85,43,0,105,249,13,138, + 16,192,4,16,65,196,145,166,46,59,23,161,40,24,45,50,2,120,45,62,53,147,11,8,142,196,9,137,75,70,224,2, + 224,21,139,86,2,104,1,112,56,103,24,130,12,189,148,151,108,227,189,39,134,184,23,32,128,115,110,120,187,168,38,185, + 163,50,64,213,19,67,40,3,60,32,164,105,2,150,139,165,228,162,0,152,32,34,120,85,66,25,224,243,22,146,36,29, + 86,23,100,228,34,95,45,27,16,84,149,48,222,2,64,226,146,76,92,206,146,131,108,182,254,1,16,145,70,187,221,154, + 174,213,142,243,191,232,118,59,128,180,212,107,63,107,203,140,135,143,30,220,78,43,233,130,14,6,39,205,192,48,200,71, + 186,188,7,163,82,153,216,86,213,251,139,11,175,63,3,252,5,198,186,65,227,184,230,144,207,0,0,0,0,73,69,78, + 68,174,66,96,130, +}; +const nall::vector<uint8_t> Folder = { //size: 581 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,1,194,73,68,65,84,56,141,165,144,49,107,147,81,20,134,159,115,239, + 87,44,41,226,224,16,186,20,28,156,50,118,235,46,153,28,130,208,213,95,160,187,208,63,224,226,86,87,255,135,40,196, + 185,96,196,89,41,138,36,146,80,105,191,38,37,223,189,231,158,227,144,38,54,88,90,193,119,57,220,123,207,121,238,121, + 95,233,118,187,252,143,170,221,221,221,55,238,254,248,154,183,11,119,127,50,24,12,142,110,4,152,89,175,215,235,221,51, + 51,204,12,119,7,224,244,244,244,126,191,223,63,236,116,58,207,151,205,57,103,66,8,101,56,28,126,172,235,186,0,84, + 57,103,87,85,38,147,9,165,148,21,36,132,192,246,246,118,7,120,187,132,2,76,167,211,170,148,242,170,174,235,131,43, + 128,140,170,98,102,107,144,118,187,221,218,220,220,164,213,106,17,99,36,132,192,104,52,98,60,30,63,92,89,80,85,83, + 45,28,126,72,204,154,63,63,129,0,224,204,129,249,234,214,61,0,123,251,236,236,237,199,24,190,85,57,103,79,41,49, + 109,156,151,207,30,33,114,217,120,53,41,95,59,1,144,212,57,120,253,126,167,74,41,153,170,2,78,12,240,233,248,236, + 234,2,203,178,158,124,20,30,180,183,64,220,43,85,37,231,140,136,16,131,16,227,117,35,235,202,106,184,57,130,120,149, + 115,182,156,51,184,19,68,216,184,1,160,197,105,178,81,204,9,65,0,22,0,213,197,6,243,84,8,128,249,162,185,184, + 99,230,152,59,89,23,117,105,161,73,182,2,184,106,65,164,98,82,55,12,127,205,105,212,110,180,80,69,97,114,54,95, + 0,84,213,82,74,224,145,47,163,115,78,166,13,127,103,190,174,24,132,159,103,151,22,68,196,204,12,17,161,201,70,235, + 78,117,107,136,34,194,69,82,128,82,185,59,199,39,134,8,124,254,58,186,117,120,169,217,108,142,192,81,101,27,91,253, + 119,199,119,159,130,243,227,251,248,159,1,34,140,69,194,139,223,71,22,33,158,28,99,167,49,0,0,0,0,73,69,78, + 68,174,66,96,130, +}; +const nall::vector<uint8_t> Font = { //size: 627 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,5,73,68,65,84,56,141, + 157,147,205,75,148,81,20,198,127,51,119,26,103,116,104,132,176,15,130,138,172,137,92,181,16,218,106,6,173,219,105,229, + 190,93,224,127,16,109,6,134,105,33,17,33,180,210,162,77,68,84,16,168,45,114,81,65,37,83,145,31,73,58,99,56, + 78,227,152,54,239,124,221,251,222,247,180,136,25,169,209,192,14,28,184,220,115,249,61,231,121,224,250,18,201,248,85,32, + 97,173,141,176,139,82,74,57,192,16,137,100,188,88,169,148,197,243,188,93,181,83,114,36,145,140,23,253,214,218,72,40, + 20,102,108,98,14,128,177,137,57,68,132,209,241,89,60,207,50,58,62,67,177,92,101,248,233,60,90,107,180,174,81,171, + 85,105,107,109,195,90,27,241,215,87,186,114,254,20,0,151,251,98,136,8,151,206,157,68,68,24,232,61,193,147,183,171, + 164,243,37,106,198,34,34,136,72,195,74,3,80,87,254,187,231,87,138,188,251,186,129,118,45,217,245,202,206,128,186,242, + 214,3,161,102,44,83,51,5,180,54,24,237,178,178,94,218,221,6,227,169,60,61,93,251,136,134,20,218,184,44,231,255, + 1,168,123,174,171,103,214,202,212,140,203,209,142,48,29,123,131,104,227,146,206,57,59,3,238,77,206,55,134,174,245,120, + 254,62,199,133,51,29,136,8,7,219,131,104,237,178,148,43,54,1,2,245,195,64,111,103,99,56,249,33,207,199,244,6, + 67,119,215,208,198,160,181,139,49,46,217,82,133,82,85,19,14,6,154,1,247,95,44,208,223,211,73,110,179,74,106,241, + 7,55,6,78,227,67,240,60,97,41,87,228,250,88,10,109,44,153,239,14,177,195,209,102,11,253,61,199,241,196,227,193, + 203,12,23,207,30,162,173,69,17,14,42,90,91,20,7,218,67,104,227,162,141,203,98,246,231,246,25,120,158,240,248,205, + 10,1,37,28,219,223,250,71,160,126,31,191,1,218,101,250,75,1,216,6,240,240,213,55,166,62,231,89,93,175,242,122, + 54,223,0,204,45,111,50,252,232,19,65,191,16,218,227,99,122,161,192,200,179,217,173,12,148,82,78,185,92,138,12,246, + 197,24,236,163,169,186,187,162,116,119,29,105,186,119,28,7,165,148,19,0,134,110,223,185,117,243,63,191,243,181,95,46, + 181,156,109,120,254,28,88,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Image = { //size: 558 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,11,10,16,7,18,54,148,178,182,0,0,1,187,73, + 68,65,84,56,203,157,211,77,107,19,65,24,192,241,255,236,219,52,221,152,212,5,161,165,5,161,224,165,133,92,196,162, + 23,83,232,201,131,159,64,232,103,40,158,235,49,24,131,245,11,8,222,122,245,32,210,64,181,216,30,10,213,158,84,68, + 15,42,210,67,34,5,149,38,155,110,183,217,153,233,97,233,234,98,10,33,3,3,243,250,123,102,134,103,68,189,81,91, + 3,238,51,90,121,66,189,81,51,90,235,145,106,189,81,51,14,128,49,134,7,143,158,178,181,243,110,168,176,75,213,5, + 86,87,150,1,112,0,132,16,236,238,127,102,238,230,29,44,203,194,181,21,133,130,226,247,145,77,162,52,137,210,40,165, + 1,72,148,97,107,231,77,30,48,198,224,216,130,160,236,51,51,25,115,183,90,36,40,5,108,236,126,231,237,123,63,67, + 82,64,211,254,231,52,206,121,195,178,44,46,249,146,27,243,49,179,83,139,8,225,114,251,122,151,111,7,167,68,39,2, + 165,83,64,41,147,187,206,95,64,8,74,227,146,78,104,19,39,45,92,187,204,159,163,46,190,156,64,58,160,207,1,125, + 1,32,128,98,193,163,125,120,133,215,123,95,8,202,167,124,61,8,40,142,123,104,109,104,255,248,196,228,213,57,244,133, + 128,5,37,95,130,16,244,142,125,122,61,131,231,128,235,167,111,244,106,239,37,133,49,143,153,217,249,193,64,210,239,19, + 117,14,115,147,6,3,6,180,73,163,238,111,63,167,31,71,131,129,78,55,228,217,250,139,244,46,233,110,180,214,132,199, + 17,97,24,81,153,78,135,155,205,38,120,151,51,192,202,105,158,196,118,36,8,135,190,22,196,137,193,113,199,168,76,159, + 100,107,166,38,24,124,2,128,197,91,21,90,63,127,13,200,189,107,185,94,235,195,199,255,129,165,234,2,27,155,219,67, + 167,114,14,16,66,176,186,178,156,165,231,48,69,74,153,1,235,141,199,15,239,141,250,157,207,0,181,88,225,150,139,66, + 18,171,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Markup = { //size: 709 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,22,20,19,51,203,197,162,151,0,0,2,82,73, + 68,65,84,56,203,149,146,189,79,83,81,24,198,127,231,246,210,43,80,108,122,129,66,33,66,172,124,72,136,128,24,28, + 28,140,68,93,48,33,38,14,70,101,209,77,227,232,162,49,33,93,252,7,12,38,24,163,131,31,3,49,46,234,224,228, + 96,92,64,38,33,166,45,1,77,173,20,232,237,135,45,247,182,183,237,189,14,166,216,43,198,132,103,122,79,242,158,231, + 252,222,243,188,98,118,118,246,101,34,145,184,192,222,116,113,122,122,122,14,128,80,40,100,239,85,161,80,200,174,58,201, + 213,66,211,52,44,203,2,64,8,177,243,84,181,22,66,224,114,185,240,122,189,14,148,29,3,203,178,136,68,34,142,11, + 181,18,66,48,48,48,176,107,22,185,246,208,223,223,255,95,130,127,73,174,109,172,37,168,234,243,90,134,165,175,89,178, + 134,69,217,178,113,203,18,82,169,157,203,119,158,93,125,113,111,234,137,131,160,175,175,111,199,224,251,230,79,30,190,90, + 32,208,166,50,121,230,24,7,59,155,105,80,20,210,121,131,149,216,22,139,203,177,199,151,110,63,189,238,48,136,70,163, + 0,36,82,6,175,23,54,56,63,62,204,112,175,159,116,222,96,53,250,5,217,227,135,122,31,77,251,224,202,196,8,243, + 203,241,49,199,8,85,130,185,71,239,153,60,53,196,145,160,74,42,153,160,165,107,16,111,75,0,189,80,34,17,91,69, + 182,76,164,138,193,233,177,160,243,19,35,145,8,159,194,26,62,223,126,198,199,122,200,101,52,202,178,7,36,65,157,36, + 227,174,179,105,80,100,124,13,10,1,127,43,138,226,222,157,194,219,197,143,156,24,237,34,147,78,146,52,27,241,119,116, + 96,219,96,3,8,9,97,153,172,167,44,22,87,150,240,213,219,206,20,194,225,48,9,77,167,187,221,199,124,116,147,96, + 175,31,203,134,106,46,249,76,138,227,35,131,8,33,176,109,155,248,250,6,210,223,4,5,179,140,162,184,145,60,126,50, + 249,2,91,57,19,189,88,33,167,155,152,249,45,199,94,180,181,54,255,33,80,85,245,247,98,200,18,217,237,2,141,133, + 31,120,100,133,205,237,22,146,117,110,202,21,139,66,170,204,72,169,68,177,104,210,228,105,68,215,117,196,204,204,204,155, + 100,50,121,174,106,20,183,14,113,246,228,48,71,123,84,130,7,2,124,139,197,249,176,98,96,226,198,40,150,201,102,82, + 40,162,194,141,201,33,52,77,99,215,126,94,187,251,252,126,123,64,189,57,53,49,202,225,238,86,0,210,153,44,15,222, + 173,81,193,197,118,193,196,48,76,110,77,116,146,203,229,248,5,131,250,25,20,161,246,118,40,0,0,0,0,73,69,78, + 68,174,66,96,130, +}; +const nall::vector<uint8_t> Program = { //size: 609 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,214,1,5,14,9,17,179,225,58,161,0,0,1,238,73, + 68,65,84,56,203,165,147,61,104,83,81,20,128,191,123,238,123,105,140,177,105,82,7,155,162,173,70,170,77,148,214,90, + 39,7,21,7,103,135,110,65,156,93,172,17,7,137,173,58,184,137,139,160,131,63,136,118,214,69,212,69,196,216,165,40, + 175,138,105,165,224,79,138,144,34,181,146,180,9,36,105,124,215,193,164,160,77,176,234,129,51,221,251,125,231,222,115,207, + 133,255,12,213,108,193,137,211,1,100,1,180,176,175,239,46,175,214,108,117,226,116,56,113,76,241,83,202,93,154,121,104, + 156,56,38,125,156,45,141,246,74,179,202,59,206,63,49,75,233,123,106,254,241,9,182,158,188,70,165,202,108,35,137,52, + 130,35,137,91,110,110,226,178,18,81,40,183,76,46,53,74,100,248,122,67,137,172,134,111,186,185,231,103,197,242,172,199, + 246,111,194,227,11,98,89,54,249,241,139,68,78,173,150,72,13,238,7,178,219,19,55,220,252,139,17,209,150,141,29,236, + 166,58,55,129,50,101,188,225,189,248,163,67,84,191,56,244,156,187,79,165,202,236,155,99,12,2,88,53,209,100,228,244, + 109,55,159,74,138,214,22,118,107,39,246,134,48,170,180,128,39,180,13,29,236,1,37,24,99,112,23,51,196,174,76,49, + 149,136,189,4,212,202,21,90,2,93,69,221,226,199,14,108,198,183,115,136,106,118,28,17,176,55,198,16,109,163,68,106, + 169,49,197,249,82,157,171,159,32,60,61,122,56,219,155,124,144,255,94,204,4,150,63,62,66,219,62,172,64,23,162,53, + 198,24,20,6,227,130,132,98,165,233,145,131,94,96,207,74,15,6,198,152,3,194,239,46,29,13,216,109,209,69,74,95, + 49,133,207,136,183,13,37,130,136,70,41,141,213,190,171,14,135,7,198,120,253,203,43,212,37,83,23,142,180,174,235,27, + 94,176,124,65,68,129,136,254,153,109,189,165,116,242,64,29,158,107,54,202,250,234,33,186,247,119,242,62,122,230,206,55, + 41,204,132,116,168,7,183,125,112,249,109,98,183,253,59,252,199,81,46,125,120,90,168,100,158,149,157,56,166,54,39,127, + 245,153,250,129,201,122,147,215,84,249,95,226,7,144,100,183,170,35,108,244,94,0,0,0,0,73,69,78,68,174,66,96, + 130, +}; +const nall::vector<uint8_t> Script = { //size: 516 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,236,0,236,0,236,29,35,22,54,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,9,15,10,59,4,237,28,251,236,0,0,1,145,73, + 68,65,84,56,203,149,147,191,142,218,64,16,198,127,131,86,162,12,206,3,32,10,10,55,72,199,91,68,138,168,82,240, + 8,185,154,198,13,7,114,7,244,20,52,244,156,174,35,77,36,222,129,148,84,200,72,8,176,131,43,26,104,152,43,214, + 235,24,78,119,209,141,52,187,171,209,206,55,223,252,147,201,100,242,114,56,28,126,240,57,105,247,251,253,103,0,194,48, + 212,207,74,24,134,234,144,140,123,164,105,154,195,11,130,10,72,49,166,216,227,171,231,221,80,49,247,220,68,36,187,45, + 16,128,170,3,211,55,185,152,98,4,231,128,8,162,5,187,100,12,84,222,7,144,34,3,205,12,130,5,18,7,252,17, + 3,196,230,238,254,139,229,227,124,149,251,162,88,41,21,83,80,209,236,143,228,183,138,213,36,137,121,252,249,200,110,183, + 123,7,64,29,135,2,227,76,255,38,49,189,94,143,32,8,232,116,58,92,175,215,183,0,82,228,231,10,42,16,39,49, + 79,79,214,121,179,217,224,251,62,171,213,138,32,8,30,110,106,160,242,175,255,37,4,69,73,226,36,143,188,221,110,49, + 198,80,175,215,73,211,148,40,138,150,65,16,52,239,230,64,17,205,134,72,36,119,222,239,247,24,99,242,25,41,151,203, + 212,106,53,162,40,90,150,238,219,104,251,173,40,202,104,52,98,56,28,98,140,201,245,116,58,225,251,62,81,20,1,52, + 115,0,207,243,240,60,143,74,165,98,245,75,133,106,181,202,96,48,96,58,157,98,140,225,114,185,0,176,88,44,0,154, + 179,217,236,143,140,199,227,95,199,227,241,251,71,171,119,62,159,89,175,215,180,90,45,230,243,57,141,70,227,119,183,219, + 253,118,195,252,191,251,219,110,63,0,75,23,217,217,95,1,152,44,191,17,163,238,139,75,0,0,0,0,73,69,78,68, + 174,66,96,130, +}; +const nall::vector<uint8_t> Text = { //size: 333 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,22,20,15,56,186,96,38,66,0,0,0,218,73, + 68,65,84,56,203,173,146,61,110,132,48,16,133,191,7,72,187,91,33,33,159,129,159,179,108,153,34,199,65,230,22,28, + 33,81,218,28,6,115,1,26,250,173,76,138,136,21,36,94,88,162,188,106,44,123,222,124,51,30,181,109,251,49,12,195, + 11,199,244,90,215,245,59,0,214,218,233,168,172,181,211,236,148,204,193,56,142,120,239,1,144,116,47,53,199,146,136,227, + 152,52,77,87,40,119,3,239,61,206,185,85,194,82,146,168,170,234,87,47,201,242,80,20,197,38,65,72,201,242,225,146, + 224,167,158,34,200,243,60,80,241,198,52,157,136,162,104,155,0,160,239,251,213,101,89,150,192,5,184,1,231,253,22,66, + 4,146,144,46,15,23,98,69,224,156,219,28,222,55,209,206,47,132,9,180,79,32,137,174,235,130,149,231,233,135,140,130, + 4,33,147,221,61,200,178,140,191,40,49,198,124,54,77,115,61,146,100,140,121,227,191,244,5,84,81,95,185,252,185,63, + 236,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Video = { //size: 592 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,4,28,9,32,30,1,50,75,149,0,0,1,221,73, + 68,65,84,56,203,165,147,191,170,26,81,16,198,127,251,71,55,55,70,238,53,32,65,13,168,205,54,194,86,203,130,205, + 54,10,130,104,231,59,228,33,146,34,16,244,17,52,15,96,17,172,197,70,43,27,219,72,34,9,11,130,141,165,138,112, + 37,146,213,157,20,234,230,154,164,72,110,6,206,97,102,190,153,57,243,13,103,20,203,118,94,37,19,119,239,1,2,225, + 44,114,190,5,4,68,4,80,78,30,57,97,135,195,33,248,238,251,175,177,108,71,122,189,158,108,183,91,25,14,135,82, + 42,149,174,108,215,117,255,136,183,90,45,177,108,71,176,108,71,14,135,131,172,86,43,73,167,211,226,186,238,95,217,205, + 102,83,44,219,17,149,255,20,237,69,58,243,54,249,60,129,105,154,56,142,195,100,50,33,22,139,133,246,120,60,38,30, + 143,255,134,111,54,27,62,127,249,138,98,217,142,36,19,119,60,102,136,247,223,246,170,14,144,121,153,225,126,187,253,167, + 214,159,221,222,6,31,63,205,84,21,224,137,97,0,208,237,118,169,86,171,24,134,65,52,26,37,18,137,80,175,215,209, + 52,13,85,85,169,215,235,40,138,194,57,71,7,80,1,162,209,40,34,66,16,4,100,179,89,114,185,220,245,160,52,45, + 76,20,57,209,208,117,29,128,83,149,51,56,157,78,201,231,243,152,166,73,173,86,3,192,243,60,42,149,10,166,105,226, + 121,30,134,97,176,223,239,209,53,141,176,131,167,55,55,136,8,237,118,155,217,108,198,104,52,162,211,233,176,88,44,240, + 125,159,76,38,67,54,155,101,50,153,224,251,62,34,18,210,86,1,34,145,8,0,229,114,153,245,122,77,185,92,166,84, + 42,145,203,229,40,20,10,44,151,75,82,169,20,197,98,145,227,241,200,133,118,72,225,120,60,34,34,12,6,131,144,39, + 64,191,223,7,32,159,207,211,104,52,174,102,16,4,193,207,2,23,231,229,132,191,225,172,207,231,243,80,255,53,78,191, + 4,219,182,29,82,121,152,12,132,175,61,212,119,187,29,0,138,101,59,239,128,55,143,92,133,15,63,0,208,50,35,119, + 229,61,168,67,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Go { +const nall::vector<uint8_t> Down = { //size: 683 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,61,73,68,65,84,56,141, + 133,147,77,104,19,65,24,134,223,153,236,230,15,107,192,96,210,67,252,193,170,245,34,26,143,73,180,224,193,139,241,34, + 20,47,30,42,226,65,20,234,161,85,241,42,8,210,21,60,169,80,132,156,20,33,162,82,83,91,114,177,214,85,8,181, + 45,20,123,168,85,180,84,205,154,174,253,11,233,38,179,179,159,135,214,26,155,24,223,227,55,223,60,243,190,243,205,48, + 34,66,181,226,221,106,30,132,48,234,137,193,208,123,68,115,117,73,169,105,34,132,111,93,72,195,118,4,108,71,96,201, + 42,96,201,50,1,0,119,31,221,168,1,215,2,0,48,198,144,155,121,142,178,93,66,161,56,131,143,115,99,104,63,120, + 181,174,41,94,175,88,29,202,163,248,235,110,108,8,0,17,136,28,16,17,20,238,110,8,80,18,151,85,157,28,196,214, + 237,187,96,57,36,189,146,108,72,178,177,92,54,81,189,22,239,82,215,13,50,142,55,10,57,72,69,66,45,209,139,39, + 175,251,20,151,10,34,199,43,73,130,152,4,184,68,81,22,160,122,57,184,194,112,254,212,53,47,8,16,162,130,116,54, + 85,154,95,156,75,49,34,66,162,91,77,183,69,143,39,143,68,147,158,247,249,87,144,92,64,162,140,21,123,17,211,243, + 57,16,104,45,22,71,219,246,211,24,157,24,41,79,78,141,247,189,238,17,237,124,45,114,199,203,177,140,241,197,152,162, + 72,112,47,136,87,0,151,141,66,101,26,170,143,193,237,227,80,125,46,68,35,71,97,46,152,52,249,97,220,32,194,153, + 245,75,212,53,81,4,33,249,112,240,158,229,229,77,8,248,131,40,209,79,148,93,139,112,123,57,220,62,23,182,109,217, + 131,144,175,5,217,161,140,69,14,146,186,38,138,127,77,65,215,196,68,69,172,116,62,24,188,83,218,17,56,0,155,149, + 160,122,86,79,222,188,41,128,253,161,99,232,203,62,46,9,81,233,212,53,49,81,119,140,186,38,122,103,141,79,47,134, + 199,6,68,107,48,1,174,48,40,110,142,67,225,19,200,189,123,91,249,97,126,235,215,53,209,219,240,29,144,131,142,161, + 145,129,239,166,177,64,187,155,98,216,229,143,193,252,186,76,185,81,61,239,200,213,220,13,1,186,38,138,36,145,204,100, + 159,89,91,177,15,65,167,21,79,251,159,88,142,252,147,187,90,108,227,111,252,173,120,151,122,46,210,188,243,54,0,204, + 230,63,95,218,104,253,191,0,0,56,124,69,189,15,0,195,55,197,217,127,245,252,2,115,74,18,42,134,104,28,203,0, + 0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Home = { //size: 606 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,10,14,20,37,19,83,42,210,59,0,0,1,235,73, + 68,65,84,56,203,149,147,191,107,83,81,20,128,191,123,251,222,75,211,64,242,36,160,85,135,100,81,123,19,104,85,172, + 17,92,28,140,66,19,167,135,212,74,39,145,162,163,24,92,58,180,110,193,169,254,24,234,212,37,139,245,199,96,19,240, + 15,240,63,16,121,91,92,196,90,219,240,98,81,137,33,121,215,33,246,217,151,80,33,103,186,92,206,247,221,115,14,231, + 194,1,225,41,85,172,128,174,128,246,148,122,200,48,177,7,123,74,105,79,169,61,73,113,104,120,177,56,163,203,55,111, + 252,87,34,250,225,154,235,110,20,148,98,253,220,89,182,39,78,113,228,240,56,39,188,38,83,107,107,212,92,151,130,82, + 215,14,185,110,117,64,176,31,126,83,156,97,247,248,49,148,202,50,22,141,210,106,181,24,219,252,74,182,92,30,144,136, + 126,184,122,251,22,157,100,146,116,42,77,42,149,2,64,107,104,183,219,236,214,235,156,44,149,66,18,177,31,126,247,160, + 68,199,48,201,229,46,96,219,118,208,154,214,26,0,223,247,249,185,181,69,114,110,46,144,136,10,232,130,82,188,127,84, + 198,107,54,57,63,157,35,30,143,35,132,8,9,124,223,15,206,134,16,140,230,243,212,92,23,3,184,3,172,78,157,62, + 195,253,210,61,54,170,111,3,240,201,202,51,86,30,63,69,139,17,116,167,133,48,70,209,221,223,44,47,45,209,238,165, + 204,202,121,120,190,48,153,33,17,79,0,160,212,4,153,140,34,155,205,244,94,20,146,145,244,149,222,196,83,121,144,22, + 90,107,22,38,51,204,195,186,236,239,211,178,44,76,211,196,48,140,224,254,75,227,7,0,31,234,59,116,187,126,144,11, + 48,32,144,82,34,165,196,146,159,1,232,96,241,241,83,3,128,111,222,47,58,34,18,90,36,99,96,179,254,14,207,231, + 40,0,151,46,78,115,53,26,67,234,113,46,75,147,237,77,66,21,24,253,21,252,155,126,239,165,239,222,14,162,217,56, + 112,245,3,65,36,18,193,182,109,18,137,4,2,137,16,16,139,197,112,28,103,0,178,44,43,252,23,174,207,58,175,0, + 135,225,98,245,229,139,215,119,255,0,86,248,213,163,133,187,128,26,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Left = { //size: 655 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,33,73,68,65,84,56,141, + 133,147,79,72,20,113,20,199,191,111,102,126,179,59,187,82,98,108,173,27,181,66,8,17,9,130,149,110,91,135,220,34, + 86,211,76,68,34,136,14,37,116,178,162,45,186,122,137,16,3,59,196,30,36,240,208,37,10,130,176,110,29,36,87,138, + 142,21,30,34,75,247,80,185,108,146,187,237,204,238,204,239,247,235,48,153,174,140,238,131,119,122,127,248,188,239,123,15, + 82,74,212,242,163,55,181,43,241,91,90,198,43,166,97,11,139,167,88,29,17,38,163,225,230,174,133,31,159,13,175,28, + 101,139,226,22,16,62,157,60,220,223,115,109,224,158,103,49,0,111,130,120,138,13,25,190,186,241,139,201,97,99,207,206, + 102,82,104,115,208,170,200,42,242,190,200,129,174,193,83,87,13,147,175,224,227,247,105,28,137,246,128,84,88,241,20,147, + 85,213,132,159,36,165,92,135,76,83,137,67,125,141,29,7,59,217,215,95,31,80,176,242,208,84,134,88,83,31,136,20, + 16,0,9,64,74,1,33,5,238,164,47,184,4,241,20,27,10,26,219,31,244,159,184,228,175,175,111,160,247,139,175,192, + 165,3,166,232,16,146,99,102,254,25,136,8,4,130,132,171,126,123,180,215,29,225,216,109,246,168,169,113,255,249,238,227, + 131,70,174,180,128,119,223,222,128,49,31,116,77,7,87,4,44,81,128,105,22,80,180,86,80,182,75,80,72,133,159,5, + 209,186,59,177,166,1,231,54,44,251,15,76,231,55,74,50,15,112,1,135,155,168,8,19,92,114,72,46,193,29,9,199, + 22,224,142,59,114,174,152,117,215,56,51,106,95,206,46,125,185,254,248,101,218,132,237,147,173,123,19,144,122,25,66,47, + 129,5,0,127,64,133,30,80,193,12,5,204,175,64,213,168,90,199,245,34,146,130,169,182,150,88,184,189,45,166,207,21, + 94,35,95,153,135,144,192,233,200,13,136,127,20,220,118,29,0,210,79,238,174,53,248,191,70,21,147,187,118,68,146,231, + 206,12,4,138,108,17,115,203,211,232,12,13,227,254,196,136,197,43,240,111,186,198,141,135,196,116,125,188,183,251,172,17, + 14,135,40,168,132,48,250,112,4,153,49,155,54,230,122,158,114,102,204,158,176,43,149,142,231,47,158,102,103,103,223,150, + 203,229,138,87,90,181,6,94,182,58,82,195,182,80,50,191,156,11,120,17,212,124,229,90,239,252,23,109,243,52,116,236, + 202,203,9,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Right = { //size: 676 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,54,73,68,65,84,56,141, + 149,146,75,72,84,97,28,197,127,223,227,206,195,70,195,20,82,196,94,68,32,104,20,4,133,211,70,104,209,34,130,4, + 91,70,129,66,184,201,114,140,54,66,43,55,141,144,139,40,114,19,20,189,164,69,98,62,112,17,45,102,208,41,164,20, + 55,209,34,44,51,157,177,129,30,227,120,239,220,251,181,8,95,51,19,212,129,179,249,254,135,195,249,159,255,135,49,134, + 124,134,187,116,172,177,83,183,21,155,229,83,82,4,198,163,113,119,245,129,190,112,151,53,16,142,88,161,98,154,53,20, + 53,0,184,210,210,27,60,121,244,236,105,4,179,225,136,213,240,223,6,74,106,154,14,159,241,181,55,95,175,13,250,67, + 19,225,136,213,86,76,39,26,35,250,43,134,157,91,30,21,217,155,237,131,129,169,207,99,84,149,237,195,39,183,241,120, + 252,214,202,135,249,153,97,99,56,31,139,58,63,55,12,58,181,233,185,120,31,41,20,74,40,132,144,8,4,0,137,79, + 67,120,184,148,249,119,176,171,188,158,248,244,184,51,54,57,176,128,49,167,98,81,103,6,64,3,184,94,142,216,199,103, + 40,169,81,66,129,16,8,1,66,1,194,99,217,158,35,189,52,207,193,186,35,86,77,213,158,218,167,99,119,39,194,17, + 171,35,22,117,250,53,64,206,91,37,157,89,192,118,179,216,110,22,165,52,165,37,101,148,4,66,248,45,63,70,184,216, + 94,142,119,75,163,212,132,234,68,107,115,87,201,208,171,71,125,199,175,90,199,52,192,210,143,57,222,39,95,175,119,160, + 125,130,148,35,209,89,137,214,10,191,47,136,79,6,80,248,41,205,149,163,76,144,172,157,49,235,43,108,41,80,130,212, + 2,101,201,63,244,129,167,178,160,44,26,42,154,72,47,102,204,131,151,119,86,178,171,153,141,21,0,90,14,93,91,55, + 80,150,64,105,201,200,92,47,218,39,169,14,237,167,110,251,9,38,223,196,237,196,219,248,87,227,178,169,68,193,226,237, + 39,61,91,206,40,45,178,151,206,117,7,148,82,212,87,54,81,161,247,50,240,252,97,102,49,249,101,196,184,121,103,52, + 198,20,124,142,112,196,50,151,91,187,249,229,37,73,166,82,230,197,232,224,138,237,216,29,177,27,78,127,190,182,160,131, + 53,56,57,155,196,84,98,117,122,118,106,209,219,20,185,160,179,191,37,168,40,175,204,124,251,158,26,54,46,23,54,71, + 254,167,4,66,18,95,78,167,238,197,162,133,145,243,241,27,65,222,9,180,110,118,229,182,0,0,0,0,73,69,78,68, + 174,66,96,130, +}; +const nall::vector<uint8_t> Up = { //size: 652 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,30,73,68,65,84,56,141, + 149,147,79,104,19,65,20,198,191,55,187,51,217,141,133,122,104,76,255,209,130,4,237,193,64,42,168,208,213,138,104,68, + 98,69,45,20,114,107,74,201,73,144,98,22,193,171,199,82,145,160,23,15,69,79,30,165,66,241,226,77,42,94,68,80, + 208,67,41,180,42,149,148,52,137,166,154,38,217,217,25,15,81,172,33,169,246,29,223,251,230,199,124,223,155,33,173,53, + 218,213,201,155,124,30,0,150,102,189,233,118,26,214,110,224,184,60,221,223,21,73,246,117,29,76,58,46,79,239,9,224, + 184,60,26,16,251,178,87,206,76,6,199,70,147,193,128,8,102,29,151,71,255,11,224,184,188,3,132,197,137,115,211,214, + 150,151,199,150,183,137,248,200,37,11,132,69,199,229,29,255,4,16,225,209,232,112,162,167,55,52,72,159,75,31,240,177, + 244,30,157,157,157,20,27,58,209,13,194,195,93,1,142,203,211,253,7,34,137,179,71,199,249,74,254,13,12,198,97,50, + 142,87,107,11,136,13,29,23,161,253,61,137,230,60,216,142,195,81,193,237,108,42,225,218,235,229,101,104,242,32,132,137, + 58,125,199,54,21,241,46,255,28,23,78,95,13,154,166,248,43,15,182,211,247,212,88,198,82,228,161,34,75,16,1,1, + 30,224,40,203,117,8,219,64,65,174,162,168,86,113,254,212,69,139,216,159,60,216,111,223,241,99,227,221,135,250,98,148, + 175,172,193,228,6,56,55,80,81,5,84,141,175,16,54,131,176,25,150,191,189,64,184,55,68,71,14,15,135,137,53,242, + 160,145,140,153,30,232,142,100,111,76,220,177,5,15,64,65,194,135,135,215,185,5,188,45,60,131,100,21,16,35,36,6, + 50,208,90,67,41,160,94,175,225,241,211,249,74,177,180,57,99,18,67,234,83,110,197,158,185,119,185,225,137,163,122,247, + 250,19,171,44,115,240,141,109,112,193,192,76,130,193,9,115,15,110,87,101,77,91,191,236,7,137,33,101,46,205,122,78, + 211,38,180,214,10,165,250,23,48,131,96,112,6,30,104,64,100,77,91,47,231,60,218,245,29,0,128,210,62,126,212,139, + 141,43,251,26,178,174,160,85,235,63,99,182,106,250,74,162,90,219,134,50,53,160,21,124,73,240,189,61,0,164,47,17, + 31,188,6,98,0,49,2,17,246,0,32,108,220,186,63,25,110,37,38,194,70,115,239,39,48,247,197,219,182,208,154,34, + 0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Media { +const nall::vector<uint8_t> Back = { //size: 770 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,45,2,189,124,103,101,0,0,2,143,73, + 68,65,84,56,203,165,83,75,72,84,81,24,254,206,189,215,251,56,231,58,51,62,152,115,238,216,66,169,241,65,153,20, + 101,66,104,17,33,210,178,168,36,104,17,73,45,42,90,181,13,83,194,32,13,119,17,101,49,52,139,138,158,154,101,229, + 34,136,44,180,32,113,81,173,194,69,138,66,216,99,102,238,189,94,157,211,194,81,52,90,8,254,240,111,190,255,255,126, + 190,255,5,172,209,200,42,114,20,0,38,0,9,192,253,7,183,53,0,206,127,72,147,185,4,150,115,146,35,187,0,12, + 0,145,92,28,26,179,25,154,154,26,39,22,153,3,207,95,196,8,33,150,162,40,249,144,80,67,225,112,69,60,190,97, + 255,200,200,135,11,65,16,148,100,179,217,226,104,52,26,41,47,143,31,24,30,30,238,208,120,84,0,0,238,222,185,135, + 195,205,135,32,184,3,69,85,34,233,116,58,182,62,94,118,212,102,246,9,0,129,174,235,215,77,211,204,171,170,170,56, + 98,231,219,167,8,33,243,130,59,29,138,227,136,21,218,253,89,63,42,132,104,222,182,125,107,255,142,218,218,99,125,189, + 253,150,150,167,233,149,149,241,157,117,117,181,189,155,106,170,79,62,126,244,196,84,85,85,229,142,128,198,163,28,148,90, + 0,0,74,41,118,237,105,232,41,42,40,44,107,109,109,43,8,133,66,68,102,37,108,102,27,156,243,203,29,23,47,177, + 130,194,66,34,179,18,148,82,104,170,14,77,56,2,127,82,191,150,20,116,95,233,174,9,135,34,154,55,235,34,157,74, + 129,82,134,150,227,45,164,190,190,193,246,102,189,37,140,217,12,69,5,22,52,193,57,130,57,31,0,96,154,38,166,166, + 167,164,174,235,200,184,41,120,190,15,198,24,92,207,133,231,187,200,184,25,120,158,11,198,24,24,165,40,46,226,80,162, + 130,195,48,116,0,128,97,232,120,248,224,254,183,151,131,3,191,45,147,33,38,214,65,81,84,188,29,122,35,147,201,132, + 171,231,25,75,152,197,44,112,206,161,56,92,44,155,129,133,205,213,91,118,127,249,252,245,106,34,209,243,243,211,232,71, + 55,152,11,64,41,243,77,202,206,222,74,220,152,233,127,214,231,7,115,1,24,165,16,66,64,227,130,195,52,141,92,11, + 6,4,231,136,149,236,235,118,51,153,107,239,222,15,181,143,141,141,30,228,130,207,111,172,172,126,154,158,75,189,154,153, + 254,113,250,118,242,230,153,108,86,18,193,57,52,46,22,214,216,214,126,30,0,192,29,1,85,81,167,33,101,184,180,180, + 244,220,248,196,120,215,235,193,193,206,198,189,194,39,144,105,25,91,223,57,49,57,158,156,248,62,217,197,29,1,34,165, + 92,113,202,158,231,193,178,172,73,0,240,124,95,39,144,139,103,235,27,134,57,227,186,158,10,192,6,36,93,237,51,65, + 74,105,0,0,33,196,95,134,145,133,66,107,180,191,249,146,220,194,180,154,76,242,0,0,0,0,73,69,78,68,174,66, + 96,130, +}; +const nall::vector<uint8_t> Eject = { //size: 628 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,6,73,68,65,84,56,141, + 149,83,77,104,19,97,16,125,179,155,152,118,105,44,65,232,154,221,110,18,130,43,98,2,66,65,5,181,90,35,136,138, + 20,255,218,24,155,24,5,65,17,4,79,94,148,30,60,121,82,207,158,12,90,170,130,224,201,131,182,122,240,162,222,60, + 24,17,84,234,15,173,105,77,211,109,218,36,187,109,50,30,154,72,210,36,37,14,124,48,135,247,30,111,102,222,71,204, + 140,102,69,68,118,0,196,204,86,51,140,109,13,242,122,77,211,54,51,179,64,68,159,153,217,104,89,128,136,236,46,151, + 75,219,179,119,215,83,129,32,189,126,245,230,32,17,37,153,217,172,3,51,115,205,3,64,0,60,39,78,29,127,50,54, + 246,98,233,221,251,183,203,131,225,147,227,0,124,229,113,106,240,141,28,108,216,183,191,247,72,32,24,232,239,235,11,217, + 64,192,246,29,59,119,103,178,115,209,151,207,199,239,1,152,110,234,0,128,164,235,122,111,44,30,205,230,242,57,206,46, + 204,243,124,214,96,211,50,249,252,133,120,174,167,103,219,97,81,20,59,106,56,149,70,81,20,209,239,247,111,58,61,20, + 254,144,252,148,44,230,11,121,78,205,76,241,239,233,73,94,88,204,242,196,247,137,210,153,88,248,71,48,24,220,234,245, + 122,109,117,35,248,124,190,141,221,30,229,202,129,80,104,139,174,235,66,102,46,13,34,2,17,33,151,95,132,170,40,20, + 30,136,200,204,143,110,78,254,156,186,10,224,23,42,75,137,68,34,157,197,98,241,144,236,238,186,127,231,246,221,54,81, + 16,27,158,150,153,113,99,248,122,225,219,151,175,215,28,142,246,135,137,68,34,99,3,0,85,85,59,102,254,164,6,102, + 211,233,117,151,46,95,180,168,106,55,88,213,155,166,101,111,107,119,196,84,165,251,25,128,21,1,143,199,179,228,118,187, + 135,13,195,184,69,68,171,51,81,215,75,146,84,112,58,157,22,80,14,146,166,105,210,232,227,145,143,13,125,55,169,254, + 163,199,2,0,82,21,7,34,0,140,60,24,109,137,124,246,92,180,168,40,138,88,237,160,36,8,194,114,44,62,68,107, + 83,255,21,203,178,92,2,202,87,0,208,9,160,11,43,49,110,73,0,64,26,192,44,85,125,103,250,79,1,6,128,191, + 20,183,247,30,217,9,206,54,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Flash = { //size: 607 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,1,220,73,68,65,84,56,141,133,147,59,107,148,65,24,133,159,249,110, + 43,209,40,134,40,152,8,171,177,49,177,241,2,134,32,66,44,20,4,11,11,27,11,123,241,31,216,139,32,22,234,191, + 208,50,8,130,133,63,32,44,22,65,188,173,96,52,70,99,130,65,55,155,221,253,246,75,230,61,22,123,55,31,241,133, + 153,102,230,60,51,115,206,59,78,18,103,166,103,230,128,171,128,241,255,10,128,183,102,54,187,80,154,175,68,0,146,174, + 92,186,56,19,7,1,4,8,156,90,91,165,1,165,112,136,128,242,167,197,169,229,149,213,57,96,54,234,95,62,57,242, + 156,201,177,175,56,6,133,173,213,214,92,254,121,28,239,175,37,75,223,87,46,0,116,1,50,99,114,236,51,51,215,31, + 18,186,117,0,178,44,35,77,155,164,105,147,102,179,137,56,132,74,143,121,179,234,187,224,46,192,100,56,28,97,60,74, + 90,253,64,218,104,80,175,87,169,109,254,96,227,207,55,178,172,198,248,177,91,4,65,56,240,180,222,13,4,56,71,181, + 178,200,175,229,87,212,106,117,26,141,12,23,12,179,119,120,156,131,133,136,125,251,71,219,15,177,28,128,9,73,84,42, + 155,100,156,35,26,218,102,228,0,36,145,17,199,34,137,33,9,214,144,60,222,231,1,36,22,190,28,5,61,2,183,51, + 187,78,189,91,58,130,247,189,13,81,199,99,147,241,162,116,138,151,175,167,112,78,168,63,9,117,124,2,111,142,98,49, + 199,3,83,11,98,190,35,112,109,173,6,32,32,212,215,110,189,62,48,33,19,166,157,39,247,131,28,96,214,139,49,232, + 233,141,213,245,13,146,56,160,16,135,173,145,244,198,158,36,162,144,132,172,253,222,196,219,191,38,10,228,141,208,109,115, + 251,242,225,60,239,186,117,239,89,21,41,39,5,51,99,203,66,206,222,184,191,43,192,63,189,137,229,196,168,45,111,156, + 152,152,224,99,249,125,238,95,104,93,212,81,44,22,241,38,104,255,92,39,137,211,231,167,31,32,238,8,134,216,181,11, + 218,28,104,2,119,23,74,243,79,254,2,78,177,239,207,22,156,213,133,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Floppy = { //size: 561 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,1,195,73,68,65,84,56,141, + 149,147,191,139,19,65,20,199,63,51,187,185,132,228,20,148,52,70,136,44,28,92,35,40,34,28,136,86,138,165,133,181, + 216,28,162,127,131,98,103,165,157,40,254,3,162,133,216,88,164,201,157,88,168,136,88,92,171,22,129,92,97,227,110,147, + 236,50,155,157,247,198,34,119,249,33,39,196,47,51,195,131,225,251,229,243,30,60,179,117,239,245,91,17,185,201,84,129, + 185,22,235,35,255,172,181,175,98,17,185,241,112,251,42,91,31,158,130,170,9,170,160,74,8,106,56,172,85,65,101,94, + 135,192,206,245,7,60,123,243,249,118,12,32,26,248,253,226,49,65,132,85,165,215,238,3,16,3,70,68,56,245,232,57, + 132,191,169,255,173,202,203,44,0,47,129,147,183,238,174,108,6,144,119,223,23,3,20,17,97,56,28,174,100,78,146,100, + 137,192,136,40,81,20,145,36,201,234,4,94,231,4,114,48,188,193,96,176,146,185,219,237,46,207,160,58,72,251,31,130, + 229,22,188,178,253,228,35,141,236,43,81,177,127,180,195,76,159,73,227,12,121,235,44,27,167,143,207,9,188,8,76,10, + 162,98,159,43,151,47,81,175,215,169,213,106,179,107,173,165,44,75,242,60,103,119,247,61,249,218,6,222,183,0,176,135, + 56,170,138,181,17,237,118,155,126,191,79,175,215,163,217,108,34,34,140,199,99,70,163,17,69,81,128,177,168,42,126,177, + 5,149,128,170,98,12,180,90,173,25,117,154,166,148,101,137,115,14,231,28,101,89,18,66,32,168,80,85,11,67,156,84, + 158,216,78,55,36,203,178,89,64,150,101,75,102,231,28,1,80,85,42,239,167,1,214,152,47,123,63,127,157,223,236,172, + 55,198,89,32,77,83,58,157,14,222,123,210,52,93,50,59,231,32,192,137,99,107,51,2,115,241,206,203,117,99,248,84, + 183,126,243,92,252,173,110,76,76,32,48,61,7,187,177,176,35,134,192,158,191,144,139,169,27,145,240,227,15,253,243,15, + 58,103,73,91,81,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Next = { //size: 771 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,45,27,217,23,207,165,0,0,2,144,73, + 68,65,84,56,203,189,146,205,75,84,81,24,135,127,231,222,59,247,156,123,103,70,156,132,57,231,14,153,180,8,196,116, + 6,197,153,6,218,180,16,170,255,32,136,136,218,180,206,2,147,74,164,54,130,81,88,67,209,70,8,103,81,145,86,138, + 50,72,43,69,173,69,148,203,180,175,77,230,76,126,204,140,51,222,249,242,158,22,142,34,214,50,122,224,133,195,195,121, + 15,191,243,242,2,255,128,26,0,202,62,103,0,48,255,226,255,128,0,176,170,103,7,64,26,64,17,64,109,245,17,9, + 32,95,45,103,207,221,93,52,183,219,68,36,18,233,94,88,88,28,78,165,82,105,69,81,86,92,46,87,33,28,110,239, + 94,92,252,60,146,205,100,62,129,192,112,28,103,67,74,137,83,167,79,46,237,52,39,18,147,1,69,112,11,134,201,46, + 6,67,205,137,104,52,114,206,235,245,114,93,215,3,204,160,231,91,130,71,39,66,109,193,46,143,199,91,111,89,129,90, + 193,183,3,60,123,250,28,0,192,253,2,10,183,4,84,85,85,95,189,124,205,154,67,45,151,162,209,200,104,99,227,145, + 227,154,75,211,199,70,199,141,99,145,200,133,246,112,219,184,16,226,76,177,84,244,239,141,111,89,2,26,247,251,161,83, + 13,138,162,226,193,64,204,179,190,182,230,238,190,126,173,63,159,203,83,41,37,250,250,250,107,178,217,172,183,183,183,231, + 198,161,195,245,103,21,16,0,128,105,154,224,126,14,205,18,2,133,178,13,0,200,231,114,160,6,37,15,99,143,60,211, + 211,83,187,78,115,169,228,78,255,221,3,153,108,186,166,179,243,242,110,2,97,9,104,92,8,172,172,38,65,8,176,158, + 89,5,99,6,32,37,236,130,13,66,128,181,204,42,24,165,144,142,68,50,149,148,140,49,0,0,99,12,130,115,40,156, + 115,24,110,3,138,162,34,32,14,66,119,81,196,227,79,236,153,217,105,185,227,12,230,198,228,155,68,118,100,248,197,55, + 74,117,0,0,165,58,252,130,67,19,66,32,249,235,7,202,149,50,38,38,198,138,95,191,127,217,244,249,234,186,76,211, + 125,191,92,41,179,143,243,239,237,183,115,179,197,236,70,254,113,176,165,117,96,118,110,106,105,123,6,6,44,46,160,9, + 206,241,97,94,146,161,248,96,201,231,171,139,181,134,219,99,110,205,83,172,84,202,247,134,226,131,165,92,62,63,210,26, + 10,223,52,76,211,118,42,21,194,24,173,126,129,130,11,14,141,91,2,170,162,204,52,53,54,93,9,88,13,203,68,193, + 166,4,209,150,39,127,190,59,209,209,113,181,33,208,176,76,128,2,8,201,108,57,91,28,0,110,221,238,217,222,3,33, + 64,108,219,174,174,39,217,4,144,51,12,182,85,44,22,124,0,40,0,71,130,164,25,165,37,0,176,109,219,218,25,226, + 46,82,74,175,148,146,236,115,84,74,73,241,63,248,13,221,115,236,68,32,12,77,214,0,0,0,0,73,69,78,68,174, + 66,96,130, +}; +const nall::vector<uint8_t> Optical = { //size: 931 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,13,215,0, + 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,4,1,17,53,53,42,125,41,75,0,0,3,48,73, + 68,65,84,56,203,109,147,203,79,92,101,24,198,127,223,119,206,249,56,103,206,64,231,82,24,40,101,46,13,139,138,181, + 11,77,105,162,27,218,196,109,53,154,214,148,82,117,211,24,132,181,43,255,0,141,91,40,184,211,136,216,164,186,108,216, + 168,69,161,216,185,64,36,182,44,96,8,129,4,40,48,131,23,152,14,115,174,110,74,98,136,239,242,201,251,203,179,120, + 158,71,112,226,134,134,7,47,3,31,2,125,64,238,133,188,6,76,3,95,141,142,140,229,255,251,47,78,192,99,201,68, + 242,245,219,183,63,216,239,232,232,120,213,178,172,102,128,122,189,94,219,218,218,124,50,49,241,77,164,186,95,157,27,29, + 25,27,228,127,156,167,30,205,205,126,231,121,94,176,180,180,20,46,44,44,132,165,82,41,92,92,92,12,203,229,114,88, + 173,86,67,223,247,131,217,217,153,169,161,225,193,169,99,78,59,118,238,239,31,16,47,157,239,185,145,207,231,229,193,193, + 1,190,239,35,132,64,8,129,97,24,72,41,105,52,26,34,155,205,117,39,18,137,253,136,109,190,86,44,148,30,104,67, + 195,131,151,147,137,228,199,183,250,7,174,46,47,47,75,223,247,169,213,14,57,172,29,80,171,29,80,175,63,71,211,53, + 154,148,66,211,116,194,48,164,187,187,187,51,159,127,28,121,229,226,133,121,173,183,247,210,167,119,238,124,148,118,29,55, + 85,175,215,113,93,7,93,55,104,110,110,33,213,214,78,107,107,27,137,68,146,74,117,151,38,213,132,227,184,248,190,79, + 170,45,229,46,46,254,110,233,64,223,217,206,179,185,74,165,130,82,10,215,115,137,218,205,172,174,174,146,47,252,6,16, + 222,184,254,158,200,229,206,177,82,94,38,17,79,226,121,30,103,206,116,158,6,250,36,144,51,77,83,41,165,48,77,19, + 33,32,30,143,147,47,60,14,35,150,125,209,247,253,214,239,127,184,31,196,98,49,170,213,10,158,231,225,56,14,134,97, + 24,64,78,63,142,83,41,69,16,4,232,186,142,109,219,72,41,130,63,255,218,223,0,208,52,205,1,76,199,113,240,60, + 15,33,4,190,239,11,64,72,96,173,209,104,120,74,41,148,82,156,58,21,163,209,104,240,238,59,215,165,82,234,153,174, + 235,171,111,93,123,91,173,175,175,163,84,19,174,235,226,121,30,135,135,135,62,176,166,3,211,219,219,219,201,116,58,221, + 10,208,158,106,103,119,111,135,158,158,30,241,249,103,95,152,128,185,177,177,193,207,15,127,36,151,61,135,235,186,68,34, + 17,118,118,119,234,192,67,173,183,247,82,165,188,186,114,237,74,223,213,184,166,105,232,186,142,101,90,236,85,246,152,159, + 47,242,228,201,31,84,170,21,218,90,83,8,33,145,82,210,213,213,197,189,123,147,255,212,143,234,159,104,197,66,105,243, + 229,11,61,231,99,177,88,71,186,43,221,34,132,64,74,13,93,55,136,70,155,137,199,19,216,118,20,41,37,71,71,71, + 100,179,89,138,197,194,223,79,151,158,222,191,59,58,254,165,6,80,44,148,30,88,17,243,77,219,142,158,206,100,50,166, + 148,18,199,113,8,130,128,48,12,1,176,44,139,76,38,195,220,220,35,231,151,95,167,103,238,142,142,223,4,52,237,184, + 211,197,66,233,219,104,115,36,59,59,59,147,75,165,218,149,105,154,178,165,165,5,203,178,0,216,220,218,244,39,39,39, + 158,175,148,87,190,30,29,25,187,249,2,11,197,137,101,234,183,6,250,223,176,237,200,251,186,166,95,17,82,116,9,33, + 68,16,4,155,158,231,253,100,24,198,248,201,57,255,11,186,149,81,110,74,152,180,58,0,0,0,0,73,69,78,68,174, + 66,96,130, +}; +const nall::vector<uint8_t> Pause = { //size: 464 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,32,43,74,96,129,68,0,0,1,93,73, + 68,65,84,56,203,205,146,75,110,20,65,12,134,191,42,187,153,238,40,234,213,216,138,56,64,114,12,136,224,72,72,112, + 164,40,202,25,0,133,59,68,16,16,172,103,150,72,48,105,250,97,22,253,200,0,19,177,4,47,74,165,175,92,191,126, + 63,224,95,71,218,187,159,254,61,59,45,159,34,226,35,16,58,191,173,215,107,206,159,61,121,191,47,250,246,245,245,89, + 12,67,62,127,254,244,102,159,95,191,121,119,182,217,110,19,16,121,134,102,134,170,198,229,197,21,151,23,87,168,234,224, + 102,172,15,112,115,95,76,45,14,220,29,17,161,239,123,62,125,249,128,136,96,238,116,93,183,240,219,207,55,35,55,251, + 83,192,204,16,17,118,119,223,41,180,64,84,48,115,186,182,69,68,184,107,118,136,40,162,130,63,36,208,180,59,154,166, + 65,84,16,17,220,215,64,26,118,205,55,218,246,7,229,170,90,156,205,113,223,3,31,29,52,109,67,34,33,121,116,48, + 246,70,136,8,202,85,137,228,95,29,44,2,110,62,38,14,3,67,12,168,42,102,134,79,165,229,44,148,101,133,170,96, + 110,15,59,32,160,239,187,169,4,95,184,100,229,81,177,154,154,120,104,10,54,78,225,228,228,49,146,5,45,70,7,36, + 16,17,170,163,106,226,197,92,66,28,154,66,188,124,245,2,0,201,57,215,245,81,189,42,143,191,254,206,143,235,170,158, + 5,150,237,218,108,55,167,68,34,165,105,99,35,17,41,72,115,74,26,143,116,191,185,183,252,23,241,19,86,58,109,31, + 74,23,56,251,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Play = { //size: 660 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,36,33,206,217,173,94,0,0,2,33,73, + 68,65,84,56,203,157,147,75,107,19,1,20,133,207,60,50,201,36,77,38,49,153,105,98,19,19,90,73,48,35,186,74, + 209,212,72,82,108,138,5,193,103,116,39,88,16,193,66,182,221,249,7,92,244,23,72,151,130,47,186,114,163,136,32,46, + 12,66,77,21,177,88,108,160,17,74,250,208,164,51,77,50,51,185,46,196,166,98,41,177,119,117,238,230,131,115,239,57, + 64,119,120,28,96,184,93,58,2,192,1,160,9,128,122,5,176,187,151,252,248,216,235,96,48,152,6,224,235,21,192,252, + 17,138,44,31,25,62,149,250,198,48,76,199,178,204,47,229,15,159,110,182,90,173,207,181,90,77,239,201,66,52,22,147, + 188,62,169,248,236,233,28,239,145,60,254,106,117,101,178,191,95,25,233,48,244,102,32,52,80,175,213,106,180,47,32,169, + 170,146,40,58,138,215,11,55,216,72,100,128,157,56,63,193,245,185,221,225,141,245,245,219,162,83,76,58,69,215,187,100, + 242,88,99,121,185,178,55,96,56,149,146,56,142,41,94,189,114,141,5,1,174,62,55,212,164,202,165,79,167,5,151,83, + 76,252,168,255,156,52,45,107,117,104,112,168,178,180,180,212,252,7,144,203,102,165,182,217,46,94,186,120,153,221,210,235, + 48,140,54,12,163,13,187,195,142,120,34,193,229,243,227,14,34,186,64,48,83,137,120,252,125,230,76,166,81,42,149,204, + 157,223,7,100,5,13,173,14,0,208,116,13,32,2,1,176,241,54,120,61,62,232,164,131,200,98,252,135,252,134,215,19, + 144,120,142,117,3,104,238,0,20,69,70,245,251,111,127,186,190,5,155,205,142,195,193,48,44,211,196,236,236,3,107,241, + 235,226,102,44,22,189,163,4,66,111,1,90,187,59,53,101,252,149,62,89,150,201,38,8,0,8,209,240,32,120,158,199, + 227,39,143,172,133,143,11,70,60,113,244,94,102,36,251,176,211,233,172,22,10,133,22,246,138,175,44,43,16,4,27,117, + 136,240,242,213,11,42,151,231,45,183,199,243,60,123,118,116,90,16,236,149,92,46,171,237,245,198,46,64,9,64,20,237, + 52,51,115,223,210,116,109,101,52,59,122,43,32,135,230,143,171,234,198,126,65,234,222,32,32,99,123,187,181,121,110,44, + 53,125,66,61,57,7,48,155,138,162,80,207,81,38,162,48,0,3,192,26,195,48,214,127,215,146,136,216,131,212,249,23, + 48,70,193,31,65,224,78,98,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Record = { //size: 653 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,31,73,68,65,84,56,141, + 165,146,191,79,83,81,20,199,191,231,222,190,246,181,233,15,250,196,244,17,219,69,23,41,97,0,177,9,152,72,28,28, + 193,137,85,7,255,2,13,187,131,110,44,46,50,59,43,115,19,226,212,116,168,77,108,9,67,141,44,150,0,173,37,64, + 109,74,222,123,188,182,247,29,135,214,154,98,49,38,124,147,179,220,156,243,201,61,223,243,37,102,198,117,36,174,53,13, + 192,55,238,177,64,20,212,128,199,18,88,80,64,18,64,81,2,249,57,230,175,151,123,233,242,10,59,68,15,69,52,250, + 97,106,109,205,8,77,79,251,68,56,76,238,254,190,247,51,151,235,182,10,133,247,12,188,188,199,108,143,5,148,136,30, + 197,102,103,179,169,245,117,189,231,186,232,53,155,240,92,23,50,24,132,223,52,225,148,74,170,186,185,249,101,190,219,93, + 196,96,112,8,40,18,69,3,177,216,247,187,27,27,55,156,131,3,168,118,27,96,238,151,231,1,74,33,152,78,227,60, + 159,239,214,183,182,94,204,51,191,27,49,81,2,79,110,173,174,70,187,167,167,232,213,235,128,101,1,142,3,216,54,96, + 89,96,203,130,93,46,35,190,188,172,105,209,232,171,191,76,20,192,3,61,153,212,46,118,119,161,26,13,144,223,15,105, + 24,32,162,225,15,188,94,15,189,86,11,122,42,101,20,136,140,69,230,230,159,43,16,221,145,74,161,83,46,131,29,7, + 66,8,176,148,16,145,8,40,18,1,2,1,176,235,66,213,106,240,199,98,42,208,191,78,115,184,130,98,46,116,78,78, + 88,155,156,132,32,130,16,2,130,8,100,89,64,163,1,175,90,133,119,116,4,65,132,139,90,77,234,192,183,17,15,8, + 200,183,247,246,58,250,204,12,136,8,52,128,72,41,251,48,33,160,153,38,72,215,97,55,26,149,52,115,103,4,176,192, + 252,233,172,88,252,204,68,28,202,100,32,164,4,6,32,16,65,24,6,66,75,75,168,103,179,29,184,238,243,171,114,48, + 165,133,195,229,228,202,202,77,221,52,165,58,62,6,92,23,52,49,1,17,143,163,190,189,221,57,175,84,94,207,41,245, + 230,202,36,150,136,66,36,196,91,61,145,120,22,74,165,60,95,56,76,78,173,38,156,195,195,31,174,109,63,189,207,156, + 251,103,148,127,235,35,145,188,13,164,25,72,120,192,78,134,249,108,92,223,149,128,255,213,47,18,206,244,197,113,23,107, + 46,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Rewind = { //size: 764 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,39,32,146,243,206,11,0,0,2,137,73, + 68,65,84,56,203,189,147,203,75,84,97,24,198,159,239,59,183,153,243,157,51,206,120,59,103,108,186,200,232,228,128,102, + 58,102,74,58,16,65,16,109,211,69,101,33,129,45,170,93,23,108,17,210,133,90,212,34,250,11,2,105,85,102,19,66, + 132,82,139,194,114,22,225,37,44,138,74,37,203,209,105,200,60,115,142,142,206,215,102,144,2,187,64,208,11,239,230,247, + 240,91,189,239,3,252,135,161,0,220,191,224,30,241,15,34,203,173,3,192,206,113,5,128,55,151,67,88,67,36,30,143, + 238,82,20,197,87,84,84,92,29,137,212,118,204,37,147,143,100,89,6,33,196,160,148,110,240,251,253,129,186,186,72,199, + 236,108,226,9,249,209,12,133,66,50,231,220,107,89,214,250,96,121,105,155,198,180,14,0,153,145,225,177,45,182,109,123, + 40,165,82,56,188,121,191,166,107,199,8,33,43,175,199,223,148,83,0,136,70,163,180,185,57,234,181,109,39,236,55,205, + 3,117,219,106,251,182,215,215,183,223,143,245,185,37,89,146,40,165,222,138,138,242,29,13,13,245,177,202,234,170,163,189, + 119,239,185,4,65,16,12,191,9,177,181,165,213,55,58,54,186,33,176,49,16,138,238,108,58,83,224,203,47,237,234,58, + 239,243,120,60,132,103,57,152,202,196,166,230,198,27,76,211,106,46,95,186,194,124,249,249,132,103,57,84,85,133,40,200, + 16,13,191,225,42,44,246,157,211,116,125,215,169,147,167,89,158,199,43,58,75,54,172,133,5,168,42,131,174,107,66,87, + 215,133,198,194,130,2,209,89,114,86,57,211,24,10,124,110,80,211,48,225,86,93,94,213,237,146,102,18,51,220,118,210, + 176,172,111,248,242,53,9,66,0,93,215,179,51,137,207,220,89,180,145,78,91,72,229,56,83,85,24,166,9,106,154,230, + 76,184,162,170,197,178,210,157,61,119,110,191,127,216,255,96,222,237,98,40,49,3,160,84,128,172,72,188,183,183,231,109, + 119,247,77,91,150,148,85,238,102,110,24,134,1,33,22,139,241,88,44,102,119,118,158,29,46,49,215,221,26,123,57,42, + 189,26,31,171,20,37,145,23,23,27,210,80,252,121,166,166,58,18,89,90,201,188,27,124,246,180,105,110,118,150,6,131, + 101,226,208,208,224,114,89,48,116,253,167,51,198,227,113,2,112,150,78,219,133,47,70,226,23,53,198,90,178,28,153,173, + 149,181,65,14,80,107,121,65,73,37,146,199,83,169,228,137,169,169,143,124,207,238,189,165,100,173,23,156,156,156,164,224, + 60,239,195,244,196,166,199,253,253,87,15,31,58,178,143,3,243,4,156,241,44,212,233,79,19,102,255,192,192,181,182,182, + 246,131,228,119,37,112,22,23,101,2,238,5,144,81,20,87,10,0,108,219,17,0,104,0,87,255,186,77,156,115,101,13, + 70,56,231,250,63,87,245,59,186,53,233,69,8,225,63,138,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Skip = { //size: 782 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,39,8,167,70,102,241,0,0,2,155,73, + 68,65,84,56,203,189,147,59,76,19,113,28,199,191,255,123,244,238,218,43,82,192,222,181,64,33,62,18,104,4,68,211, + 68,133,193,129,81,6,28,28,25,157,92,140,38,74,84,210,85,33,44,190,66,28,12,218,184,24,37,6,69,67,116,84, + 112,144,71,124,64,76,120,212,96,160,143,163,244,122,215,235,113,45,127,23,32,81,97,51,126,167,95,62,223,228,51,125, + 127,192,63,72,25,0,102,23,46,237,193,127,11,11,160,2,128,12,192,3,160,8,160,180,213,201,0,246,1,32,91,156, + 238,42,240,120,220,222,246,246,182,30,199,113,82,133,66,65,230,121,158,147,36,201,113,9,2,215,214,118,170,183,88,44, + 102,1,106,10,130,80,178,237,141,210,95,130,80,109,200,171,6,149,135,138,226,239,246,251,247,219,186,158,91,100,24,166, + 92,150,101,82,93,19,28,84,20,127,119,69,165,207,109,26,249,21,85,85,139,85,85,85,142,166,105,59,34,182,49,28, + 246,122,60,238,139,207,159,13,139,147,51,83,205,101,178,124,214,227,145,150,114,57,35,93,93,27,60,255,98,120,68,154, + 155,251,22,22,68,225,28,207,242,122,42,173,25,45,45,45,118,125,125,221,70,60,30,167,164,171,171,43,224,18,184,133, + 216,227,39,34,97,8,50,107,107,180,231,218,85,211,52,140,41,128,156,120,52,20,227,9,67,160,235,58,141,70,123,51, + 90,102,109,49,153,76,221,92,142,47,127,111,58,210,244,131,11,168,42,10,142,5,0,48,13,3,130,36,144,123,119,238, + 203,105,77,59,25,141,222,96,182,57,199,179,164,191,111,160,34,171,175,151,245,245,223,122,112,248,224,129,119,44,235,186, + 192,41,170,138,180,150,0,33,64,38,171,65,20,37,128,82,36,146,171,212,235,245,110,18,2,102,45,171,65,20,4,208, + 77,138,68,50,65,221,146,200,151,74,78,121,69,185,31,156,162,40,48,11,58,24,134,69,80,173,129,97,26,136,197,134, + 172,68,50,181,228,18,248,67,219,220,178,242,24,123,251,70,159,253,58,187,106,154,249,187,141,13,77,49,2,178,206,169, + 170,138,68,234,39,156,162,131,209,209,17,123,97,105,62,239,243,85,94,57,222,90,255,114,230,243,212,130,83,116,248,233, + 153,79,214,196,248,7,91,207,153,131,199,142,70,6,40,161,122,231,153,206,2,0,144,137,241,241,192,235,177,87,139,181, + 181,213,196,231,171,188,237,243,87,222,241,112,178,77,128,205,233,47,147,243,12,1,111,152,230,211,214,230,200,117,183,91, + 74,3,196,140,68,34,59,163,226,148,128,10,150,97,222,135,27,194,151,130,129,186,85,194,32,79,65,76,2,148,173,142, + 173,124,60,221,209,113,185,62,88,183,4,66,178,161,80,104,243,207,33,17,203,178,2,91,103,30,128,33,73,98,9,0, + 108,187,224,3,192,83,144,117,81,16,54,246,124,6,74,169,151,82,74,118,225,2,254,71,126,1,54,156,22,72,126,132, + 128,72,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Stop = { //size: 429 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,12,6,17,40,46,242,211,255,195,0,0,1,58,73, + 68,65,84,56,203,205,146,95,74,3,49,16,135,191,236,164,175,22,10,102,60,128,88,240,20,34,30,66,196,75,8,226, + 137,68,188,130,136,215,16,84,4,69,41,138,62,172,44,180,187,221,221,196,135,253,171,173,138,79,26,8,204,100,50,95, + 230,55,25,248,235,101,122,246,198,47,115,111,128,96,27,111,52,26,177,189,179,117,105,140,145,159,50,207,207,46,198,113, + 28,155,15,0,117,142,193,96,96,78,142,79,191,77,222,219,223,245,170,74,28,199,0,68,77,96,213,41,34,213,227,183, + 119,87,60,78,238,121,121,125,230,45,137,73,179,20,239,61,0,214,90,156,106,11,108,1,170,29,64,196,214,91,144,72, + 48,192,60,207,234,152,160,206,45,2,156,186,22,16,69,2,6,124,8,20,101,65,154,165,204,102,211,10,96,5,183,12, + 176,214,171,32,4,79,89,150,20,197,156,44,75,153,165,83,166,105,5,176,34,104,79,130,237,122,224,152,60,61,0,80, + 150,37,222,123,202,162,226,251,26,216,200,115,234,22,1,234,58,9,121,158,19,8,24,32,16,240,222,183,77,20,43,168, + 91,82,129,246,122,48,94,223,252,242,27,165,147,16,62,85,160,136,72,56,60,58,248,118,14,36,138,34,231,58,64,59, + 202,73,146,212,163,28,170,227,80,217,193,84,66,42,191,185,17,24,174,12,175,249,23,235,29,41,108,117,184,218,69,135, + 206,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Place { +const nall::vector<uint8_t> Bookmarks = { //size: 753 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,10,6,3,42,40,185,100,186,202,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,2,61, + 73,68,65,84,56,203,149,147,77,79,83,65,20,134,159,153,222,185,247,246,131,182,96,63,80,106,20,98,76,140,49,38, + 198,104,252,13,154,96,220,152,16,226,194,133,127,193,164,11,8,44,76,252,31,132,61,145,159,96,226,194,132,13,10,6, + 48,86,180,84,161,32,45,183,237,237,237,244,142,139,98,161,194,66,79,50,155,153,57,207,188,239,57,103,4,192,84,113, + 97,14,152,225,223,99,126,241,213,244,44,128,152,42,46,204,141,72,61,243,226,249,67,60,95,227,181,58,4,90,83,243, + 218,0,72,41,0,16,199,153,13,63,160,94,89,230,217,189,34,169,236,228,75,11,152,121,252,232,65,24,134,70,118,131, + 14,217,84,140,141,242,62,141,202,1,67,229,61,84,171,77,168,34,120,163,25,90,153,20,249,145,56,117,32,149,157,164, + 182,183,244,218,2,112,28,71,26,224,224,208,35,26,115,161,222,36,93,170,80,187,50,74,144,136,97,249,109,82,165,10, + 93,21,129,145,56,49,39,232,123,177,0,92,87,1,134,150,223,59,144,95,42,212,199,178,68,130,14,185,213,45,140,16, + 252,186,86,32,249,109,23,198,243,68,237,206,32,192,118,108,194,110,216,223,20,135,30,237,66,142,204,90,137,122,33,71, + 226,199,62,218,181,81,77,31,128,119,159,124,58,106,131,143,43,49,36,128,173,20,230,84,161,8,13,70,8,164,238,98, + 34,17,16,2,231,168,137,142,218,103,218,33,1,132,16,128,57,33,196,93,84,195,199,31,30,234,189,110,43,146,219,63, + 169,95,206,247,248,36,6,45,156,68,143,16,142,143,146,220,44,83,187,122,17,29,117,64,136,129,91,110,73,241,100,17, + 110,175,55,123,0,131,1,3,185,11,41,0,76,54,77,189,173,73,126,223,69,53,90,116,109,69,245,230,196,185,19,213, + 83,96,64,41,139,116,58,129,223,209,228,135,227,36,163,14,92,31,235,235,74,13,104,252,11,224,53,90,188,89,126,139, + 37,13,161,233,45,173,13,66,10,108,21,65,8,129,0,186,221,144,175,229,106,152,111,30,201,207,235,235,0,79,45,128, + 15,171,91,220,191,17,239,143,237,121,33,165,164,41,210,108,236,7,114,123,252,22,119,143,197,88,0,135,94,131,137,220, + 16,133,194,165,51,137,226,84,1,215,54,119,206,173,193,252,251,205,234,140,110,53,195,157,106,32,93,87,161,59,122,192, + 240,31,132,238,134,76,222,201,152,165,149,170,56,221,55,57,85,92,152,253,207,239,204,226,171,105,1,240,27,115,187,219, + 217,106,190,108,255,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Desktop = { //size: 722 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,2,23,0,42,10,182,151,62,76,0,0,2,95,73, + 68,65,84,56,203,165,147,93,76,207,81,24,199,63,231,247,79,180,48,179,24,27,235,154,102,46,136,205,172,197,52,46, + 112,161,194,13,174,72,102,140,214,100,105,11,115,229,109,35,204,186,112,41,11,139,27,47,155,41,169,141,44,111,49,47, + 75,72,249,139,213,164,214,239,229,156,231,113,81,254,254,255,113,97,115,110,206,246,61,223,231,57,159,243,221,115,204,162, + 101,197,84,87,149,51,240,125,8,128,246,246,118,94,63,171,227,111,107,199,238,179,188,121,215,3,64,247,135,78,154,239, + 63,192,44,204,91,87,239,197,98,69,201,198,135,119,235,99,207,59,26,5,64,84,177,97,200,246,178,218,67,198,152,170, + 100,159,170,222,51,139,150,21,235,191,16,244,13,206,166,186,106,255,31,4,105,0,111,222,245,208,210,246,130,129,175,189, + 184,225,247,156,58,126,44,81,248,139,64,129,178,202,163,108,43,41,165,225,102,43,3,95,123,1,70,27,0,163,66,24, + 167,114,95,49,95,250,186,82,110,247,253,17,172,141,216,185,117,49,53,231,207,49,61,123,126,226,204,251,133,67,24,167, + 98,239,154,148,66,21,193,218,8,99,60,98,177,52,198,165,167,179,107,251,18,250,62,60,77,120,98,51,179,231,204,253, + 220,211,153,115,160,124,19,198,132,191,209,69,80,21,84,65,85,176,206,34,206,33,78,200,156,48,204,203,87,189,136,198, + 14,123,143,154,174,108,152,58,49,78,86,214,20,0,156,115,88,107,113,206,34,162,168,42,65,24,160,162,88,107,241,131, + 17,188,152,146,53,169,151,182,198,203,7,19,25,8,58,214,192,162,40,6,16,129,48,244,113,206,33,170,132,81,136,136, + 36,191,210,75,203,205,47,186,248,237,71,72,198,248,76,6,198,8,140,49,40,6,107,35,48,6,85,37,138,2,212,9, + 34,14,128,254,161,25,228,230,23,174,242,140,49,27,243,150,175,165,116,207,73,84,21,17,71,24,133,248,254,8,65,224, + 19,4,62,97,20,224,156,224,156,195,57,199,195,39,131,108,44,94,143,49,222,117,15,160,171,59,206,226,165,43,57,81, + 115,11,39,163,70,113,14,17,193,217,209,93,196,225,196,113,237,198,123,118,148,150,209,252,248,99,234,28,116,117,199,153, + 183,160,128,51,181,119,88,189,98,22,126,56,12,40,145,181,140,197,67,75,219,32,155,183,148,112,225,210,237,68,8,105, + 201,137,116,117,199,153,144,145,73,221,181,183,76,155,252,41,101,38,134,252,41,172,40,40,162,225,102,107,138,110,114,243, + 11,59,140,241,114,146,69,17,119,228,81,211,213,211,64,255,152,52,46,55,191,168,226,111,159,137,255,93,63,1,185,254, + 98,48,219,255,91,223,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Home = { //size: 679 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,36,73,68,65,84,56,141,165,146,77,107,83,65,20,134,159,51,115, + 107,211,196,170,88,48,196,66,193,69,237,34,27,161,226,162,123,201,170,139,32,116,235,47,208,189,208,63,224,198,93,221, + 250,55,68,20,226,78,40,24,237,198,34,149,86,41,77,73,168,54,183,105,155,59,51,119,142,139,124,180,129,226,198,179, + 25,230,204,57,207,249,120,71,106,181,26,255,99,201,242,242,242,27,85,93,189,226,237,76,85,159,52,155,205,205,127,2, + 98,140,245,122,189,126,51,198,72,140,17,85,5,224,248,248,120,174,209,104,108,84,171,213,231,163,96,239,61,198,152,252, + 224,224,224,115,154,166,57,64,226,189,215,16,2,157,78,135,60,207,199,16,99,12,149,74,165,10,188,27,65,1,122,189, + 94,146,231,249,171,52,77,215,47,1,60,33,4,98,140,19,144,114,185,92,44,20,10,20,139,69,172,181,24,99,104,181, + 90,180,219,237,197,241,8,33,132,24,66,206,198,71,199,105,118,81,9,4,0,165,15,244,199,94,85,3,172,172,177,176, + 178,102,173,249,153,120,239,213,57,71,47,83,94,62,123,140,200,48,240,242,166,116,226,6,128,11,202,250,235,15,11,137, + 115,46,134,16,0,197,26,248,178,219,189,220,192,232,152,220,188,21,238,149,75,32,170,73,8,1,239,61,34,130,53,130, + 181,23,41,215,11,9,143,22,111,147,24,225,211,247,223,164,231,126,160,70,136,104,84,4,209,196,123,31,189,247,160,138, + 17,97,202,10,198,8,247,43,215,89,186,59,139,53,3,96,237,65,153,111,251,41,95,247,186,184,160,152,129,127,0,8, + 97,208,65,223,229,220,185,49,205,210,252,44,51,215,44,103,46,31,143,175,170,204,207,205,112,171,52,197,214,94,151,204, + 197,49,64,67,200,17,73,232,164,25,219,251,39,108,238,252,97,245,97,101,84,101,176,11,129,204,71,222,54,15,177,70, + 88,152,155,25,0,66,8,209,57,7,106,217,105,157,112,212,203,80,224,168,231,198,138,140,150,233,66,36,61,247,88,35, + 28,118,135,35,136,72,140,49,34,34,100,62,82,156,78,0,232,251,124,152,120,65,201,163,82,154,78,16,17,206,92,0, + 200,19,85,101,247,40,34,2,91,63,90,227,224,237,189,195,73,9,135,237,140,190,245,233,105,31,129,205,36,78,149,26, + 239,119,103,159,130,178,255,171,125,133,234,87,155,8,109,17,243,226,47,238,171,54,255,32,151,176,79,0,0,0,0,73, + 69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Server = { //size: 642 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,96,0,96,0,96,101,20,102,74,0,0,0,9,112,72,89,115,0,0,11,18,0, + 0,11,18,1,210,221,126,252,0,0,0,7,116,73,77,69,7,213,5,24,13,41,13,225,69,167,57,0,0,0,62,116, + 69,88,116,67,111,109,109,101,110,116,0,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80, + 10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83,116,101,105,110,101, + 114,39,51,239,88,0,0,1,197,73,68,65,84,56,203,141,146,189,138,34,81,16,133,191,235,54,218,6,6,98,172,160, + 145,8,3,254,177,6,194,226,62,192,198,70,3,247,5,140,134,13,124,2,31,192,23,16,246,17,54,22,100,2,3,55, + 145,53,53,145,246,47,16,49,209,139,77,119,215,6,59,221,171,163,50,123,224,66,113,239,61,167,234,84,149,226,26,79, + 90,235,223,124,128,193,96,240,25,248,197,29,178,44,151,75,241,125,95,124,223,23,207,243,196,117,93,113,93,87,140,49, + 98,140,145,241,120,44,90,107,1,190,94,177,181,214,114,62,159,175,200,247,4,78,167,147,236,247,251,80,4,235,82,68, + 41,197,104,52,250,200,1,173,86,43,138,173,247,143,167,211,137,114,185,252,144,60,157,78,49,198,252,19,208,90,127,1, + 190,135,23,201,100,18,99,12,34,130,136,16,4,1,34,130,239,251,127,9,150,69,16,4,161,237,159,86,183,219,5,160, + 215,235,1,112,60,30,153,207,231,0,136,72,148,41,140,67,33,128,78,167,51,179,66,98,136,70,163,17,125,10,43,80, + 74,33,34,24,99,136,199,227,40,165,0,232,247,251,79,214,96,48,120,5,94,181,214,98,89,22,195,225,144,213,106,69, + 62,159,167,84,42,177,221,110,241,125,63,170,64,68,200,102,179,225,62,124,139,189,111,146,227,56,20,139,69,102,179,25, + 74,41,226,241,56,133,66,33,58,151,22,110,166,32,34,20,10,5,38,147,9,237,118,27,219,182,113,93,151,197,98,17, + 85,96,219,54,135,195,225,241,24,235,245,58,213,106,53,234,124,46,151,187,219,204,55,124,186,177,224,121,30,65,16,68, + 222,29,199,193,243,60,28,199,1,136,70,248,134,68,236,209,194,236,118,59,0,54,155,13,137,68,130,245,122,77,44,22, + 139,54,54,220,187,43,11,135,195,129,76,38,3,64,165,82,33,149,74,209,108,54,73,165,82,212,106,53,210,233,244,77, + 162,75,129,231,151,151,151,31,252,63,158,1,254,0,124,80,17,254,250,115,5,147,0,0,0,0,73,69,78,68,174,66, + 96,130, +}; +const nall::vector<uint8_t> Share = { //size: 697 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, + 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, + 97,112,101,46,111,114,103,155,238,60,26,0,0,2,54,73,68,65,84,56,141,125,147,207,75,212,65,20,192,63,111,230, + 107,172,38,90,80,45,66,132,68,157,194,91,93,130,46,65,7,15,29,36,242,210,41,130,14,65,157,69,188,117,144,16, + 58,85,215,46,5,37,228,31,32,84,22,221,52,163,31,134,66,96,65,184,225,82,173,185,201,126,191,243,102,94,135,93, + 55,53,233,93,30,243,230,205,231,253,28,25,29,29,189,111,102,231,249,87,54,204,236,194,248,248,248,236,46,119,109,145, + 145,145,145,218,208,208,80,111,74,137,148,18,102,6,64,173,86,99,102,102,102,54,165,116,99,211,57,132,128,115,46,174, + 172,172,204,79,78,78,70,128,44,132,96,170,74,181,90,37,198,216,134,56,231,232,235,235,59,1,76,111,66,1,234,245, + 122,22,99,188,13,140,109,1,4,84,149,148,210,54,72,185,92,238,42,149,74,116,117,117,225,189,199,57,71,165,82,97, + 117,117,245,248,38,48,83,213,164,26,185,251,162,224,119,254,55,18,8,0,70,3,104,180,173,102,14,56,61,124,234,234, + 195,97,239,221,151,44,132,96,69,81,80,207,141,91,215,207,33,210,114,220,218,41,219,118,2,160,80,99,236,222,211,35, + 89,81,20,73,85,1,35,115,240,102,121,173,25,95,118,233,120,75,59,47,28,45,239,5,49,203,84,149,16,2,34,130, + 115,130,247,187,188,220,33,170,9,51,16,196,178,16,66,10,33,128,25,78,132,142,255,0,52,26,121,72,196,100,248,102, + 138,77,128,106,51,131,70,17,145,86,201,26,141,104,70,74,70,50,35,104,83,3,100,94,104,20,218,6,152,106,68,36, + 163,250,43,167,242,163,65,174,233,191,37,100,94,168,174,229,77,128,170,166,162,40,192,60,159,42,235,124,175,231,237,9, + 104,99,125,219,56,178,206,110,64,240,78,248,182,214,42,65,68,82,140,17,193,104,228,129,206,142,102,15,150,95,62,96, + 189,178,216,126,159,98,162,251,80,63,199,206,94,193,249,140,141,70,142,64,204,82,74,242,122,225,51,165,159,57,243,207, + 22,219,209,194,215,247,76,76,76,48,55,55,215,222,204,39,83,83,124,120,254,24,201,246,16,130,146,113,96,73,222,190, + 91,88,46,237,235,235,223,89,231,181,203,23,25,24,24,64,90,11,97,102,44,46,46,113,115,226,14,61,189,251,241,94, + 180,167,179,227,149,12,14,14,30,78,41,93,2,14,110,5,152,217,25,51,59,185,213,230,156,251,40,34,211,214,252,93, + 234,189,127,244,7,187,71,87,220,223,105,176,149,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +namespace Prompt { +const nall::vector<uint8_t> Error = { //size: 653 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,10,9,50,14,147,83,180,176,0,0,2,26,73, + 68,65,84,56,203,157,147,189,79,147,81,20,198,127,247,109,11,229,163,190,160,196,26,77,160,104,155,2,182,11,196,148, + 68,135,142,186,50,105,210,129,17,254,34,59,50,116,102,35,178,144,64,88,68,7,48,146,22,154,104,99,248,176,36,164, + 45,77,91,40,246,61,199,225,125,75,16,137,26,79,114,115,147,155,243,252,158,228,57,247,24,110,84,14,82,192,60,144, + 6,198,189,231,18,176,14,44,101,96,235,122,191,185,33,126,59,28,10,45,76,38,147,4,195,97,124,3,3,168,42,157, + 179,51,206,203,101,138,133,2,213,102,51,155,129,197,223,0,57,120,55,157,76,190,28,153,153,225,114,123,27,231,244,20, + 28,7,85,69,12,88,67,119,241,79,77,82,221,221,229,83,177,184,154,129,87,0,190,174,243,116,50,249,250,94,44,70, + 123,115,19,109,52,64,4,85,65,69,65,4,105,182,232,28,124,163,63,22,195,182,172,232,139,106,245,193,50,172,152,28, + 164,134,67,161,247,207,230,230,184,88,91,67,157,14,170,138,42,168,122,98,5,197,133,169,49,4,83,41,62,111,108,80, + 107,181,102,45,96,126,50,145,224,114,103,7,117,28,16,80,1,21,113,15,234,129,20,84,193,113,184,200,231,121,60,22, + 1,152,247,3,233,96,248,62,63,62,124,68,69,25,43,127,231,79,181,111,223,65,170,53,2,15,31,1,164,253,192,184, + 213,63,136,138,27,216,223,74,68,81,237,96,122,2,0,227,22,112,149,246,191,0,240,250,84,5,0,63,80,234,212,207, + 38,20,131,170,195,151,145,17,183,65,196,189,81,55,60,55,85,68,221,32,181,217,2,40,89,192,250,249,201,9,198,30, + 186,34,255,34,238,58,138,39,86,193,26,28,164,93,171,1,172,91,192,210,254,222,30,129,120,220,37,203,117,145,55,58, + 237,78,67,80,99,240,71,34,148,14,15,1,150,172,12,108,213,90,173,108,165,144,167,103,234,169,11,185,230,138,119,171, + 40,24,67,79,52,70,227,224,128,122,187,157,205,192,150,15,96,25,86,158,87,42,179,182,207,23,29,72,36,112,26,13, + 228,162,125,245,19,21,48,118,136,222,248,4,141,114,153,194,241,241,106,6,222,220,186,76,118,95,223,194,147,209,81,2, + 182,141,233,237,69,69,112,154,77,58,245,58,95,143,142,186,206,139,183,110,227,255,172,243,79,194,71,102,30,185,88,118, + 119,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Information = { //size: 863 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,3,2,6,32,50,58,80,156,247,0,0,0,53,116, + 69,88,116,67,111,109,109,101,110,116,0,40,99,41,32,50,48,48,52,32,74,97,107,117,98,32,83,116,101,105,110,101, + 114,10,10,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,144,217,139,111,0,0,2,171, + 73,68,65,84,56,203,149,146,75,72,84,113,20,198,191,255,220,59,227,189,58,215,71,38,89,106,102,82,62,8,69,34, + 19,196,161,6,37,212,164,162,144,108,98,202,112,97,180,8,19,178,69,203,16,49,170,69,143,77,162,139,136,160,2,3, + 3,37,200,16,73,116,38,74,74,205,138,52,149,76,157,113,116,156,185,119,174,247,245,111,229,160,53,17,126,171,115,224, + 251,126,156,115,56,4,17,84,92,217,212,76,41,28,6,37,41,32,132,152,136,49,203,16,250,180,255,101,107,227,159,94, + 118,125,83,84,222,148,193,48,164,239,98,109,101,90,185,189,0,113,2,15,85,55,224,241,5,83,123,122,63,92,33,38, + 230,44,165,122,73,127,87,235,215,136,0,150,37,111,239,181,212,111,223,147,185,99,44,16,82,70,103,125,146,18,90,85, + 89,69,211,163,109,37,249,89,233,233,201,123,91,110,61,118,1,136,95,203,48,107,69,73,213,213,219,245,231,143,150,21, + 31,204,249,172,168,186,155,183,152,21,0,68,167,32,170,78,13,239,74,104,150,139,230,16,205,115,59,117,38,37,115,114, + 252,109,39,0,152,194,36,134,61,87,110,47,64,32,164,142,177,44,67,45,102,198,32,132,80,80,24,154,110,40,148,194, + 232,26,156,236,46,42,204,1,195,114,167,214,114,97,192,170,66,227,5,43,15,89,209,87,85,205,72,52,51,166,11,137, + 177,156,115,87,178,224,200,223,189,213,1,37,144,58,229,17,253,60,207,33,32,169,92,109,93,131,105,195,13,8,33,68, + 209,116,72,178,106,50,12,42,38,88,163,224,245,75,46,81,10,49,43,65,73,27,158,150,134,21,69,55,169,170,177,22, + 225,1,136,97,64,12,207,74,94,95,32,70,148,85,203,138,164,250,51,146,99,49,250,195,247,94,84,116,58,183,36,41, + 238,111,139,30,193,106,73,240,250,131,136,19,120,181,163,173,89,220,176,130,153,209,6,122,222,12,131,143,98,115,39,126, + 45,139,0,240,211,39,234,31,39,188,254,222,225,153,133,37,81,54,87,236,79,171,24,114,141,193,202,97,226,175,27,108, + 19,66,199,59,187,250,229,153,233,249,236,180,36,235,161,107,237,3,55,207,28,206,186,228,254,50,31,98,88,146,232,180, + 103,85,251,23,151,114,220,131,35,170,192,250,74,195,171,175,255,131,99,167,27,171,100,42,60,47,43,45,178,20,30,200, + 70,52,207,65,213,117,248,150,69,12,185,198,241,206,53,162,197,113,210,229,39,237,55,30,68,4,0,64,109,93,67,98, + 136,110,113,5,100,164,59,78,36,49,132,0,44,11,116,117,207,5,25,205,191,175,163,237,206,20,254,167,154,26,187,213, + 233,180,81,207,98,31,21,101,23,253,62,249,140,58,157,54,26,201,203,254,131,161,2,192,253,187,15,145,157,155,141,233, + 169,105,108,90,78,167,141,206,204,190,50,2,210,16,253,52,250,194,216,236,4,0,80,85,125,242,122,141,32,196,31,89, + 88,88,120,157,151,23,251,40,146,233,55,86,76,54,94,124,138,29,4,0,0,0,0,73,69,78,68,174,66,96,130, +}; +const nall::vector<uint8_t> Question = { //size: 932 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, + 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,3,54,73,68,65,84,56,141, + 109,147,91,108,84,101,20,133,191,243,255,231,90,81,26,192,134,78,161,244,54,237,128,78,169,83,130,5,77,83,46,70, + 45,250,162,162,134,196,132,152,24,19,43,6,73,76,39,65,140,105,162,173,23,36,241,65,13,137,17,210,248,224,131,9, + 160,71,35,130,142,213,160,5,105,25,90,219,130,99,167,98,157,161,45,80,123,153,105,167,118,206,239,67,75,3,193,157, + 236,151,157,189,87,214,94,89,75,83,74,113,99,21,111,107,9,0,207,0,117,64,112,126,220,5,68,128,214,184,27,238, + 187,113,95,187,14,80,188,173,69,0,141,139,114,204,87,119,62,186,206,190,39,224,19,149,229,249,0,156,191,152,164,243, + 66,194,59,116,236,215,204,100,122,166,9,120,59,238,134,189,5,128,249,227,182,251,170,138,66,45,47,61,236,156,138,14, + 112,162,61,70,79,255,48,0,107,74,242,120,160,198,207,198,181,171,8,191,255,245,212,79,157,3,29,64,109,220,13,123, + 250,60,147,198,77,235,74,67,111,238,122,200,217,179,255,75,174,141,165,217,251,220,102,42,253,249,164,167,102,248,161,35, + 78,171,219,201,241,95,98,188,187,231,17,231,149,3,110,245,143,29,241,70,160,153,162,250,230,64,112,251,123,169,191,135, + 199,212,211,225,79,85,81,125,179,122,177,229,136,202,102,61,213,211,63,164,70,199,211,74,41,165,78,158,142,169,154,157, + 31,169,134,183,190,80,137,145,113,21,220,190,63,93,84,223,28,144,185,254,173,47,191,240,228,134,77,163,227,105,237,208, + 177,179,0,24,134,206,103,199,207,115,216,61,71,123,247,95,60,190,229,110,86,46,207,229,243,239,123,25,25,77,81,186, + 98,9,37,43,150,202,83,209,63,39,4,80,87,85,225,211,78,180,199,0,176,76,157,75,151,199,72,94,77,97,91,6, + 85,21,62,0,174,254,147,198,48,116,114,28,139,206,223,135,8,173,46,16,82,136,58,29,8,6,203,150,19,189,152,196, + 48,36,166,105,96,89,6,150,105,16,10,20,176,123,199,70,148,82,28,60,218,129,99,91,8,161,145,184,50,201,234,226, + 60,60,165,130,215,69,68,8,13,67,215,49,141,185,182,76,131,189,207,214,98,234,146,195,95,69,233,187,52,74,142,99, + 34,132,192,177,76,52,52,52,64,0,93,93,177,203,132,2,5,24,134,156,99,97,232,44,190,221,102,32,57,198,153,222, + 4,109,209,65,28,219,196,177,45,114,28,147,242,194,101,196,6,175,33,164,232,18,64,228,220,133,132,183,101,125,25,186, + 46,209,117,137,97,232,104,66,240,115,247,32,167,123,147,72,41,177,109,99,1,164,210,159,71,247,31,67,94,54,235,69, + 4,208,250,241,145,51,153,13,107,87,177,254,174,149,232,82,162,75,65,238,34,135,221,79,221,75,195,99,213,228,56,38, + 150,101,98,219,38,107,138,239,164,204,151,203,129,214,72,70,41,213,42,226,110,184,111,34,149,105,218,247,193,55,83,175, + 63,191,153,80,192,135,148,2,41,181,5,191,27,243,186,4,10,151,240,68,109,41,175,125,248,237,244,68,42,211,20,119, + 195,125,55,89,121,107,141,191,250,141,134,7,237,104,108,152,104,108,152,196,149,73,108,123,238,231,202,210,101,148,228,47, + 166,233,224,201,105,183,173,231,236,204,191,179,181,113,55,236,221,18,166,59,110,179,247,237,218,113,191,93,85,225,211,202, + 11,151,162,105,26,241,196,40,191,245,143,120,239,124,242,93,102,124,114,186,41,235,121,55,135,233,255,226,44,165,168,83, + 74,5,1,164,148,93,179,179,217,136,82,234,150,56,255,7,102,247,76,148,162,219,138,97,0,0,0,0,73,69,78,68, + 174,66,96,130, +}; +const nall::vector<uint8_t> Warning = { //size: 603 + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, + 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, + 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,214,2,16,14,39,45,183,238,146,119,0,0,1,232,73, + 68,65,84,56,203,149,147,193,74,27,97,20,133,191,59,153,206,52,137,51,131,16,153,74,237,70,67,196,32,134,65,74, + 154,48,4,130,72,99,131,116,23,186,16,34,93,116,231,48,27,241,9,92,27,116,101,192,66,192,69,73,86,5,173,175, + 80,8,62,128,80,92,4,10,133,22,92,212,64,73,49,127,55,214,18,200,180,246,192,189,139,203,225,59,103,115,133,8, + 133,240,200,128,183,0,3,120,221,128,47,227,124,122,20,192,132,163,121,120,14,112,1,71,64,117,156,79,139,72,247,82, + 176,90,88,88,208,158,164,82,90,10,86,67,240,238,13,48,97,47,13,122,98,119,151,76,179,73,26,116,19,246,238,5, + 8,161,56,5,197,108,185,44,122,62,143,158,207,147,45,151,101,10,138,33,20,249,151,118,160,123,2,195,94,167,163,60, + 207,83,158,231,169,94,167,163,78,96,184,3,221,191,54,8,97,197,133,165,140,239,139,225,251,56,142,131,227,56,24,190, + 79,198,247,197,133,165,16,86,34,1,38,236,103,193,72,4,1,162,105,88,150,133,101,89,136,166,145,8,2,178,96,152, + 176,63,22,16,194,250,52,164,231,10,5,140,82,9,17,193,182,109,108,219,70,68,48,74,37,230,10,5,166,33,29,194, + 250,8,32,4,49,160,177,120,155,174,233,58,34,242,167,129,8,154,174,147,8,2,22,193,48,160,17,130,192,237,10,225, + 213,44,180,94,44,47,27,147,103,103,16,139,161,148,162,223,239,3,144,76,38,17,17,184,185,225,106,109,141,15,231,231, + 131,75,168,55,224,157,132,16,123,12,87,79,193,154,63,62,230,97,181,138,82,10,165,20,181,90,13,128,118,187,141,136, + 32,34,252,56,61,229,98,99,131,46,124,255,12,147,154,192,102,28,204,153,92,142,120,165,114,103,20,17,92,215,197,117, + 221,145,91,188,82,97,38,151,35,14,166,192,166,108,195,215,151,144,154,61,56,96,162,94,191,75,255,61,192,8,64,68, + 184,110,181,184,220,218,226,61,124,147,67,24,62,3,121,192,255,233,39,240,17,148,254,9,14,7,240,102,34,226,47,162, + 116,13,195,30,52,127,1,151,222,125,8,28,180,225,19,0,0,0,0,73,69,78,68,174,66,96,130, +}; +} +} diff --git a/hiro/resource/resource.hpp b/hiro/resource/resource.hpp new file mode 100644 index 00000000..5597d3dd --- /dev/null +++ b/hiro/resource/resource.hpp @@ -0,0 +1,102 @@ +namespace Icon { +namespace Action { +extern const nall::vector<uint8_t> Add; +extern const nall::vector<uint8_t> Attach; +extern const nall::vector<uint8_t> Bookmark; +extern const nall::vector<uint8_t> FullScreen; +extern const nall::vector<uint8_t> Mute; +extern const nall::vector<uint8_t> New; +extern const nall::vector<uint8_t> Open; +extern const nall::vector<uint8_t> Properties; +extern const nall::vector<uint8_t> Quit; +extern const nall::vector<uint8_t> Refresh; +extern const nall::vector<uint8_t> Remove; +extern const nall::vector<uint8_t> Save; +extern const nall::vector<uint8_t> Search; +extern const nall::vector<uint8_t> Settings; +extern const nall::vector<uint8_t> Stop; +} +namespace Application { +extern const nall::vector<uint8_t> Browser; +extern const nall::vector<uint8_t> Calculator; +extern const nall::vector<uint8_t> Calendar; +extern const nall::vector<uint8_t> Chat; +extern const nall::vector<uint8_t> FileManager; +extern const nall::vector<uint8_t> Mail; +extern const nall::vector<uint8_t> Monitor; +extern const nall::vector<uint8_t> Terminal; +extern const nall::vector<uint8_t> TextEditor; +} +namespace Device { +extern const nall::vector<uint8_t> Clock; +extern const nall::vector<uint8_t> Display; +extern const nall::vector<uint8_t> Joypad; +extern const nall::vector<uint8_t> Keyboard; +extern const nall::vector<uint8_t> Microphone; +extern const nall::vector<uint8_t> Mouse; +extern const nall::vector<uint8_t> Network; +extern const nall::vector<uint8_t> Optical; +extern const nall::vector<uint8_t> Printer; +extern const nall::vector<uint8_t> Speaker; +extern const nall::vector<uint8_t> Storage; +} +namespace Edit { +extern const nall::vector<uint8_t> Clear; +extern const nall::vector<uint8_t> Copy; +extern const nall::vector<uint8_t> Cut; +extern const nall::vector<uint8_t> Delete; +extern const nall::vector<uint8_t> Find; +extern const nall::vector<uint8_t> Paste; +extern const nall::vector<uint8_t> Redo; +extern const nall::vector<uint8_t> Replace; +extern const nall::vector<uint8_t> Undo; +} +namespace Emblem { +extern const nall::vector<uint8_t> Archive; +extern const nall::vector<uint8_t> Audio; +extern const nall::vector<uint8_t> Binary; +extern const nall::vector<uint8_t> File; +extern const nall::vector<uint8_t> Folder; +extern const nall::vector<uint8_t> Font; +extern const nall::vector<uint8_t> Image; +extern const nall::vector<uint8_t> Markup; +extern const nall::vector<uint8_t> Program; +extern const nall::vector<uint8_t> Script; +extern const nall::vector<uint8_t> Text; +extern const nall::vector<uint8_t> Video; +} +namespace Go { +extern const nall::vector<uint8_t> Down; +extern const nall::vector<uint8_t> Home; +extern const nall::vector<uint8_t> Left; +extern const nall::vector<uint8_t> Right; +extern const nall::vector<uint8_t> Up; +} +namespace Media { +extern const nall::vector<uint8_t> Back; +extern const nall::vector<uint8_t> Eject; +extern const nall::vector<uint8_t> Flash; +extern const nall::vector<uint8_t> Floppy; +extern const nall::vector<uint8_t> Next; +extern const nall::vector<uint8_t> Optical; +extern const nall::vector<uint8_t> Pause; +extern const nall::vector<uint8_t> Play; +extern const nall::vector<uint8_t> Record; +extern const nall::vector<uint8_t> Rewind; +extern const nall::vector<uint8_t> Skip; +extern const nall::vector<uint8_t> Stop; +} +namespace Place { +extern const nall::vector<uint8_t> Bookmarks; +extern const nall::vector<uint8_t> Desktop; +extern const nall::vector<uint8_t> Home; +extern const nall::vector<uint8_t> Server; +extern const nall::vector<uint8_t> Share; +} +namespace Prompt { +extern const nall::vector<uint8_t> Error; +extern const nall::vector<uint8_t> Information; +extern const nall::vector<uint8_t> Question; +extern const nall::vector<uint8_t> Warning; +} +} diff --git a/phoenix/windows/action/action.cpp b/hiro/windows/action/action.cpp similarity index 100% rename from phoenix/windows/action/action.cpp rename to hiro/windows/action/action.cpp diff --git a/phoenix/windows/action/check-item.cpp b/hiro/windows/action/check-item.cpp similarity index 100% rename from phoenix/windows/action/check-item.cpp rename to hiro/windows/action/check-item.cpp diff --git a/phoenix/windows/action/item.cpp b/hiro/windows/action/item.cpp similarity index 100% rename from phoenix/windows/action/item.cpp rename to hiro/windows/action/item.cpp diff --git a/phoenix/windows/action/menu.cpp b/hiro/windows/action/menu.cpp similarity index 100% rename from phoenix/windows/action/menu.cpp rename to hiro/windows/action/menu.cpp diff --git a/phoenix/windows/action/radio-item.cpp b/hiro/windows/action/radio-item.cpp similarity index 100% rename from phoenix/windows/action/radio-item.cpp rename to hiro/windows/action/radio-item.cpp diff --git a/phoenix/windows/action/separator.cpp b/hiro/windows/action/separator.cpp similarity index 100% rename from phoenix/windows/action/separator.cpp rename to hiro/windows/action/separator.cpp diff --git a/phoenix/windows/application.cpp b/hiro/windows/application.cpp similarity index 100% rename from phoenix/windows/application.cpp rename to hiro/windows/application.cpp diff --git a/phoenix/windows/browser-window.cpp b/hiro/windows/browser-window.cpp similarity index 96% rename from phoenix/windows/browser-window.cpp rename to hiro/windows/browser-window.cpp index 146c4c8e..93b2ba6b 100644 --- a/phoenix/windows/browser-window.cpp +++ b/hiro/windows/browser-window.cpp @@ -19,7 +19,7 @@ static string BrowserWindow_fileDialog(bool save, BrowserWindow::State& state) { for(auto& filter : state.filters) { lstring part = filter.split("("); if(part.size() != 2) continue; - part[1].rtrim<1>(")"); + part[1].rtrim(")"); part[1].replace(" ", ""); part[1].transform(",", ";"); filters.append(filter, "\t", part[1], "\t"); diff --git a/phoenix/windows/desktop.cpp b/hiro/windows/desktop.cpp similarity index 100% rename from phoenix/windows/desktop.cpp rename to hiro/windows/desktop.cpp diff --git a/phoenix/windows/font.cpp b/hiro/windows/font.cpp similarity index 94% rename from phoenix/windows/font.cpp rename to hiro/windows/font.cpp index 94db0ecf..6cfadfb2 100644 --- a/phoenix/windows/font.cpp +++ b/hiro/windows/font.cpp @@ -26,9 +26,7 @@ Size pFont::size(string font, string text) { } HFONT pFont::create(string description) { - lstring part; - part.split(",", description); - for(auto& item : part) item.trim(" "); + lstring part = description.split<2>(",").strip(); string family = "Sans"; unsigned size = 8u; diff --git a/phoenix/windows/header.hpp b/hiro/windows/header.hpp similarity index 100% rename from phoenix/windows/header.hpp rename to hiro/windows/header.hpp diff --git a/phoenix/windows/keyboard.cpp b/hiro/windows/keyboard.cpp similarity index 100% rename from phoenix/windows/keyboard.cpp rename to hiro/windows/keyboard.cpp diff --git a/phoenix/windows/message-window.cpp b/hiro/windows/message-window.cpp similarity index 100% rename from phoenix/windows/message-window.cpp rename to hiro/windows/message-window.cpp diff --git a/phoenix/windows/monitor.cpp b/hiro/windows/monitor.cpp similarity index 100% rename from phoenix/windows/monitor.cpp rename to hiro/windows/monitor.cpp diff --git a/phoenix/windows/mouse.cpp b/hiro/windows/mouse.cpp similarity index 100% rename from phoenix/windows/mouse.cpp rename to hiro/windows/mouse.cpp diff --git a/phoenix/windows/object.cpp b/hiro/windows/object.cpp similarity index 100% rename from phoenix/windows/object.cpp rename to hiro/windows/object.cpp diff --git a/phoenix/windows/phoenix.Manifest b/hiro/windows/phoenix.Manifest similarity index 100% rename from phoenix/windows/phoenix.Manifest rename to hiro/windows/phoenix.Manifest diff --git a/phoenix/windows/phoenix.rc b/hiro/windows/phoenix.rc similarity index 100% rename from phoenix/windows/phoenix.rc rename to hiro/windows/phoenix.rc diff --git a/phoenix/windows/platform.cpp b/hiro/windows/platform.cpp similarity index 100% rename from phoenix/windows/platform.cpp rename to hiro/windows/platform.cpp diff --git a/phoenix/windows/platform.hpp b/hiro/windows/platform.hpp similarity index 98% rename from phoenix/windows/platform.hpp rename to hiro/windows/platform.hpp index 06378f53..36366c6b 100644 --- a/phoenix/windows/platform.hpp +++ b/hiro/windows/platform.hpp @@ -273,6 +273,7 @@ struct pButton : public pWidget { HIMAGELIST himagelist; Size minimumSize(); + void setBordered(bool bordered); void setImage(const image& image, Orientation orientation); void setText(string text); @@ -360,6 +361,7 @@ struct pComboButton : public pWidget { struct pConsole : public pWidget { Console& console; LRESULT CALLBACK (*windowProc)(HWND, UINT, LPARAM, WPARAM); + HBRUSH backgroundBrush = nullptr; void print(string text); void reset(); @@ -392,6 +394,7 @@ struct pHexEdit : public pWidget { HexEdit& hexEdit; WindowProc windowProc = nullptr; HWND scrollBar = nullptr; + HBRUSH backgroundBrush = nullptr; void setBackgroundColor(Color color); void setColumns(unsigned columns); @@ -456,6 +459,7 @@ struct pLabel : public pWidget { struct pLineEdit : public pWidget { LineEdit& lineEdit; + HBRUSH backgroundBrush = nullptr; Size minimumSize(); void setBackgroundColor(Color color); @@ -580,6 +584,7 @@ struct pTabFrame : public pWidget { struct pTextEdit : public pWidget { TextEdit& textEdit; + HBRUSH backgroundBrush = nullptr; void setBackgroundColor(Color color); void setCursorPosition(unsigned position); diff --git a/phoenix/windows/settings.cpp b/hiro/windows/settings.cpp similarity index 100% rename from phoenix/windows/settings.cpp rename to hiro/windows/settings.cpp diff --git a/phoenix/windows/timer.cpp b/hiro/windows/timer.cpp similarity index 100% rename from phoenix/windows/timer.cpp rename to hiro/windows/timer.cpp diff --git a/phoenix/windows/utility.cpp b/hiro/windows/utility.cpp similarity index 86% rename from phoenix/windows/utility.cpp rename to hiro/windows/utility.cpp index 5902f0d5..ce692b59 100644 --- a/phoenix/windows/utility.cpp +++ b/hiro/windows/utility.cpp @@ -245,13 +245,41 @@ static LRESULT CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT switch(msg) { case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: case WM_CTLCOLORSTATIC: { Object* object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA); if(object == nullptr) break; - if(dynamic_cast<HexEdit*>(object) || dynamic_cast<LineEdit*>(object) || dynamic_cast<TextEdit*>(object)) { - //text edit controls, when disabled, use CTLCOLORSTATIC instead of CTLCOLOREDIT - //override this behavior: we do not want read-only edit controls to use the parent window background color - return windowProc(hwnd, WM_CTLCOLOREDIT, wparam, lparam); + //allow custom colors for various widgets + //note that this happens always: default colors are black text on a white background, unless overridden + //this intentionally overrides the default behavior of Windows to paint disabled controls with the window background color + if(dynamic_cast<Console*>(object)) { + Console& console = *(Console*)object; + Color& background = console.state.backgroundColor; + Color& foreground = console.state.foregroundColor; + SetTextColor((HDC)wparam, RGB(foreground.red, foreground.green, foreground.blue)); + SetBkColor((HDC)wparam, RGB(background.red, background.green, background.blue)); + return (LRESULT)console.p.backgroundBrush; + } else if(dynamic_cast<HexEdit*>(object)) { + HexEdit& hexEdit = *(HexEdit*)object; + Color& background = hexEdit.state.backgroundColor; + Color& foreground = hexEdit.state.foregroundColor; + SetTextColor((HDC)wparam, RGB(foreground.red, foreground.green, foreground.blue)); + SetBkColor((HDC)wparam, RGB(background.red, background.green, background.blue)); + return (LRESULT)hexEdit.p.backgroundBrush; + } else if(dynamic_cast<LineEdit*>(object)) { + LineEdit& lineEdit = *(LineEdit*)object; + Color& background = lineEdit.state.backgroundColor; + Color& foreground = lineEdit.state.foregroundColor; + SetTextColor((HDC)wparam, RGB(foreground.red, foreground.green, foreground.blue)); + SetBkColor((HDC)wparam, RGB(background.red, background.green, background.blue)); + return (LRESULT)lineEdit.p.backgroundBrush; + } else if(dynamic_cast<TextEdit*>(object)) { + TextEdit& textEdit = *(TextEdit*)object; + Color& background = textEdit.state.backgroundColor; + Color& foreground = textEdit.state.foregroundColor; + SetTextColor((HDC)wparam, RGB(foreground.red, foreground.green, foreground.blue)); + SetBkColor((HDC)wparam, RGB(background.red, background.green, background.blue)); + return (LRESULT)textEdit.p.backgroundBrush; } else if(!GetParentWidget((Sizable*)object) && window.p.brush) { SetBkColor((HDC)wparam, window.p.brushColor); return (INT_PTR)window.p.brush; diff --git a/phoenix/windows/widget/button.cpp b/hiro/windows/widget/button.cpp similarity index 95% rename from phoenix/windows/widget/button.cpp rename to hiro/windows/widget/button.cpp index 0598c620..26a938f1 100644 --- a/phoenix/windows/widget/button.cpp +++ b/hiro/windows/widget/button.cpp @@ -32,7 +32,10 @@ Size pButton::minimumSize() { size.height += button.state.image.height; } - return {size.width + 20, size.height + 10}; + return {size.width + (button.state.text ? 20 : 10), size.height + 10}; +} + +void pButton::setBordered(bool bordered) { } void pButton::setImage(const image& image, Orientation orientation) { @@ -75,6 +78,7 @@ void pButton::constructor() { hwnd = CreateWindow(L"BUTTON", L"", WS_CHILD | WS_TABSTOP, 0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&button); setDefaultFont(); + setBordered(button.state.bordered); setImage(button.state.image, button.state.orientation); //setText(button.state.text); //called by setImage(); synchronize(); diff --git a/phoenix/windows/widget/canvas.cpp b/hiro/windows/widget/canvas.cpp similarity index 100% rename from phoenix/windows/widget/canvas.cpp rename to hiro/windows/widget/canvas.cpp diff --git a/phoenix/windows/widget/check-button.cpp b/hiro/windows/widget/check-button.cpp similarity index 100% rename from phoenix/windows/widget/check-button.cpp rename to hiro/windows/widget/check-button.cpp diff --git a/phoenix/windows/widget/check-label.cpp b/hiro/windows/widget/check-label.cpp similarity index 100% rename from phoenix/windows/widget/check-label.cpp rename to hiro/windows/widget/check-label.cpp diff --git a/phoenix/windows/widget/combo-button.cpp b/hiro/windows/widget/combo-button.cpp similarity index 100% rename from phoenix/windows/widget/combo-button.cpp rename to hiro/windows/widget/combo-button.cpp diff --git a/phoenix/windows/widget/console.cpp b/hiro/windows/widget/console.cpp similarity index 86% rename from phoenix/windows/widget/console.cpp rename to hiro/windows/widget/console.cpp index 812fdfa3..64abd98b 100644 --- a/phoenix/windows/widget/console.cpp +++ b/hiro/windows/widget/console.cpp @@ -15,6 +15,8 @@ void pConsole::reset() { } void pConsole::setBackgroundColor(Color color) { + if(backgroundBrush) DeleteObject(backgroundBrush); + backgroundBrush = CreateSolidBrush(RGB(color.red, color.green, color.blue)); } void pConsole::setForegroundColor(Color color) { @@ -31,6 +33,7 @@ void pConsole::constructor() { ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&console); setDefaultFont(); + setBackgroundColor(console.state.backgroundColor); windowProc = (LRESULT CALLBACK (*)(HWND, UINT, LPARAM, WPARAM))GetWindowLongPtr(hwnd, GWLP_WNDPROC); SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)Console_windowProc); diff --git a/phoenix/windows/widget/frame.cpp b/hiro/windows/widget/frame.cpp similarity index 100% rename from phoenix/windows/widget/frame.cpp rename to hiro/windows/widget/frame.cpp diff --git a/phoenix/windows/widget/hex-edit.cpp b/hiro/windows/widget/hex-edit.cpp similarity index 97% rename from phoenix/windows/widget/hex-edit.cpp rename to hiro/windows/widget/hex-edit.cpp index 3dace06c..b29f81b4 100644 --- a/phoenix/windows/widget/hex-edit.cpp +++ b/hiro/windows/widget/hex-edit.cpp @@ -50,6 +50,8 @@ static LRESULT CALLBACK HexEdit_windowProc(HWND hwnd, UINT msg, WPARAM wparam, L } void pHexEdit::setBackgroundColor(Color color) { + if(backgroundBrush) DeleteObject(backgroundBrush); + backgroundBrush = CreateSolidBrush(RGB(color.red, color.green, color.blue)); } void pHexEdit::setColumns(unsigned columns) { @@ -131,6 +133,7 @@ void pHexEdit::constructor() { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HexEdit_windowProc); setDefaultFont(); + setBackgroundColor(hexEdit.state.backgroundColor); setLength(hexEdit.state.length); setOffset(hexEdit.state.offset); update(); diff --git a/phoenix/windows/widget/horizontal-scroller.cpp b/hiro/windows/widget/horizontal-scroller.cpp similarity index 100% rename from phoenix/windows/widget/horizontal-scroller.cpp rename to hiro/windows/widget/horizontal-scroller.cpp diff --git a/phoenix/windows/widget/horizontal-slider.cpp b/hiro/windows/widget/horizontal-slider.cpp similarity index 100% rename from phoenix/windows/widget/horizontal-slider.cpp rename to hiro/windows/widget/horizontal-slider.cpp diff --git a/phoenix/windows/widget/label.cpp b/hiro/windows/widget/label.cpp similarity index 100% rename from phoenix/windows/widget/label.cpp rename to hiro/windows/widget/label.cpp diff --git a/phoenix/windows/widget/line-edit.cpp b/hiro/windows/widget/line-edit.cpp similarity index 87% rename from phoenix/windows/widget/line-edit.cpp rename to hiro/windows/widget/line-edit.cpp index 0b383132..c1e0be14 100644 --- a/phoenix/windows/widget/line-edit.cpp +++ b/hiro/windows/widget/line-edit.cpp @@ -6,6 +6,8 @@ Size pLineEdit::minimumSize() { } void pLineEdit::setBackgroundColor(Color color) { + if(backgroundBrush) DeleteObject(backgroundBrush); + backgroundBrush = CreateSolidBrush(RGB(color.red, color.green, color.blue)); } void pLineEdit::setEditable(bool editable) { @@ -37,6 +39,7 @@ void pLineEdit::constructor() { ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&lineEdit); setDefaultFont(); + setBackgroundColor(lineEdit.state.backgroundColor); setEditable(lineEdit.state.editable); setText(lineEdit.state.text); synchronize(); diff --git a/phoenix/windows/widget/list-view.cpp b/hiro/windows/widget/list-view.cpp similarity index 91% rename from phoenix/windows/widget/list-view.cpp rename to hiro/windows/widget/list-view.cpp index 465a9fe0..7813614b 100644 --- a/phoenix/windows/widget/list-view.cpp +++ b/hiro/windows/widget/list-view.cpp @@ -57,6 +57,7 @@ void pListView::reset() { } void pListView::setBackgroundColor(Color color) { + ListView_SetBkColor(hwnd, RGB(color.red, color.green, color.blue)); } void pListView::setCheckable(bool checkable) { @@ -152,6 +153,7 @@ void pListView::constructor() { SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&listView); setDefaultFont(); setHeaderText(listView.state.headerText); + setBackgroundColor(listView.state.backgroundColor); setHeaderVisible(listView.state.headerVisible); setCheckable(listView.state.checkable); for(auto& text : listView.state.text) append(text); @@ -259,17 +261,28 @@ LRESULT pListView::onCustomDraw(LPARAM lparam) { LPNMLVCUSTOMDRAW lvcd = (LPNMLVCUSTOMDRAW)lparam; switch(lvcd->nmcd.dwDrawStage) { - case CDDS_PREPAINT: + + case CDDS_PREPAINT: { return CDRF_NOTIFYITEMDRAW; - case CDDS_ITEMPREPAINT: - if(listView.state.headerText.size() >= 2) { - //draw alternating row colors of there are two or more columns - if(lvcd->nmcd.dwItemSpec % 2) lvcd->clrTextBk = GetSysColor(COLOR_WINDOW) ^ 0x070707; + } + + case CDDS_ITEMPREPAINT: { + Color& background = listView.state.backgroundColor; + Color& foreground = listView.state.foregroundColor; + lvcd->clrText = RGB(foreground.red, foreground.green, foreground.blue); + lvcd->clrTextBk = RGB(background.red, background.green, background.blue); + if(listView.state.headerText.size() >= 2 && lvcd->nmcd.dwItemSpec % 2) { + //draw alternating row colors if there are two or more columns + lvcd->clrTextBk = RGB(max(0, (signed)background.red - 17), max(0, (signed)background.green - 17), max(0, (signed)background.blue - 17)); } return CDRF_DODEFAULT; - default: + } + + default: { return CDRF_DODEFAULT; } + + } } } diff --git a/phoenix/windows/widget/progress-bar.cpp b/hiro/windows/widget/progress-bar.cpp similarity index 100% rename from phoenix/windows/widget/progress-bar.cpp rename to hiro/windows/widget/progress-bar.cpp diff --git a/phoenix/windows/widget/radio-button.cpp b/hiro/windows/widget/radio-button.cpp similarity index 100% rename from phoenix/windows/widget/radio-button.cpp rename to hiro/windows/widget/radio-button.cpp diff --git a/phoenix/windows/widget/radio-label.cpp b/hiro/windows/widget/radio-label.cpp similarity index 100% rename from phoenix/windows/widget/radio-label.cpp rename to hiro/windows/widget/radio-label.cpp diff --git a/phoenix/windows/widget/tab-frame.cpp b/hiro/windows/widget/tab-frame.cpp similarity index 100% rename from phoenix/windows/widget/tab-frame.cpp rename to hiro/windows/widget/tab-frame.cpp diff --git a/phoenix/windows/widget/text-edit.cpp b/hiro/windows/widget/text-edit.cpp similarity index 91% rename from phoenix/windows/widget/text-edit.cpp rename to hiro/windows/widget/text-edit.cpp index 509897fc..7ce02d7a 100644 --- a/phoenix/windows/widget/text-edit.cpp +++ b/hiro/windows/widget/text-edit.cpp @@ -1,6 +1,8 @@ namespace phoenix { void pTextEdit::setBackgroundColor(Color color) { + if(backgroundBrush) DeleteObject(backgroundBrush); + backgroundBrush = CreateSolidBrush(RGB(color.red, color.green, color.blue)); } void pTextEdit::setCursorPosition(unsigned position) { @@ -49,6 +51,7 @@ void pTextEdit::constructor() { ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&textEdit); setDefaultFont(); + setBackgroundColor(textEdit.state.backgroundColor); setCursorPosition(textEdit.state.cursorPosition); setEditable(textEdit.state.editable); setText(textEdit.state.text); diff --git a/phoenix/windows/widget/vertical-scroller.cpp b/hiro/windows/widget/vertical-scroller.cpp similarity index 100% rename from phoenix/windows/widget/vertical-scroller.cpp rename to hiro/windows/widget/vertical-scroller.cpp diff --git a/phoenix/windows/widget/vertical-slider.cpp b/hiro/windows/widget/vertical-slider.cpp similarity index 100% rename from phoenix/windows/widget/vertical-slider.cpp rename to hiro/windows/widget/vertical-slider.cpp diff --git a/phoenix/windows/widget/viewport.cpp b/hiro/windows/widget/viewport.cpp similarity index 100% rename from phoenix/windows/widget/viewport.cpp rename to hiro/windows/widget/viewport.cpp diff --git a/phoenix/windows/widget/widget.cpp b/hiro/windows/widget/widget.cpp similarity index 100% rename from phoenix/windows/widget/widget.cpp rename to hiro/windows/widget/widget.cpp diff --git a/phoenix/windows/window.cpp b/hiro/windows/window.cpp similarity index 98% rename from phoenix/windows/window.cpp rename to hiro/windows/window.cpp index fff305f0..79b64c4e 100644 --- a/phoenix/windows/window.cpp +++ b/hiro/windows/window.cpp @@ -192,7 +192,11 @@ void pWindow::setModal(bool modality) { updateModality(); while(window.state.modal) { Application::processEvents(); - usleep(20 * 1000); + if(Application::main) { + Application::main(); + } else { + usleep(20 * 1000); + } } if(auto position = modal.find(this)) modal.remove(position()); updateModality(); diff --git a/nall/Makefile b/nall/GNUmakefile similarity index 90% rename from nall/Makefile rename to nall/GNUmakefile index 9697bcd6..e51a20a8 100644 --- a/nall/Makefile +++ b/nall/GNUmakefile @@ -1,7 +1,3 @@ -# Makefile -# author: byuu -# license: public domain - [A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z [0-9] = 0 1 2 3 4 5 6 7 8 9 @@ -36,8 +32,8 @@ endif cflags := -x c -std=c99 objcflags := -x objective-c -std=c99 -cppflags := -x c++ -std=c++11 -objcppflags := -x objective-c++ -std=c++11 +cppflags := -x c++ -std=c++14 +objcppflags := -x objective-c++ -std=c++14 flags := link := @@ -48,20 +44,23 @@ ifeq ($(compiler),) else ifeq ($(platform),macosx) compiler := clang++ else ifeq ($(platform),bsd) - compiler := g++47 + compiler := g++49 else compiler := g++ endif endif +# clang settings +ifeq ($(findstring clang++,$(compiler)),clang++) + flags += -fwrapv # gcc settings -ifeq ($(findstring g++,$(compiler)),g++) +else ifeq ($(findstring g++,$(compiler)),g++) flags += -fwrapv endif -# clang settings -ifeq ($(findstring clang++,$(compiler)),clang++) - flags += -fwrapv -w +# windows settings +ifeq ($(platform),windows) + link := $(link) -lws2_32 -lole32 endif # macosx settings @@ -81,9 +80,8 @@ ifeq ($(arch),x86) link := -m32 $(link) endif -ifeq ($(prefix),) - prefix := /usr/local -endif +# paths +prefix := $(HOME)/.local # function rwildcard(directory, pattern) rwildcard = \ diff --git a/nall/algorithm.hpp b/nall/algorithm.hpp index 5867c1cd..89fec57d 100644 --- a/nall/algorithm.hpp +++ b/nall/algorithm.hpp @@ -1,19 +1,29 @@ #ifndef NALL_ALGORITHM_HPP #define NALL_ALGORITHM_HPP +#include <nall/traits.hpp> + #undef min #undef max -namespace nall { +namespace nall { namespace { -template<typename T, typename U> T min(const T& t, const U& u) { +template<typename T, typename U> auto min(const T& t, const U& u) -> T { return t < u ? t : u; } -template<typename T, typename U> T max(const T& t, const U& u) { +template<typename T, typename U, typename... P> auto min(const T& t, const U& u, P&&... p) -> T { + return t < u ? min(t, forward<P>(p)...) : min(u, forward<P>(p)...); +} + +template<typename T, typename U> auto max(const T& t, const U& u) -> T { return t > u ? t : u; } +template<typename T, typename U, typename... P> auto max(const T& t, const U& u, P&&... p) -> T { + return t > u ? max(t, forward<P>(p)...) : max(u, forward<P>(p)...); } +}} + #endif diff --git a/nall/any.hpp b/nall/any.hpp index 27a07ef2..8d6b638a 100644 --- a/nall/any.hpp +++ b/nall/any.hpp @@ -15,11 +15,7 @@ struct any { } template<typename T> any& operator=(const T& value) { - typedef typename type_if< - std::is_array<T>::value, - typename std::remove_extent<typename std::add_const<T>::type>::type*, - T - >::type auto_t; + using auto_t = type_if<is_array<T>, typename std::remove_extent<typename std::add_const<T>::type>::type*, T>; if(type() == typeid(auto_t)) { static_cast<holder<auto_t>*>(container)->value = (auto_t)value; @@ -46,7 +42,7 @@ struct any { any() = default; any(const any& source) { operator=(source); } - any(any&& source) { operator=(std::move(source)); } + any(any&& source) { operator=(move(source)); } template<typename T> any(const T& value) { operator=(value); } ~any() { reset(); } diff --git a/nall/beat/archive.hpp b/nall/beat/archive.hpp index f8c6b6cf..f3fce618 100644 --- a/nall/beat/archive.hpp +++ b/nall/beat/archive.hpp @@ -10,7 +10,7 @@ struct beatArchive : beatBase { if(fp.open(beatname, file::mode::write) == false) return false; if(pathname.endsWith("/") == false) pathname.append("/"); - checksum = ~0; + checksum.reset(); writeString("BPA1"); writeNumber(metadata.length()); writeString(metadata); @@ -19,7 +19,7 @@ struct beatArchive : beatBase { ls(list, pathname, pathname); for(auto &name : list) { if(name.endsWith("/")) { - name.rtrim<1>("/"); + name.rtrim("/"); writeNumber(0 | ((name.length() - 1) << 1)); writeString(name); } else { @@ -29,17 +29,17 @@ struct beatArchive : beatBase { writeString(name); unsigned size = stream.size(); writeNumber(size); - uint32_t checksum = ~0; + Hash::CRC32 checksum; while(size--) { uint8_t data = stream.read(); write(data); - checksum = crc32_adjust(checksum, data); + checksum.data(data); } - writeChecksum(~checksum); + writeChecksum(checksum.value()); } } - writeChecksum(~checksum); + writeChecksum(checksum.value()); fp.close(); return true; } @@ -48,7 +48,7 @@ struct beatArchive : beatBase { if(fp.open(beatname, file::mode::read) == false) return false; if(pathname.endsWith("/") == false) pathname.append("/"); - checksum = ~0; + checksum.reset(); if(readString(4) != "BPA1") return false; unsigned length = readNumber(); while(length--) read(); @@ -65,17 +65,17 @@ struct beatArchive : beatBase { file stream; if(stream.open({pathname, name}, file::mode::write) == false) return false; unsigned size = readNumber(); - uint32_t checksum = ~0; + Hash::CRC32 checksum; while(size--) { uint8_t data = read(); stream.write(data); - checksum = crc32_adjust(checksum, data); + checksum.data(data); } - if(readChecksum(~checksum) == false) return false; + if(readChecksum(checksum.value()) == false) return false; } } - return readChecksum(~checksum); + return readChecksum(checksum.value()); } }; diff --git a/nall/beat/base.hpp b/nall/beat/base.hpp index d35b8e7c..7d021d52 100644 --- a/nall/beat/base.hpp +++ b/nall/beat/base.hpp @@ -6,24 +6,24 @@ namespace nall { struct beatBase { protected: file fp; - uint32_t checksum; + Hash::CRC32 checksum; void ls(lstring& list, const string& path, const string& basepath) { lstring paths = directory::folders(path); for(auto& pathname : paths) { - list.append(string{path, pathname}.ltrim<1>(basepath)); + list.append(string{path, pathname}.ltrim(basepath)); ls(list, {path, pathname}, basepath); } lstring files = directory::files(path); for(auto& filename : files) { - list.append(string{path, filename}.ltrim<1>(basepath)); + list.append(string{path, filename}.ltrim(basepath)); } } void write(uint8_t data) { fp.write(data); - checksum = crc32_adjust(checksum, data); + checksum.data(data); } void writeNumber(uint64_t data) { @@ -50,7 +50,7 @@ protected: uint8_t read() { uint8_t data = fp.read(); - checksum = crc32_adjust(checksum, data); + checksum.data(data); return data; } @@ -68,12 +68,12 @@ protected: string readString(unsigned length) { string text; - text.reserve(length + 1); - for(unsigned n = 0; n < length; n++) { - text[n] = fp.read(); - checksum = crc32_adjust(checksum, text[n]); + text.resize(length + 1); + char* p = text.pointer(); + while(length--) { + *p = fp.read(); + checksum.data(*p++); } - text[length] = 0; return text; } diff --git a/nall/beat/delta.hpp b/nall/beat/delta.hpp index 04145efb..487097fa 100644 --- a/nall/beat/delta.hpp +++ b/nall/beat/delta.hpp @@ -1,7 +1,6 @@ #ifndef NALL_BEAT_DELTA_HPP #define NALL_BEAT_DELTA_HPP -#include <nall/crc32.hpp> #include <nall/file.hpp> #include <nall/filemap.hpp> #include <nall/stdint.hpp> @@ -63,12 +62,12 @@ bool bpsdelta::create(const string& filename, const string& metadata) { file modifyFile; if(modifyFile.open(filename, file::mode::write) == false) return false; - uint32_t sourceChecksum = ~0, modifyChecksum = ~0; + Hash::CRC32 sourceChecksum, modifyChecksum; unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; auto write = [&](uint8_t data) { modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); + modifyChecksum.data(data); }; auto encode = [&](uint64_t data) { @@ -103,7 +102,7 @@ bool bpsdelta::create(const string& filename, const string& metadata) { //source tree creation for(unsigned offset = 0; offset < sourceSize; offset++) { uint16_t symbol = sourceData[offset + 0]; - sourceChecksum = crc32_adjust(sourceChecksum, symbol); + sourceChecksum.data(symbol); if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8; Node *node = new Node; node->offset = offset; @@ -199,11 +198,10 @@ bool bpsdelta::create(const string& filename, const string& metadata) { targetReadFlush(); - sourceChecksum = ~sourceChecksum; - for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); + for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum.value() >> n); + uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value(); for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; + uint32_t outputChecksum = modifyChecksum.value(); for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); modifyFile.close(); diff --git a/nall/beat/linear.hpp b/nall/beat/linear.hpp index 4ee44a57..ac13894c 100644 --- a/nall/beat/linear.hpp +++ b/nall/beat/linear.hpp @@ -1,7 +1,6 @@ #ifndef NALL_BEAT_LINEAR_HPP #define NALL_BEAT_LINEAR_HPP -#include <nall/crc32.hpp> #include <nall/file.hpp> #include <nall/filemap.hpp> #include <nall/stdint.hpp> @@ -56,12 +55,12 @@ bool bpslinear::create(const string& filename, const string& metadata) { file modifyFile; if(modifyFile.open(filename, file::mode::write) == false) return false; - uint32_t modifyChecksum = ~0; + Hash::CRC32 modifyChecksum; unsigned targetRelativeOffset = 0, outputOffset = 0; auto write = [&](uint8_t data) { modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); + modifyChecksum.data(data); }; auto encode = [&](uint64_t data) { @@ -136,11 +135,11 @@ bool bpslinear::create(const string& filename, const string& metadata) { targetReadFlush(); - uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize); + uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).value(); for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); + uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value(); for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; + uint32_t outputChecksum = modifyChecksum.value(); for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); modifyFile.close(); diff --git a/nall/beat/metadata.hpp b/nall/beat/metadata.hpp index 2b31fdfd..f83771ca 100644 --- a/nall/beat/metadata.hpp +++ b/nall/beat/metadata.hpp @@ -1,7 +1,6 @@ #ifndef NALL_BEAT_METADATA_HPP #define NALL_BEAT_METADATA_HPP -#include <nall/crc32.hpp> #include <nall/file.hpp> #include <nall/filemap.hpp> #include <nall/stdint.hpp> @@ -75,11 +74,11 @@ bool bpsmetadata::save(const string& filename, const string& metadata) { return data; }; - uint32_t checksum = ~0; + Hash::CRC32 checksum; auto write = [&](uint8_t data) { targetFile.write(data); - checksum = crc32_adjust(checksum, data); + checksum.data(data); }; auto encode = [&](uint64_t data) { @@ -105,7 +104,7 @@ bool bpsmetadata::save(const string& filename, const string& metadata) { for(unsigned n = 0; n < targetLength; n++) write(metadata[n]); unsigned length = sourceFile.size() - sourceFile.offset() - 4; for(unsigned n = 0; n < length; n++) write(read()); - uint32_t outputChecksum = ~checksum; + uint32_t outputChecksum = checksum.value(); for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); targetFile.close(); diff --git a/nall/beat/multi.hpp b/nall/beat/multi.hpp index c99001c8..6d9428d6 100644 --- a/nall/beat/multi.hpp +++ b/nall/beat/multi.hpp @@ -23,7 +23,7 @@ struct bpsmulti { bool create(const string& patchName, const string& sourcePath, const string& targetPath, bool delta = false, const string& metadata = "") { if(fp.open()) fp.close(); fp.open(patchName, file::mode::write); - checksum = ~0; + checksum.reset(); writeString("BPM1"); //signature writeNumber(metadata.length()); @@ -35,7 +35,7 @@ struct bpsmulti { for(auto& targetName : targetList) { if(targetName.endsWith("/")) { - targetName.rtrim<1>("/"); + targetName.rtrim("/"); writeNumber(CreatePath | ((targetName.length() - 1) << 2)); writeString(targetName); } else if(auto position = sourceList.find(targetName)) { //if sourceName == targetName @@ -44,19 +44,19 @@ struct bpsmulti { dp.open({targetPath, targetName}, file::mode::read); bool identical = sp.size() == dp.size(); - uint32_t cksum = ~0; + Hash::CRC32 cksum; for(unsigned n = 0; n < sp.size(); n++) { uint8_t byte = sp.read(); if(identical && byte != dp.read()) identical = false; - cksum = crc32_adjust(cksum, byte); + cksum.data(byte); } if(identical) { writeNumber(MirrorFile | ((targetName.length() - 1) << 2)); writeString(targetName); writeNumber(OriginSource); - writeChecksum(~cksum); + writeChecksum(cksum.value()); } else { writeNumber(ModifyFile | ((targetName.length() - 1) << 2)); writeString(targetName); @@ -84,12 +84,12 @@ struct bpsmulti { auto buffer = file::read({targetPath, targetName}); writeNumber(buffer.size()); for(auto &byte : buffer) write(byte); - writeChecksum(crc32_calculate(buffer.data(), buffer.size())); + writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).value()); } } //checksum - writeChecksum(~checksum); + writeChecksum(checksum.value()); fp.close(); return true; } @@ -100,7 +100,7 @@ struct bpsmulti { if(fp.open()) fp.close(); fp.open(patchName, file::mode::read); - checksum = ~0; + checksum.reset(); if(readString(4) != "BPM1") return false; auto metadataLength = readNumber(); @@ -142,7 +142,7 @@ struct bpsmulti { } } - uint32_t cksum = ~checksum; + uint32_t cksum = checksum.value(); if(read() != (uint8_t)(cksum >> 0)) return false; if(read() != (uint8_t)(cksum >> 8)) return false; if(read() != (uint8_t)(cksum >> 16)) return false; @@ -154,25 +154,25 @@ struct bpsmulti { protected: file fp; - uint32_t checksum; + Hash::CRC32 checksum; //create() functions void ls(lstring& list, const string& path, const string& basepath) { lstring paths = directory::folders(path); for(auto& pathname : paths) { - list.append(string{path, pathname}.ltrim<1>(basepath)); + list.append(string{path, pathname}.ltrim(basepath)); ls(list, {path, pathname}, basepath); } lstring files = directory::files(path); for(auto& filename : files) { - list.append(string{path, filename}.ltrim<1>(basepath)); + list.append(string{path, filename}.ltrim(basepath)); } } void write(uint8_t data) { fp.write(data); - checksum = crc32_adjust(checksum, data); + checksum.data(data); } void writeNumber(uint64_t data) { @@ -203,7 +203,7 @@ protected: //apply() functions uint8_t read() { uint8_t data = fp.read(); - checksum = crc32_adjust(checksum, data); + checksum.data(data); return data; } @@ -221,9 +221,9 @@ protected: string readString(unsigned length) { string text; - text.reserve(length + 1); - for(unsigned n = 0; n < length; n++) text[n] = read(); - text[length] = 0; + text.resize(length + 1); + char* p = text.pointer(); + while(length--) *p++ = read(); return text; } diff --git a/nall/beat/patch.hpp b/nall/beat/patch.hpp index 59c6c5d1..081c4ff0 100644 --- a/nall/beat/patch.hpp +++ b/nall/beat/patch.hpp @@ -1,7 +1,6 @@ #ifndef NALL_BEAT_PATCH_HPP #define NALL_BEAT_PATCH_HPP -#include <nall/crc32.hpp> #include <nall/file.hpp> #include <nall/filemap.hpp> #include <nall/stdint.hpp> @@ -129,12 +128,12 @@ unsigned bpspatch::size() const { bpspatch::result bpspatch::apply() { if(modifySize < 19) return result::patch_too_small; - uint32_t modifyChecksum = ~0, targetChecksum = ~0; + Hash::CRC32 modifyChecksum, targetChecksum; unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; auto read = [&]() -> uint8_t { uint8_t data = modifyData[modifyOffset++]; - modifyChecksum = crc32_adjust(modifyChecksum, data); + modifyChecksum.data(data); return data; }; @@ -152,7 +151,7 @@ bpspatch::result bpspatch::apply() { auto write = [&](uint8_t data) { targetData[outputOffset++] = data; - targetChecksum = crc32_adjust(targetChecksum, data); + targetChecksum.data(data); }; if(read() != 'B') return result::patch_invalid_header; @@ -201,14 +200,13 @@ bpspatch::result bpspatch::apply() { uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0; for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n; for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n; - uint32_t checksum = ~modifyChecksum; + uint32_t checksum = modifyChecksum.value(); for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n; - uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize); - targetChecksum = ~targetChecksum; + uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).value(); if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid; - if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid; + if(targetChecksum.value() != modifyTargetChecksum) return result::target_checksum_invalid; if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid; return result::success; diff --git a/nall/config.hpp b/nall/config.hpp index 4c69bce8..0a7d8f55 100644 --- a/nall/config.hpp +++ b/nall/config.hpp @@ -60,7 +60,7 @@ struct Node { for(auto& child : children) { auto leaf = path[child.name]; if(!leaf.exists()) continue; - if(!child.empty()) child.set(leaf.data.trim<1>(" ", "\r")); + if(!child.empty()) child.set(leaf.text()); child.load(leaf); } } diff --git a/nall/crc16.hpp b/nall/crc16.hpp deleted file mode 100644 index be79a502..00000000 --- a/nall/crc16.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NALL_CRC16_HPP -#define NALL_CRC16_HPP - -#include <nall/stdint.hpp> - -namespace nall { - -inline uint16_t crc16_adjust(uint16_t crc16, uint8_t data) { - for(unsigned n = 0; n < 8; n++) { - if((crc16 & 1) ^ (data & 1)) crc16 = (crc16 >> 1) ^ 0x8408; - else crc16 >>= 1; - data >>= 1; - } - return crc16; -} - -inline uint16_t crc16_calculate(const uint8_t* data, unsigned length) { - uint16_t crc16 = ~0; - for(unsigned n = 0; n < length; n++) { - crc16 = crc16_adjust(crc16, data[n]); - } - return ~crc16; -} - -} - -#endif diff --git a/nall/decode/bmp.hpp b/nall/decode/bmp.hpp new file mode 100644 index 00000000..04330639 --- /dev/null +++ b/nall/decode/bmp.hpp @@ -0,0 +1,8 @@ +#ifndef NALL_DECODE_BMP_HPP +#define NALL_DECODE_BMP_HPP + +namespace nall { + +} + +#endif diff --git a/nall/gzip.hpp b/nall/decode/gzip.hpp similarity index 81% rename from nall/gzip.hpp rename to nall/decode/gzip.hpp index 2d43e7ab..db42100c 100644 --- a/nall/gzip.hpp +++ b/nall/decode/gzip.hpp @@ -1,12 +1,12 @@ -#ifndef NALL_GZIP_HPP -#define NALL_GZIP_HPP +#ifndef NALL_DECODE_GZIP_HPP +#define NALL_DECODE_GZIP_HPP #include <nall/file.hpp> -#include <nall/inflate.hpp> +#include <nall/decode/inflate.hpp> -namespace nall { +namespace nall { namespace Decode { -struct gzip { +struct GZIP { string filename; uint8_t* data = nullptr; unsigned size = 0; @@ -14,18 +14,18 @@ struct gzip { inline bool decompress(const string& filename); inline bool decompress(const uint8_t* data, unsigned size); - inline gzip(); - inline ~gzip(); + inline GZIP(); + inline ~GZIP(); }; -bool gzip::decompress(const string& filename) { +bool GZIP::decompress(const string& filename) { if(auto memory = file::read(filename)) { return decompress(memory.data(), memory.size()); } return false; } -bool gzip::decompress(const uint8_t* data, unsigned size) { +bool GZIP::decompress(const uint8_t* data, unsigned size) { if(size < 18) return false; if(data[0] != 0x1f) return false; if(data[1] != 0x8b) return false; @@ -73,13 +73,13 @@ bool gzip::decompress(const uint8_t* data, unsigned size) { return inflate(this->data, this->size, data + p, size - p - 8); } -gzip::gzip() { +GZIP::GZIP() { } -gzip::~gzip() { +GZIP::~GZIP() { if(data) delete[] data; } -} +}} #endif diff --git a/nall/inflate.hpp b/nall/decode/inflate.hpp similarity index 98% rename from nall/inflate.hpp rename to nall/decode/inflate.hpp index d096d173..00fb2305 100644 --- a/nall/inflate.hpp +++ b/nall/decode/inflate.hpp @@ -1,9 +1,9 @@ -#ifndef NALL_INFLATE_HPP -#define NALL_INFLATE_HPP +#ifndef NALL_DECODE_INFLATE_HPP +#define NALL_DECODE_INFLATE_HPP #include <setjmp.h> -namespace nall { +namespace nall { namespace Decode { namespace puff { inline int puff( @@ -344,6 +344,6 @@ inline int puff( } -} +}} #endif diff --git a/nall/png.hpp b/nall/decode/png.hpp similarity index 93% rename from nall/png.hpp rename to nall/decode/png.hpp index ccdf64eb..3991f823 100644 --- a/nall/png.hpp +++ b/nall/decode/png.hpp @@ -1,15 +1,12 @@ -#ifndef NALL_PNG_HPP -#define NALL_PNG_HPP +#ifndef NALL_DECODE_PNG_HPP +#define NALL_DECODE_PNG_HPP -//PNG image decoder -//author: byuu - -#include <nall/inflate.hpp> #include <nall/string.hpp> +#include <nall/decode/inflate.hpp> -namespace nall { +namespace nall { namespace Decode { -struct png { +struct PNG { struct Info { unsigned width; unsigned height; @@ -39,8 +36,8 @@ struct png { inline unsigned readbits(const uint8_t*& data); unsigned bitpos = 0; - inline png(); - inline ~png(); + inline PNG(); + inline ~PNG(); protected: enum class FourCC : unsigned { @@ -57,14 +54,14 @@ protected: inline unsigned read(const uint8_t* data, unsigned length); }; -bool png::decode(const string& filename) { +bool PNG::decode(const string& filename) { if(auto memory = file::read(filename)) { return decode(memory.data(), memory.size()); } return false; } -bool png::decode(const uint8_t* sourceData, unsigned sourceSize) { +bool PNG::decode(const uint8_t* sourceData, unsigned sourceSize) { if(sourceSize < 8) return false; if(read(sourceData + 0, 4) != 0x89504e47) return false; if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false; @@ -170,7 +167,7 @@ bool png::decode(const uint8_t* sourceData, unsigned sourceSize) { return true; } -unsigned png::interlace(unsigned pass, unsigned index) { +unsigned PNG::interlace(unsigned pass, unsigned index) { static const unsigned data[7][4] = { //x-distance, y-distance, x-origin, y-origin {8, 8, 0, 0}, @@ -184,7 +181,7 @@ unsigned png::interlace(unsigned pass, unsigned index) { return data[pass][index]; } -unsigned png::inflateSize() { +unsigned PNG::inflateSize() { if(info.interlaceMethod == 0) { return info.width * info.height * info.bytesPerPixel + info.height; } @@ -201,7 +198,7 @@ unsigned png::inflateSize() { return size; } -bool png::deinterlace(const uint8_t*& inputData, unsigned pass) { +bool PNG::deinterlace(const uint8_t*& inputData, unsigned pass) { unsigned xd = interlace(pass, 0), yd = interlace(pass, 1); unsigned xo = interlace(pass, 2), yo = interlace(pass, 3); unsigned width = (info.width + (xd - xo - 1)) / xd; @@ -227,7 +224,7 @@ bool png::deinterlace(const uint8_t*& inputData, unsigned pass) { return result; } -bool png::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height) { +bool PNG::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height) { uint8_t* wr = outputData; const uint8_t* rd = inputData; int bpp = info.bytesPerPixel, pitch = width * bpp; @@ -290,13 +287,13 @@ bool png::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, return true; } -unsigned png::read(const uint8_t* data, unsigned length) { +unsigned PNG::read(const uint8_t* data, unsigned length) { unsigned result = 0; while(length--) result = (result << 8) | (*data++); return result; } -unsigned png::readbits(const uint8_t*& data) { +unsigned PNG::readbits(const uint8_t*& data) { unsigned result = 0; switch(info.bitDepth) { case 1: @@ -325,13 +322,13 @@ unsigned png::readbits(const uint8_t*& data) { return result; } -png::png() { +PNG::PNG() { } -png::~png() { +PNG::~PNG() { if(data) delete[] data; } -} +}} #endif diff --git a/nall/unzip.hpp b/nall/decode/zip.hpp similarity index 94% rename from nall/unzip.hpp rename to nall/decode/zip.hpp index 269a15d2..419a99d3 100644 --- a/nall/unzip.hpp +++ b/nall/decode/zip.hpp @@ -1,14 +1,14 @@ -#ifndef NALL_UNZIP_HPP -#define NALL_UNZIP_HPP +#ifndef NALL_DECODE_ZIP_HPP +#define NALL_DECODE_ZIP_HPP #include <nall/filemap.hpp> -#include <nall/inflate.hpp> #include <nall/string.hpp> #include <nall/vector.hpp> +#include <nall/decode/inflate.hpp> -namespace nall { +namespace nall { namespace Decode { -struct unzip { +struct ZIP { struct File { string name; const uint8_t* data; @@ -102,7 +102,7 @@ struct unzip { if(fm.open()) fm.close(); } - ~unzip() { + ~ZIP() { close(); } @@ -121,6 +121,6 @@ public: vector<File> file; }; -} +}} #endif diff --git a/nall/directory.hpp b/nall/directory.hpp index 45a062c7..f2983df6 100644 --- a/nall/directory.hpp +++ b/nall/directory.hpp @@ -4,6 +4,7 @@ #include <nall/file.hpp> #include <nall/intrinsics.hpp> #include <nall/sort.hpp> +#include <nall/storage.hpp> #include <nall/string.hpp> #include <nall/vector.hpp> @@ -17,7 +18,7 @@ namespace nall { -struct directory { +struct directory : storage { static bool create(const string& pathname, unsigned permissions = 0755); //recursive static bool remove(const string& pathname); //recursive static bool exists(const string& pathname); @@ -73,7 +74,7 @@ private: #if defined(PLATFORM_WINDOWS) inline bool directory::create(const string& pathname, unsigned permissions) { string path; - lstring list = string{pathname}.transform("\\", "/").rtrim<1>("/").split("/"); + lstring list = string{pathname}.transform("\\", "/").rtrim("/").split("/"); bool result = true; for(auto& part : list) { path.append(part, "/"); @@ -93,7 +94,7 @@ private: inline bool directory::exists(const string& pathname) { string name = pathname; - name.trim<1>("\""); + name.trim("\"", "\""); DWORD result = GetFileAttributes(utf16_t(name)); if(result == INVALID_FILE_ATTRIBUTES) return false; return (result & FILE_ATTRIBUTE_DIRECTORY); @@ -103,7 +104,7 @@ private: lstring list; string path = pathname; path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); + if(!path.endsWith("\\")) path.append("\\"); path.append("*"); HANDLE handle; WIN32_FIND_DATA data; @@ -133,7 +134,7 @@ private: lstring list; string path = pathname; path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); + if(!path.endsWith("\\")) path.append("\\"); path.append("*"); HANDLE handle; WIN32_FIND_DATA data; @@ -154,12 +155,24 @@ private: return list; } #else + inline bool directory_is_folder(DIR* dp, struct dirent* ep) { + if(ep->d_type == DT_DIR) return true; + if(ep->d_type == DT_LNK || ep->d_type == DT_UNKNOWN) { + //symbolic links must be resolved to determine type + struct stat sp = {0}; + fstatat(dirfd(dp), ep->d_name, &sp, 0); + return S_ISDIR(sp.st_mode); + } + return false; + } + inline bool directory::create(const string& pathname, unsigned permissions) { string path; - lstring list = string{pathname}.rtrim<1>("/").split("/"); + lstring list = string{pathname}.rtrim("/").split("/"); bool result = true; for(auto& part : list) { path.append(part, "/"); + if(directory::exists(path)) continue; result &= (mkdir(path, permissions) == 0); } return result; @@ -175,7 +188,7 @@ private: } inline bool directory::exists(const string& pathname) { - DIR *dp = opendir(pathname); + DIR* dp = opendir(pathname); if(!dp) return false; closedir(dp); return true; @@ -190,15 +203,9 @@ private: while(ep = readdir(dp)) { if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, "..")) continue; - bool is_directory = ep->d_type & DT_DIR; - if(ep->d_type & DT_UNKNOWN) { - struct stat sp = {0}; - stat(string{pathname, ep->d_name}, &sp); - is_directory = S_ISDIR(sp.st_mode); - } - if(is_directory) { - if(strmatch(ep->d_name, pattern)) list.append(ep->d_name); - } + if(!directory_is_folder(dp, ep)) continue; + string name{ep->d_name}; + if(name.match(pattern)) list.append(std::move(name)); } closedir(dp); } @@ -215,9 +222,9 @@ private: while(ep = readdir(dp)) { if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, "..")) continue; - if((ep->d_type & DT_DIR) == 0) { - if(strmatch(ep->d_name, pattern)) list.append(ep->d_name); - } + if(directory_is_folder(dp, ep)) continue; + string name{ep->d_name}; + if(name.match(pattern)) list.append(std::move(name)); } closedir(dp); } diff --git a/nall/dl.hpp b/nall/dl.hpp index d0d0151e..baf7e70e 100644 --- a/nall/dl.hpp +++ b/nall/dl.hpp @@ -38,8 +38,10 @@ private: #if defined(PLATFORM_XORG) inline bool library::open(const string& name, const string& path) { if(handle) close(); - handle = (uintptr_t)dlopen(string(path, !path.empty() && !path.endsWith("/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY); + if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".so"), RTLD_LAZY); + if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".so"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY); + if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".so"), RTLD_LAZY); return handle; } @@ -62,8 +64,10 @@ inline void library::close() { #elif defined(PLATFORM_MACOSX) inline bool library::open(const string& name, const string& path) { if(handle) close(); - handle = (uintptr_t)dlopen(string(path, !path.empty() && !path.endsWith("/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY); + if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".dylib"), RTLD_LAZY); + if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".dylib"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY); + if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".dylib"), RTLD_LAZY); return handle; } @@ -86,8 +90,14 @@ inline void library::close() { #elif defined(PLATFORM_WINDOWS) inline bool library::open(const string& name, const string& path) { if(handle) close(); - string filepath(path, !path.empty() && !path.endsWith("/") && !path.endsWith("\\") ? "/" : "", name, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); + if(path) { + string filepath = {path, name, ".dll"}; + handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); + } + if(!handle) { + string filepath = {name, ".dll"}; + handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); + } return handle; } diff --git a/nall/file.hpp b/nall/file.hpp index 2cd28a13..cdebda4f 100644 --- a/nall/file.hpp +++ b/nall/file.hpp @@ -3,26 +3,18 @@ #include <nall/platform.hpp> #include <nall/stdint.hpp> +#include <nall/storage.hpp> #include <nall/string.hpp> #include <nall/utility.hpp> #include <nall/varint.hpp> -#include <nall/windows/utf8.hpp> +#include <nall/hash/sha256.hpp> #include <nall/stream/memory.hpp> namespace nall { -inline FILE* fopen_utf8(const string& filename, const string& mode) { - #if !defined(_WIN32) - return fopen(filename, mode); - #else - return _wfopen(utf16_t(filename), utf16_t(mode)); - #endif -} - -struct file : varint { +struct file : storage, varint { enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append }; enum class index : unsigned { absolute, relative }; - enum class time : unsigned { create, modify, access }; static bool copy(const string& sourcename, const string& targetname) { file rd, wr; @@ -32,29 +24,24 @@ struct file : varint { return true; } + //attempt to rename file first + //this will fail if paths point to different file systems; fall back to copy+remove in this case static bool move(const string& sourcename, const string& targetname) { - auto result = rename(sourcename, targetname); - if(result == 0) return true; - if(errno == EXDEV) { - //cannot move files between file systems; copy file instead of failing - if(file::copy(sourcename, targetname)) { - file::remove(sourcename); - return true; - } + if(rename(sourcename, targetname)) return true; + if(!writable(sourcename)) return false; + if(copy(sourcename, targetname)) { + remove(sourcename); + return true; } return false; } - static bool remove(const string& filename) { - return unlink(filename) == 0; - } - static bool truncate(const string& filename, unsigned size) { #if !defined(_WIN32) return truncate(filename, size) == 0; #else bool result = false; - FILE* fp = fopen(filename, "rb+"); + FILE* fp = _wfopen(utf16_t(filename), L"rb+"); if(fp) { result = _chsize(fileno(fp), size) == 0; fclose(fp); @@ -63,6 +50,29 @@ struct file : varint { #endif } + //specialization of storage::exists(); returns false for folders + static bool exists(const string& filename) { + #if !defined(_WIN32) + struct stat data; + if(stat(filename, &data) != 0) return false; + #else + struct __stat64 data; + if(_wstat64(utf16_t(filename), &data) != 0) return false; + #endif + return !(data.st_mode & S_IFDIR); + } + + static uintmax_t size(const string& filename) { + #if !defined(_WIN32) + struct stat data; + stat(filename, &data); + #else + struct __stat64 data; + _wstat64(utf16_t(filename), &data); + #endif + return S_ISREG(data.st_mode) ? data.st_size : 0u; + } + static vector<uint8_t> read(const string& filename) { vector<uint8_t> memory; file fp; @@ -115,7 +125,7 @@ struct file : varint { static string sha256(const string& filename) { auto buffer = read(filename); - return nall::sha256(buffer.data(), buffer.size()); + return Hash::SHA256(buffer.data(), buffer.size()).digest(); } uint8_t read() { @@ -231,44 +241,6 @@ struct file : varint { return file_offset >= file_size; } - static bool exists(const string& filename) { - #if !defined(_WIN32) - struct stat data; - if(stat(filename, &data) != 0) return false; - #else - struct __stat64 data; - if(_wstat64(utf16_t(filename), &data) != 0) return false; - #endif - //return true if this is a file, and false if this is a directory - return !(data.st_mode & S_IFDIR); - } - - static uintmax_t size(const string& filename) { - #if !defined(_WIN32) - struct stat data; - stat(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - return S_ISREG(data.st_mode) ? data.st_size : 0u; - } - - static time_t timestamp(const string& filename, file::time mode = file::time::create) { - #if !defined(_WIN32) - struct stat data; - stat(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - switch(mode) { default: - case file::time::create: return data.st_ctime; - case file::time::modify: return data.st_mtime; - case file::time::access: return data.st_atime; - } - } - bool open() const { return fp; } @@ -309,8 +281,9 @@ struct file : varint { fp = nullptr; } - file() { - } + file& operator=(const file&) = delete; + file(const file&) = delete; + file() = default; file(const string& filename, mode mode_) { open(filename, mode_); @@ -320,9 +293,6 @@ struct file : varint { close(); } - file& operator=(const file&) = delete; - file(const file&) = delete; - private: enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; char buffer[buffer_size] = {0}; diff --git a/nall/function.hpp b/nall/function.hpp index 77d2f41a..fe7382f1 100644 --- a/nall/function.hpp +++ b/nall/function.hpp @@ -1,6 +1,8 @@ #ifndef NALL_FUNCTION_HPP #define NALL_FUNCTION_HPP +#include <nall/traits.hpp> + namespace nall { template<typename T> class function; @@ -16,7 +18,7 @@ template<typename R, typename... P> class function<R (P...)> { struct global : container { R (*function)(P...); - R operator()(P... p) const { return function(std::forward<P>(p)...); } + R operator()(P... p) const { return function(forward<P>(p)...); } container* copy() const { return new global(function); } global(R (*function)(P...)) : function(function) {} }; @@ -24,21 +26,28 @@ template<typename R, typename... P> class function<R (P...)> { template<typename C> struct member : container { R (C::*function)(P...); C* object; - R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); } + R operator()(P... p) const { return (object->*function)(forward<P>(p)...); } container* copy() const { return new member(function, object); } member(R (C::*function)(P...), C* object) : function(function), object(object) {} }; template<typename L> struct lambda : container { mutable L object; - R operator()(P... p) const { return object(std::forward<P>(p)...); } + R operator()(P... p) const { return object(forward<P>(p)...); } container* copy() const { return new lambda(object); } lambda(const L& object) : object(object) {} }; + //value = true if R L::operator()(P...) exists + template<typename L> struct is_compatible { + template<typename T> static const typename is_same<R, decltype(declval<T>().operator()(declval<P>()...))>::type exists(T*); + template<typename T> static const false_type exists(...); + static constexpr bool value = decltype(exists<L>(0))::value; + }; + public: explicit operator bool() const { return callback; } - R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); } + R operator()(P... p) const { return (*callback)(forward<P>(p)...); } void reset() { if(callback) { delete callback; callback = nullptr; } } function& operator=(const function& source) { @@ -50,12 +59,12 @@ public: } function() = default; - function(const function &source) { operator=(source); } + function(const function& source) { operator=(source); } function(void* function) { if(function) callback = new global((R (*)(P...))function); } function(R (*function)(P...)) { callback = new global(function); } template<typename C> function(R (C::*function)(P...), C* object) { callback = new member<C>(function, object); } template<typename C> function(R (C::*function)(P...) const, C* object) { callback = new member<C>((R (C::*)(P...))function, object); } - template<typename L> function(const L& object) { callback = new lambda<L>(object); } + template<typename L, typename = enable_if<is_compatible<L>>> function(const L& object) { callback = new lambda<L>(object); } ~function() { if(callback) delete callback; } }; diff --git a/nall/hash/crc16.hpp b/nall/hash/crc16.hpp new file mode 100644 index 00000000..12c582f4 --- /dev/null +++ b/nall/hash/crc16.hpp @@ -0,0 +1,43 @@ +#ifndef NALL_HASH_CRC16_HPP +#define NALL_HASH_CRC16_HPP + +#include <nall/range.hpp> + +namespace nall { +struct string; +namespace Hash { + +struct CRC16 { + CRC16() { reset(); } + CRC16(const void* values, unsigned size) : CRC16() { data(values, size); } + + auto reset() -> void { + checksum = ~0; + } + + auto data(uint8_t value) -> void { + for(auto n : range(8)) { + if((checksum & 1) ^ (value & 1)) checksum = (checksum >> 1) ^ 0x8408; + else checksum >>= 1; + value >>= 1; + } + } + + auto data(const void* values, unsigned size) -> void { + auto p = (const uint8_t*)values; + while(size--) data(*p++); + } + + auto value() -> uint16_t { + return ~checksum; + } + + inline auto digest() -> string; + +private: + uint16_t checksum; +}; + +}} + +#endif diff --git a/nall/crc32.hpp b/nall/hash/crc32.hpp similarity index 80% rename from nall/crc32.hpp rename to nall/hash/crc32.hpp index 75700101..3ecdd64f 100644 --- a/nall/crc32.hpp +++ b/nall/hash/crc32.hpp @@ -1,11 +1,13 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP +#ifndef NALL_HASH_CRC32_HPP +#define NALL_HASH_CRC32_HPP -#include <nall/stdint.hpp> +#include <nall/range.hpp> namespace nall { +struct string; +namespace Hash { -const uint32_t crc32_table[256] = { +const uint32_t _crc32_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, @@ -48,21 +50,36 @@ const uint32_t crc32_table[256] = { 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; -inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; -} +struct CRC32 { + CRC32() { reset(); } + CRC32(const void* values, unsigned size) : CRC32() { data(values, size); } -inline uint32_t crc32_calculate(const uint8_t* data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); + auto reset() -> void { + checksum = ~0; } - return ~crc32; -} -} + auto data(uint8_t value) -> void { + checksum = ((checksum >> 8) & 0xffffff) ^ _crc32_table[(checksum ^ value) & 0xff]; + } + + auto data(const void* values, unsigned size) -> void { + auto p = (const uint8_t*)values; + while(size--) data(*p++); + } + + auto value() const -> uint32_t { + return ~checksum; + } + + inline auto digest() -> string; + +private: + uint32_t checksum; +}; + +}} #endif diff --git a/nall/hash/sha256.hpp b/nall/hash/sha256.hpp new file mode 100644 index 00000000..27105407 --- /dev/null +++ b/nall/hash/sha256.hpp @@ -0,0 +1,111 @@ +#ifndef NALL_HASH_SHA256_HPP +#define NALL_HASH_SHA256_HPP + +#include <nall/range.hpp> + +namespace nall { +struct string; +namespace Hash { + +struct SHA256 { + SHA256() { reset(); } + SHA256(const void* values, unsigned size) : SHA256() { data(values, size); } + + auto reset() -> void { + for(auto n : input) n = 0; + for(auto n : w) n = 0; + for(auto n : range(8)) h[n] = square(n); + queued = length = 0; + } + + auto data(uint8_t value) -> void { + byte(value); + length++; + } + + auto data(const void* values, unsigned size) -> void { + length += size; + auto p = (const uint8_t*)values; + while(size--) byte(*p++); + } + + auto value() const -> vector<uint8_t> { + SHA256 self(*this); + self.finish(); + vector<uint8_t> result; + for(auto n : range(32)) result.append(self.h[n >> 2] >> ((3 - (n & 3)) << 3)); + return result; + } + + inline auto digest() const -> nall::string; + +private: + auto byte(uint8_t value) -> void { + auto shift = (3 - (queued & 3)) * 8; + input[queued >> 2] &= ~(0xff << shift); + input[queued >> 2] |= (value << shift); + if(++queued == 64) block(), queued = 0; + } + + auto block() -> void { + for(auto n : range(16)) w[n] = input[n]; + for(auto n : range(16, 64)) { + uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3); + uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10); + w[n] = w[n - 16] + w[n - 7] + a + b; + } + uint32_t t[8]; + for(auto n : range(8)) t[n] = h[n]; + for(auto n : range(64)) { + uint32_t a = ror(t[0], 2) ^ ror(t[0], 13) ^ ror(t[0], 22); + uint32_t b = ror(t[4], 6) ^ ror(t[4], 11) ^ ror(t[4], 25); + uint32_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]); + uint32_t d = (t[4] & t[5]) ^ (~t[4] & t[6]); + uint32_t e = t[7] + w[n] + cube(n) + b + d; + t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e; + t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e; + } + for(auto n : range(8)) h[n] += t[n]; + } + + auto finish() -> void { + byte(0x80); + while(queued != 56) byte(0x00); + for(auto n : range(8)) byte((length << 3) >> ((7 - n) << 3)); + } + + auto ror(uint32_t x, uint32_t n) -> uint32_t { + return (x >> n) | (x << 32 - n); + } + + auto square(unsigned n) -> uint32_t { + static const uint32_t value[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, + }; + return value[n]; + } + + auto cube(unsigned n) -> uint32_t { + static const uint32_t value[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, + }; + return value[n]; + } + + uint32_t input[16]; + uint32_t queued; + uint32_t w[64]; + uint32_t h[8]; + uint64_t length; +}; + +}} + +#endif diff --git a/nall/http.hpp b/nall/http.hpp deleted file mode 100644 index 55421867..00000000 --- a/nall/http.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef NALL_HTTP_HPP -#define NALL_HTTP_HPP - -#if !defined(_WIN32) - #include <sys/types.h> - #include <sys/socket.h> - #include <netinet/in.h> - #include <netdb.h> -#else - #include <winsock2.h> - #include <ws2tcpip.h> - #include <windows.h> -#endif - -#include <nall/platform.hpp> -#include <nall/string.hpp> - -namespace nall { - -struct http { - string hostname; - addrinfo* serverinfo; - int serversocket; - string header; - - inline void download(const string& path, uint8_t*& data, unsigned& size) { - data = nullptr; - size = 0; - - send({ - "GET ", path, " HTTP/1.1\r\n" - "Host: ", hostname, "\r\n" - "Connection: close\r\n" - "\r\n" - }); - - header = downloadHeader(); - downloadContent(data, size); - } - - inline bool connect(string host, unsigned port) { - hostname = host; - - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - int status = getaddrinfo(hostname, string(port), &hints, &serverinfo); - if(status != 0) return false; - - serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); - if(serversocket == -1) return false; - - int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen); - if(result == -1) return false; - - return true; - } - - inline bool send(const string& data) { - return send((const uint8_t*)(const char*)data, data.length()); - } - - inline bool send(const uint8_t* data, unsigned size) { - while(size) { - int length = ::send(serversocket, (const char*)data, size, 0); - if(length == -1) return false; - data += length; - size -= length; - } - return true; - } - - inline string downloadHeader() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endsWith("\r\n\r\n") == false); - return output; - } - - inline string downloadChunkLength() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endsWith("\r\n") == false); - return output; - } - - inline void downloadContent(uint8_t*& data, unsigned& size) { - unsigned capacity = 0; - - if(header.ifind("\r\nTransfer-Encoding: chunked\r\n")) { - while(true) { - unsigned length = hex(downloadChunkLength()); - if(length == 0) break; - capacity += length; - data = (uint8_t*)realloc(data, capacity); - - char buffer[length]; - while(length) { - int packetlength = recv(serversocket, buffer, length, 0); - if(packetlength <= 0) break; - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } - } else if(auto position = header.ifind("\r\nContent-Length: ")) { - unsigned length = decimal((const char*)header + position() + 18); - while(length) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, min(256, length), 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } else { - while(true) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, 256, 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - } - } - - data = (uint8_t*)realloc(data, capacity + 1); - data[capacity] = 0; - } - - inline void disconnect() { - close(serversocket); - freeaddrinfo(serverinfo); - serverinfo = nullptr; - serversocket = -1; - } - - #ifdef _WIN32 - inline int close(int sock) { - return closesocket(sock); - } - - inline http() { - int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { - WSADATA wsaData; - if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - WSACleanup(); - return; - } - } else { - close(sock); - } - } - #endif -}; - -} - -#endif diff --git a/nall/http/client.hpp b/nall/http/client.hpp new file mode 100644 index 00000000..9c578640 --- /dev/null +++ b/nall/http/client.hpp @@ -0,0 +1,59 @@ +#ifndef NALL_HTTP_CLIENT_HPP +#define NALL_HTTP_CLIENT_HPP + +#include <nall/http/role.hpp> + +namespace nall { + +struct httpClient : httpRole { + inline auto open(const string& hostname, unsigned port = 80) -> bool; + inline auto upload(const httpRequest& request) -> bool; + inline auto download(const httpRequest& request) -> httpResponse; + inline auto close() -> void; + ~httpClient() { close(); } + +private: + signed fd = -1; + addrinfo* info = nullptr; +}; + +auto httpClient::open(const string& hostname, unsigned port) -> bool { + addrinfo hint = {0}; + hint.ai_family = AF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = AI_ADDRCONFIG; + + if(getaddrinfo(hostname, string{port}, &hint, &info) != 0) return close(), false; + + fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol); + if(fd < 0) return close(), false; + + if(connect(fd, info->ai_addr, info->ai_addrlen) < 0) return close(), false; + return true; +} + +auto httpClient::upload(const httpRequest& request) -> bool { + return httpRole::upload(fd, request); +} + +auto httpClient::download(const httpRequest& request) -> httpResponse { + httpResponse response(request); + httpRole::download(fd, response); + return response; +} + +auto httpClient::close() -> void { + if(fd) { + ::close(fd); + fd = -1; + } + + if(info) { + freeaddrinfo(info); + info = nullptr; + } +} + +} + +#endif diff --git a/nall/http/message.hpp b/nall/http/message.hpp new file mode 100644 index 00000000..569a789e --- /dev/null +++ b/nall/http/message.hpp @@ -0,0 +1,77 @@ +#ifndef NALL_HTTP_MESSAGE_HPP +#define NALL_HTTP_MESSAGE_HPP + +//httpMessage: base class for httpRequest and httpResponse +//provides shared functionality + +namespace nall { + +struct httpVariable { + string name; + string value; +}; + +struct httpVariables : vector<httpVariable> { + auto append(const string& name, const string& value) -> void; + auto get(const string& name) const -> string; + auto remove(const string& name) -> void; + auto set(const string& name, const string& value) -> void; +}; + +auto httpVariables::append(const string& name, const string& value) -> void { + vector::append({name, value}); +} + +auto httpVariables::get(const string& name) const -> string { + for(auto& variable : *this) { + if(variable.name.iequals(name)) return variable.value; + } + return ""; +} + +auto httpVariables::remove(const string& name) -> void { + while(true) { + unsigned n = 0; + bool found = false; + for(auto& variable : *this) { + if(!variable.name.iequals(name)) { n++; continue; } + vector::remove(n); + found = true; + break; + } + if(found == false) break; + } +} + +auto httpVariables::set(const string& name, const string& value) -> void { + for(auto& variable : *this) { + if(!variable.name.iequals(name)) continue; + variable.name = name; + variable.value = value; + return; + } + vector::append({name, value}); +} + +struct httpMessage { + using type = httpMessage; + + virtual auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool = 0; + virtual auto setHead() -> bool = 0; + + virtual auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool = 0; + virtual auto setBody() -> bool = 0; + + virtual auto header(const string& name) const -> string { return _header.get(name); } + virtual auto appendHeader(const string& name, const string& value = "") -> type& { return _header.append(name, value), *this; } + virtual auto removeHeader(const string& name) -> type& { return _header.remove(name), *this; } + virtual auto setHeader(const string& name, const string& value = "") -> type& { return _header.set(name, value), *this; } + + string _head; + string _body; + httpVariables _header; +}; + +} + +#endif diff --git a/nall/http/request.hpp b/nall/http/request.hpp new file mode 100644 index 00000000..934db529 --- /dev/null +++ b/nall/http/request.hpp @@ -0,0 +1,146 @@ +#ifndef NALL_HTTP_REQUEST_HPP +#define NALL_HTTP_REQUEST_HPP + +#include <nall/http/message.hpp> + +namespace nall { + +struct httpRequest : httpMessage { + using type = httpRequest; + + enum class RequestType : unsigned { None, Head, Get, Post }; + + explicit operator bool() const { return requestType() != RequestType::None; } + + inline auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool; + inline auto setHead() -> bool; + + inline auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool; + inline auto setBody() -> bool; + + auto ip() const -> string { + return {(uint8_t)(_ip >> 24), ".", (uint8_t)(_ip >> 16), ".", (uint8_t)(_ip >> 8), ".", (uint8_t)(_ip >> 0)}; + } + + auto requestType() const -> RequestType { return _requestType; } + auto setRequestType(RequestType value) -> void { _requestType = value; } + + auto path() const -> string { return _path; } + auto setPath(const string& value) -> void { _path = value; } + + auto appendHeader(const string& name, const string& value = "") -> type& { return httpMessage::appendHeader(name, value), *this; } + auto removeHeader(const string& name) -> type& { return httpMessage::removeHeader(name), *this; } + auto setHeader(const string& name, const string& value = "") -> type& { return httpMessage::setHeader(name, value), *this; } + + auto get(const string& name) -> string { return _get.get(name); } + auto setGet(const string& name, const string& value = "") -> void { return _get.set(name, value); } + + auto post(const string& name) -> string { return _post.get(name); } + auto setPost(const string& name, const string& value = "") -> void { return _post.set(name, value); } + +//private: + uint32_t _ip = 0; + RequestType _requestType = RequestType::None; + string _path; + httpVariables _cookie; + httpVariables _get; + httpVariables _post; +}; + +auto httpRequest::head(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool { + if(!callback) return false; + string output; + + string request = path(); + if(_get.size()) { + request.append("?"); + for(auto& get : _get) { + request.append(get.name, "=", get.value, "&"); + } + request.rtrim("&"); + } + + switch(requestType()) { + case RequestType::Head: output.append("HEAD ", request, " HTTP/1.1\r\n"); break; + case RequestType::Get : output.append("GET ", request, " HTTP/1.1\r\n"); break; + case RequestType::Post: output.append("POST ", request, " HTTP/1.1\r\n"); break; + default: return false; + } + + for(auto& header : _header) { + output.append(header.name, ": ", header.value, "\r\n"); + } + output.append("\r\n"); + + return callback(output.binary(), output.size()); +} + +auto httpRequest::setHead() -> bool { + lstring headers = _head.split("\n"); + string request = headers.takeFirst().rtrim("\r"); + string requestHost; + + if(irtrim(request, " HTTP/1.0")); + else if(irtrim(request, " HTTP/1.1")); + else return false; + + if(iltrim(request, "HEAD ")) setRequestType(RequestType::Head); + else if(iltrim(request, "GET " )) setRequestType(RequestType::Get ); + else if(iltrim(request, "POST ")) setRequestType(RequestType::Post); + else return false; + + //decode absolute URIs + request.strip().iltrim("http://"); + if(!request.beginsWith("/")) { + lstring components = request.split<1>("/"); + requestHost = components(0); + request = {"/", components(1)}; + } + + lstring components = request.split<1>("?"); + setPath(components(0)); + + if(auto queryString = components(1)) { + for(auto& block : queryString.split("&")) { + lstring variable = block.split<1>("="); + if(variable(0)) setGet(variable(0), variable(1)); + } + } + + for(auto& header : headers) { + if(header.beginsWith(" ") || header.beginsWith("\t")) continue; + auto part = header.split<1>(":").strip(); + if(!part[0] || part.size() != 2) continue; + appendHeader(part[0], part[1]); + } + + if(requestHost) setHeader("Host", requestHost); //request URI overrides host header + return true; +} + +auto httpRequest::body(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool { + if(!callback) return false; + + if(_body) { + return callback(_body.binary(), _body.size()); + } + + return true; +} + +auto httpRequest::setBody() -> bool { + if(requestType() == RequestType::Post) { + if(header("Content-Type").iequals("application/x-www-form-urlencoded")) { + for(auto& block : _body.split("\n")) { + lstring variable = block.rtrim("\r").split<1>("="); + if(variable(0)) setPost(variable(0), variable(1)); + } + } + } + + return true; +} + +} + +#endif diff --git a/nall/http/response.hpp b/nall/http/response.hpp new file mode 100644 index 00000000..7bca9201 --- /dev/null +++ b/nall/http/response.hpp @@ -0,0 +1,253 @@ +#ifndef NALL_HTTP_RESPONSE_HPP +#define NALL_HTTP_RESPONSE_HPP + +#include <nall/http/message.hpp> + +namespace nall { + +struct httpResponse : httpMessage { + using type = httpResponse; + + httpResponse() = default; + httpResponse(const httpRequest& request) { setRequest(request); } + + explicit operator bool() const { return responseType() != 0; } + auto operator()(unsigned responseType) -> type& { return setResponseType(responseType); } + + inline auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool; + inline auto setHead() -> bool; + + inline auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool; + inline auto setBody() -> bool; + + auto request() const -> const httpRequest* { return _request; } + auto setRequest(const httpRequest& value) -> type& { _request = &value; return *this; } + + auto responseType() const -> unsigned { return _responseType; } + auto setResponseType(unsigned value) -> type& { _responseType = value; return *this; } + + auto appendHeader(const string& name, const string& value = "") -> type& { return httpMessage::appendHeader(name, value), *this; } + auto removeHeader(const string& name) -> type& { return httpMessage::removeHeader(name), *this; } + auto setHeader(const string& name, const string& value = "") -> type& { return httpMessage::setHeader(name, value), *this; } + + auto hasData() const -> bool { return (bool)_data; } + auto data() const -> const vector<uint8_t>& { return _data; } + inline auto setData(const vector<uint8_t>& value) -> type&; + + auto hasFile() const -> bool { return (bool)_file; } + auto file() const -> const string& { return _file; } + inline auto setFile(const string& value) -> type&; + + auto hasText() const -> bool { return (bool)_text; } + auto text() const -> const string& { return _text; } + inline auto setText(const string& value) -> type&; + + inline auto hasBody() const -> bool; + inline auto findContentLength() const -> unsigned; + inline auto findContentType() const -> string; + inline auto findContentType(const string& suffix) const -> string; + inline auto findResponseType() const -> string; + inline auto setFileETag() -> void; + + const httpRequest* _request = nullptr; + unsigned _responseType = 0; + vector<uint8_t> _data; + string _file; + string _text; +}; + +auto httpResponse::head(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool { + if(!callback) return false; + string output; + + if(auto request = this->request()) { + if(auto eTag = header("ETag")) { + if(eTag == request->header("If-None-Match")) { + output.append("HTTP/1.1 304 Not Modified\r\n"); + output.append("Connection: close\r\n"); + output.append("\r\n"); + return callback(output.binary(), output.size()); + } + } + } + + output.append("HTTP/1.1 ", findResponseType(), "\r\n"); + for(auto& header : _header) { + output.append(header.name, ": ", header.value, "\r\n"); + } + if(hasBody()) { + if(!header("Content-Length") && !header("Transfer-Encoding").iequals("chunked")) { + output.append("Content-Length: ", findContentLength(), "\r\n"); + } + if(!header("Content-Type")) { + output.append("Content-Type: ", findContentType(), "\r\n"); + } + } + if(!header("Connection")) { + output.append("Connection: close\r\n"); + } + output.append("\r\n"); + + return callback(output.binary(), output.size()); +} + +auto httpResponse::setHead() -> bool { + lstring headers = _head.split("\n"); + string response = headers.takeFirst().rtrim("\r"); + + if(iltrim(response, "HTTP/1.0 ")); + else if(iltrim(response, "HTTP/1.1 ")); + else return false; + + setResponseType(decimal(response)); + + for(auto& header : headers) { + if(header.beginsWith(" ") || header.beginsWith("\t")) continue; + lstring variable = header.split<1>(":").strip(); + if(variable.size() != 2) continue; + appendHeader(variable[0], variable[1]); + } + + return true; +} + +auto httpResponse::body(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool { + if(!callback) return false; + if(!hasBody()) return true; + bool chunked = header("Transfer-Encoding") == "chunked"; + + if(chunked) { + string prefix = {hex(findContentLength()), "\r\n"}; + if(!callback(prefix.binary(), prefix.size())) return false; + } + + if(_body) { + if(!callback(_body.binary(), _body.size())) return false; + } else if(hasData()) { + if(!callback(data().data(), data().size())) return false; + } else if(hasFile()) { + filemap map(file(), filemap::mode::read); + if(!callback(map.data(), map.size())) return false; + } else if(hasText()) { + if(!callback(text().binary(), text().size())) return false; + } else { + string response = findResponseType(); + if(!callback(response.binary(), response.size())) return false; + } + + if(chunked) { + string suffix = {"\r\n0\r\n\r\n"}; + if(!callback(suffix.binary(), suffix.size())) return false; + } + + return true; +} + +auto httpResponse::setBody() -> bool { + return true; +} + +auto httpResponse::hasBody() const -> bool { + if(auto request = this->request()) { + if(request->requestType() == httpRequest::RequestType::Head) return false; + } + if(responseType() == 301) return false; + if(responseType() == 302) return false; + if(responseType() == 303) return false; + if(responseType() == 304) return false; + if(responseType() == 307) return false; + return true; +} + +auto httpResponse::findContentLength() const -> unsigned { + if(auto contentLength = header("Content-Length")) return decimal(contentLength); + if(_body) return _body.size(); + if(hasData()) return data().size(); + if(hasFile()) return file::size(file()); + if(hasText()) return text().size(); + return findResponseType().size(); +} + +auto httpResponse::findContentType() const -> string { + if(auto contentType = header("Content-Type")) return contentType; + if(hasData()) return "application/octet-stream"; + if(hasFile()) return findContentType(file().suffixname()); + return "text/html; charset=utf-8"; +} + +auto httpResponse::findContentType(const string& s) const -> string { + if(s == ".7z" ) return "application/x-7z-compressed"; + if(s == ".avi" ) return "video/avi"; + if(s == ".bml" ) return "text/plain; charset=utf-8"; + if(s == ".bz2" ) return "application/x-bzip2"; + if(s == ".css" ) return "text/css; charset=utf-8"; + if(s == ".gif" ) return "image/gif"; + if(s == ".gz" ) return "application/gzip"; + if(s == ".htm" ) return "text/html; charset=utf-8"; + if(s == ".html") return "text/html; charset=utf-8"; + if(s == ".jpg" ) return "image/jpeg"; + if(s == ".jpeg") return "image/jpeg"; + if(s == ".js" ) return "application/javascript"; + if(s == ".mka" ) return "audio/x-matroska"; + if(s == ".mkv" ) return "video/x-matroska"; + if(s == ".mp3" ) return "audio/mpeg"; + if(s == ".mp4" ) return "video/mp4"; + if(s == ".mpeg") return "video/mpeg"; + if(s == ".mpg" ) return "video/mpeg"; + if(s == ".ogg" ) return "audio/ogg"; + if(s == ".pdf" ) return "application/pdf"; + if(s == ".png" ) return "image/png"; + if(s == ".rar" ) return "application/x-rar-compressed"; + if(s == ".svg" ) return "image/svg+xml"; + if(s == ".tar" ) return "application/x-tar"; + if(s == ".txt" ) return "text/plain; charset=utf-8"; + if(s == ".wav" ) return "audio/vnd.wave"; + if(s == ".webm") return "video/webm"; + if(s == ".xml" ) return "text/xml; charset=utf-8"; + if(s == ".xz" ) return "application/x-xz"; + if(s == ".zip" ) return "application/zip"; + return "application/octet-stream"; //binary +} + +auto httpResponse::findResponseType() const -> string { + switch(responseType()) { + case 200: return "200 OK"; + case 301: return "301 Moved Permanently"; + case 302: return "302 Found"; + case 303: return "303 See Other"; + case 304: return "304 Not Modified"; + case 307: return "307 Temporary Redirect"; + case 400: return "400 Bad Request"; + case 403: return "403 Forbidden"; + case 404: return "404 Not Found"; + case 500: return "500 Internal Server Error"; + case 501: return "501 Not Implemented"; + case 503: return "503 Service Unavailable"; + } + return "501 Not Implemented"; +} + +auto httpResponse::setData(const vector<uint8_t>& value) -> type& { + _data = value; + setHeader("Content-Length", value.size()); + return *this; +} + +auto httpResponse::setFile(const string& value) -> type& { + _file = value; + string eTag = {"\"", string::datetime(file::timestamp(value, file::time::modify)), "\""}; + setHeader("Content-Length", file::size(value)); + setHeader("Cache-Control", "public"); + setHeader("ETag", eTag); + return *this; +} + +auto httpResponse::setText(const string& value) -> type& { + _text = value; + setHeader("Content-Length", value.size()); + return *this; +} + +} + +#endif diff --git a/nall/http/role.hpp b/nall/http/role.hpp new file mode 100644 index 00000000..7a1970e2 --- /dev/null +++ b/nall/http/role.hpp @@ -0,0 +1,161 @@ +#ifndef NALL_HTTP_ROLE_HPP +#define NALL_HTTP_ROLE_HPP + +//httpRole: base class for httpClient and httpServer +//provides shared functionality + +#include <nall/http/request.hpp> +#include <nall/http/response.hpp> + +namespace nall { + +struct httpRole { + struct Settings { + signed connectionLimit = 1024; //server + signed headSizeLimit = 16384; //client, server + signed bodySizeLimit = 65536; //client, server + signed chunkSize = 32768; //client, server + signed threadStackSize = 131072; //server + signed timeoutReceive = 15000; //server + signed timeoutSend = 15000; //server + } settings; + + inline auto configure(const string& parameters) -> bool; + inline auto download(signed fd, httpMessage& message) -> bool; + inline auto upload(signed fd, const httpMessage& message) -> bool; +}; + +auto httpRole::configure(const string& parameters) -> bool { + auto document = Markup::Document(parameters); + for(auto& parameter : document) { + string& name = parameter.name; + signed value = parameter.integer(); + + if(0); + else if(name == "connectionLimit") settings.connectionLimit = value; + else if(name == "headSizeLimit") settings.headSizeLimit = value; + else if(name == "bodySizeLimit") settings.bodySizeLimit = value; + else if(name == "chunkSize") settings.chunkSize = value; + else if(name == "threadStackSize") settings.threadStackSize = value; + else if(name == "timeoutReceive") settings.timeoutReceive = value; + else if(name == "timeoutSend") settings.timeoutSend = value; + } + return true; +} + +auto httpRole::download(signed fd, httpMessage& message) -> bool { + auto& head = message._head; + auto& body = message._body; + string chunk; + uint8_t packet[settings.chunkSize], *p = nullptr; + + head.reset(), head.reserve(4095); + body.reset(), body.reserve(4095); + + bool headReceived = false; + bool chunked = false; + bool chunkReceived = false; + bool chunkFooterReceived = true; + signed length = 0; + signed chunkLength = 0; + signed contentLength = 0; + + while(true) { + if(auto limit = settings.headSizeLimit) if(head.size() >= limit) return false; + if(auto limit = settings.bodySizeLimit) if(body.size() >= limit) return false; + + if(headReceived && !chunked && body.size() >= contentLength) { + body.resize(contentLength); + break; + } + + if(length == 0) { + length = recv(fd, packet, settings.chunkSize, MSG_NOSIGNAL); + if(length <= 0) return false; + p = packet; + } + + if(!headReceived) { + head.append((char)*p++); + --length; + + if(head.endsWith("\r\n\r\n") || head.endsWith("\n\n")) { + headReceived = true; + if(!message.setHead()) return false; + chunked = message.header("Transfer-Encoding").iequals("chunked"); + contentLength = decimal(message.header("Content-Length")); + } + + continue; + } + + if(chunked && !chunkReceived) { + char n = *p++; + --length; + + if(!chunkFooterReceived) { + if(n == '\n') chunkFooterReceived = true; + continue; + } + + chunk.append(n); + + if(chunk.endsWith("\r\n") || chunk.endsWith("\n")) { + chunkReceived = true; + chunkLength = hex(chunk); + if(chunkLength == 0) break; + chunk.reset(); + } + + continue; + } + + if(!chunked) { + body.resize(body.size() + length); + memory::copy(body.pointer() + body.size() - length, p, length); + + p += length; + length = 0; + } else { + signed transferLength = min(length, chunkLength); + body.resize(body.size() + transferLength); + memory::copy(body.pointer() + body.size() - transferLength, p, transferLength); + + p += transferLength; + length -= transferLength; + chunkLength -= transferLength; + + if(chunkLength == 0) { + chunkReceived = false; + chunkFooterReceived = false; + } + } + } + + if(!message.setBody()) return false; + return true; +} + +auto httpRole::upload(signed fd, const httpMessage& message) -> bool { + auto transfer = [&](const uint8_t* data, unsigned size) -> bool { + while(size) { + signed length = send(fd, data, min(size, settings.chunkSize), MSG_NOSIGNAL); + if(length < 0) return false; + data += length; + size -= length; + } + return true; + }; + + if(message.head([&](const uint8_t* data, unsigned size) -> bool { return transfer(data, size); })) { + if(message.body([&](const uint8_t* data, unsigned size) -> bool { return transfer(data, size); })) { + return true; + } + } + + return false; +} + +} + +#endif diff --git a/nall/http/server.hpp b/nall/http/server.hpp new file mode 100644 index 00000000..41a57e07 --- /dev/null +++ b/nall/http/server.hpp @@ -0,0 +1,136 @@ +#ifndef NALL_HTTP_SERVER_HPP +#define NALL_HTTP_SERVER_HPP + +#include <poll.h> +#include <atomic> + +#include <nall/service.hpp> +#include <nall/http/role.hpp> + +namespace nall { + +struct httpServer : httpRole, service { + inline auto open(unsigned port = 8080, const string& serviceName = "", const string& command = "") -> bool; + inline auto main(const function<httpResponse (httpRequest&)>& function = {}) -> void; + inline auto scan() -> string; + inline auto close() -> void; + ~httpServer() { close(); } + +private: + signed fd = -1; + function<httpResponse (httpRequest&)> callback; + struct sockaddr_in addrin = {0}; + std::atomic<signed> connections{0}; +}; + +auto httpServer::open(unsigned port, const string& serviceName, const string& command) -> bool { + if(serviceName) { + if(!service::command(serviceName, command)) return false; + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if(fd < 0) return false; + + { + #if defined(SO_RCVTIMEO) + if(settings.timeoutReceive) { + struct timeval rcvtimeo; + rcvtimeo.tv_sec = settings.timeoutReceive / 1000; + rcvtimeo.tv_usec = settings.timeoutReceive % 1000 * 1000; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(struct timeval)); + } + #endif + + #if defined(SO_SNDTIMEO) + if(settings.timeoutSend) { + struct timeval sndtimeo; + sndtimeo.tv_sec = settings.timeoutSend / 1000; + sndtimeo.tv_usec = settings.timeoutSend % 1000 * 1000; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &sndtimeo, sizeof(struct timeval)); + } + #endif + + #if defined(SO_NOSIGPIPE) //BSD, OSX + signed nosigpipe = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(signed)); + #endif + + #if defined(SO_REUSEADDR) //BSD, Linux, OSX + signed reuseaddr = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(signed)); + #endif + + #if defined(SO_REUSEPORT) //BSD, OSX + signed reuseport = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(signed)); + #endif + } + + addrin.sin_family = AF_INET; + addrin.sin_addr.s_addr = htonl(INADDR_ANY); + addrin.sin_port = htons(port); + + signed result = bind(fd, (struct sockaddr*)&addrin, sizeof(addrin)); + if(result < 0) return close(), false; + + result = listen(fd, SOMAXCONN); //system-wide limit (per port) + if(result < 0) return close(), false; + + return true; +} + +auto httpServer::main(const function<httpResponse (httpRequest&)>& function) -> void { + callback = function; +} + +auto httpServer::scan() -> string { + if(auto command = service::receive()) return command; + + if(connections >= settings.connectionLimit) return "busy"; + + struct pollfd query = {0}; + query.fd = fd; + query.events = POLLIN; + poll(&query, 1, 0); + + if(query.fd == fd && query.revents & POLLIN) { + ++connections; + + thread::create([&](uintptr_t) { + thread::detach(); + + signed clientfd = -1; + struct sockaddr_in settings = {0}; + socklen_t socklen = sizeof(sockaddr_in); + + clientfd = accept(fd, (struct sockaddr*)&settings, &socklen); + if(clientfd < 0) return; + + httpRequest request; + request._ip = ntohl(settings.sin_addr.s_addr); + + if(download(clientfd, request) && callback) { + auto response = callback(request); + upload(clientfd, response); + } else { + upload(clientfd, httpResponse()); //"501 Not Implemented" + } + + ::close(clientfd); + --connections; + }, 0, settings.threadStackSize); + } + + return "ok"; +} + +auto httpServer::close() -> void { + if(fd) { + ::close(fd); + fd = -1; + } +} + +} + +#endif diff --git a/nall/image.hpp b/nall/image.hpp index 5f39fce5..b1c865ea 100644 --- a/nall/image.hpp +++ b/nall/image.hpp @@ -6,9 +6,8 @@ #include <nall/bmp.hpp> #include <nall/filemap.hpp> #include <nall/interpolation.hpp> -#include <nall/png.hpp> #include <nall/stdint.hpp> - +#include <nall/decode/png.hpp> #include <nall/image/base.hpp> #include <nall/image/static.hpp> #include <nall/image/core.hpp> diff --git a/nall/image/base.hpp b/nall/image/base.hpp index 5697ec8d..a530671a 100644 --- a/nall/image/base.hpp +++ b/nall/image/base.hpp @@ -47,6 +47,7 @@ struct image { static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth); //core.hpp + inline explicit operator bool() const; inline bool operator==(const image& source); inline bool operator!=(const image& source); @@ -56,6 +57,7 @@ struct image { inline image(image&& source); inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); inline image(const string& filename); + inline image(const vector<uint8_t>& buffer); inline image(const uint8_t* data, unsigned size); inline image(); inline ~image(); diff --git a/nall/image/core.hpp b/nall/image/core.hpp index 5ee04042..c0f0a63c 100644 --- a/nall/image/core.hpp +++ b/nall/image/core.hpp @@ -3,6 +3,10 @@ namespace nall { +image::operator bool() const { + return !empty(); +} + bool image::operator==(const image& source) { if(width != source.width) return false; if(height != source.height) return false; @@ -88,6 +92,10 @@ image::image(const string& filename) { load(filename); } +image::image(const vector<uint8_t>& buffer) { + loadPNG(buffer.data(), buffer.size()); +} + image::image(const uint8_t* data, unsigned size) { loadPNG(data, size); } diff --git a/nall/image/load.hpp b/nall/image/load.hpp index 6ac17d80..9c5b6f4e 100644 --- a/nall/image/load.hpp +++ b/nall/image/load.hpp @@ -35,7 +35,7 @@ bool image::loadPNG(const string& filename) { } bool image::loadPNG(const uint8_t* pngData, unsigned pngSize) { - png source; + Decode::PNG source; if(source.decode(pngData, pngSize) == false) return false; allocate(source.info.width, source.info.height); diff --git a/nall/intrinsics.hpp b/nall/intrinsics.hpp index da41094b..eadf33e5 100644 --- a/nall/intrinsics.hpp +++ b/nall/intrinsics.hpp @@ -15,16 +15,22 @@ struct Intrinsics { static inline Endian endian(); }; +} + /* Compiler detection */ +namespace nall { + #if defined(__clang__) #define COMPILER_CLANG Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Clang; } + #pragma clang diagnostic ignored "-Wunknown-pragmas" #pragma clang diagnostic ignored "-Wempty-body" #pragma clang diagnostic ignored "-Wparentheses" #pragma clang diagnostic ignored "-Wreturn-type" #pragma clang diagnostic ignored "-Wswitch" + #pragma clang diagnostic ignored "-Wswitch-bool" #pragma clang diagnostic ignored "-Wtautological-compare" #elif defined(__GNUC__) #define COMPILER_GCC @@ -40,8 +46,12 @@ struct Intrinsics { Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Unknown; } #endif +} + /* Platform detection */ +namespace nall { + #if defined(_WIN32) #define PLATFORM_WINDOWS Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Windows; } @@ -62,6 +72,8 @@ struct Intrinsics { Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Unknown; } #endif +} + /* Architecture Detection */ #if defined(PLATFORM_MACOSX) @@ -72,6 +84,8 @@ struct Intrinsics { #include <sys/endian.h> #endif +namespace nall { + #if defined(__i386__) || defined(_M_IX86) #define ARCH_X86 Intrinsics::Architecture Intrinsics::architecture() { return Intrinsics::Architecture::x86; } @@ -84,8 +98,12 @@ struct Intrinsics { Intrinsics::Architecture Intrinsics::architecture() { return Intrinsics::Architecture::Unknown; } #endif +} + /* Endian detection */ +namespace nall { + #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) #define ENDIAN_LSB Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::LSB; } diff --git a/nall/invoke.hpp b/nall/invoke.hpp index 078f7f5b..a697fbe8 100644 --- a/nall/invoke.hpp +++ b/nall/invoke.hpp @@ -36,7 +36,7 @@ template<typename... Args> inline void invoke(const string& name, Args&&... args const char** argp = argv; lstring argl(std::forward<Args>(args)...); *argp++ = (const char*)name; - for(auto &arg : argl) *argp++ = (const char*)arg; + for(auto& arg : argl) *argp++ = (const char*)arg; *argp++ = nullptr; if(execvp(name, (char* const*)argv) < 0) { diff --git a/nall/main.hpp b/nall/main.hpp new file mode 100644 index 00000000..98a433ab --- /dev/null +++ b/nall/main.hpp @@ -0,0 +1,29 @@ +#ifndef NALL_MAIN_HPP +#define NALL_MAIN_HPP + +#include <nall/platform.hpp> +#include <nall/string.hpp> + +namespace nall { + auto main(lstring arguments) -> void; + + auto main(int argc, char** argv) -> int { + #if defined(PLATFORM_WINDOWS) + CoInitialize(0); + WSAData wsaData = {0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); + utf8_args(argc, argv); + #endif + + lstring arguments; + for(auto n : range(argc)) arguments.append(argv[n]); + + return main(move(arguments)), EXIT_SUCCESS; + } +} + +auto main(int argc, char** argv) -> int { + return nall::main(argc, argv); +} + +#endif diff --git a/nall/maybe.hpp b/nall/maybe.hpp index 4f806dac..425f98e0 100644 --- a/nall/maybe.hpp +++ b/nall/maybe.hpp @@ -6,7 +6,7 @@ namespace nall { struct nothing_t {}; static nothing_t nothing; -template<typename T> +template<typename T, typename = void> class maybe { T* value = nullptr; @@ -15,28 +15,32 @@ public: maybe(nothing_t) {} maybe(const T& source) { operator=(source); } maybe(const maybe& source) { operator=(source); } - maybe(maybe&& source) { operator=(std::move(source)); } + maybe(maybe&& source) { operator=(move(source)); } ~maybe() { reset(); } - maybe& operator=(nothing_t) { reset(); return *this; } - maybe& operator=(const T& source) { reset(); value = new T(source); return *this; } - maybe& operator=(const maybe& source) { reset(); if(source) value = new T(source()); return *this; } - maybe& operator=(maybe&& source) { reset(); value = source.value; source.value = nullptr; return *this; } + auto operator=(nothing_t) -> maybe& { reset(); return *this; } + auto operator=(const T& source) -> maybe& { reset(); value = new T(source); return *this; } + auto operator=(const maybe& source) -> maybe& { reset(); if(source) value = new T(source()); return *this; } + auto operator=(maybe&& source) -> maybe& { reset(); value = source.value; source.value = nullptr; return *this; } - bool operator==(const maybe& source) const { + auto operator==(const maybe& source) const -> bool { if(value && source.value) return *value == *source.value; return !value && !source.value; } - bool operator!=(const maybe& source) const { return !operator==(source); } + auto operator!=(const maybe& source) const -> bool { return !operator==(source); } explicit operator bool() const { return value; } - T& operator()() { assert(value); return *value; } - const T& operator()() const { assert(value); return *value; } - const T& operator()(const T& invalid) const { if(value) return *value; return invalid; } + auto operator->() -> T* { assert(value); return value; } + auto operator->() const -> T* { assert(value); return value; } + auto operator*() -> T& { assert(value); return *value; } + auto operator*() const -> T& { assert(value); return *value; } + auto operator()() -> T& { assert(value); return *value; } + auto operator()() const -> T& { assert(value); return *value; } + auto operator()(const T& invalid) const -> T& { if(value) return *value; return invalid; } - bool empty() const { return value == nullptr; } - void reset() { if(value) { delete value; value = nullptr; } } - void swap(maybe& source) { std::swap(value, source.value); } + auto empty() const -> bool { return value == nullptr; } + auto reset() -> void { if(value) { delete value; value = nullptr; } } + auto swap(maybe& source) -> void { std::swap(value, source.value); } }; template<typename T> @@ -48,27 +52,64 @@ public: maybe(nothing_t) {} maybe(const T& source) { operator=(source); } maybe(const maybe& source) { operator=(source); } - maybe(maybe&& source) { operator=(std::move(source)); } + maybe(maybe&& source) { operator=(move(source)); } - maybe& operator=(nothing_t) { value = nullptr; return *this; } - maybe& operator=(const T& source) { value = (T*)&source; return *this; } - maybe& operator=(const maybe& source) { value = source.value; return *this; } - maybe& operator=(maybe&& source) { value = source.value; source.value = nullptr; return *this; } + auto operator=(nothing_t) -> maybe& { value = nullptr; return *this; } + auto operator=(const T& source) -> maybe& { value = (T*)&source; return *this; } + auto operator=(const maybe& source) -> maybe& { value = source.value; return *this; } + auto operator=(maybe&& source) -> maybe& { value = source.value; source.value = nullptr; return *this; } - bool operator==(const maybe& source) const { + auto operator==(const maybe& source) const -> bool { if(value && source.value) return *value == *source.value; return !value && !source.value; } - bool operator!=(const maybe& source) const { return !operator==(source); } + auto operator!=(const maybe& source) const -> bool { return !operator==(source); } explicit operator bool() const { return value; } - T& operator()() { assert(value); return *value; } - const T& operator()() const { assert(value); return *value; } - const T& operator()(const T& invalid) const { if(value) return *value; return invalid; } + auto operator->() -> T* { assert(value); return value; } + auto operator->() const -> T* { assert(value); return *value; } + auto operator*() -> T& { assert(value); return *value; } + auto operator*() const -> T& { assert(value); return *value; } + auto operator()() -> T& { assert(value); return *value; } + auto operator()() const -> T& { assert(value); return *value; } + auto operator()(const T& invalid) const -> T& { if(value) return *value; return invalid; } - bool empty() const { return value == nullptr; } - void reset() { value = nullptr; } - void swap(maybe& source) { std::swap(value, source.value); } + auto empty() const -> bool { return value == nullptr; } + auto reset() -> void { value = nullptr; } + auto swap(maybe& source) -> void { std::swap(value, source.value); } +}; + +template<typename T> +class maybe<T, enable_if<is_integral<T>>> { + T value = 0; + bool valid = false; + +public: + maybe() {} + maybe(nothing_t) {} + maybe(const T& source) { operator=(source); } + maybe(const maybe& source) { operator=(source); } + maybe(maybe&& source) { operator=(move(source)); } + + auto operator=(nothing_t) -> maybe& { valid = false; return *this; } + auto operator=(const T& source) -> maybe& { valid = true; value = source; return *this; } + auto operator=(const maybe& source) -> maybe& { valid = source.valid; value = source.value; return *this; } + auto operator=(maybe&& source) -> maybe& { valid = source.valid; value = source.value; source.valid = false; return *this; } + + auto operator==(const maybe& source) const -> bool { + if(valid && source.valid) return value == source.value; + return !valid && !source.valid; + } + auto operator!=(const maybe& source) const -> bool { return !operator==(source); } + + explicit operator bool() const { return valid; } + auto operator*() const -> T { assert(valid); return value; } + auto operator()() const -> T { assert(valid); return value; } + auto operator()(const T& invalid) const -> T { if(valid) return value; return invalid; } + + auto empty() const -> bool { return !valid; } + auto reset() -> void { valid = false; } + auto swap(maybe& source) -> void { std::swap(valid, source.valid); std::swap(value, source.value); } }; } diff --git a/nall/memory.hpp b/nall/memory.hpp new file mode 100644 index 00000000..17dc6180 --- /dev/null +++ b/nall/memory.hpp @@ -0,0 +1,8 @@ +#ifndef NALL_MEMORY_HPP +#define NALL_MEMORY_HPP + +#define NALL_MEMORY_INTERNAL_HPP +#include <nall/memory/memory.hpp> +#undef NALL_MEMORY_INTERNAL_HPP + +#endif diff --git a/nall/memory/memory.hpp b/nall/memory/memory.hpp new file mode 100644 index 00000000..3df31894 --- /dev/null +++ b/nall/memory/memory.hpp @@ -0,0 +1,131 @@ +#ifdef NALL_MEMORY_INTERNAL_HPP + +#include <nall/algorithm.hpp> + +namespace nall { + +namespace memory { + inline auto allocate(unsigned size) -> void*; + inline auto allocate(unsigned size, uint8_t data) -> void*; + + inline auto resize(void* target, unsigned size) -> void*; + + inline auto free(void* target) -> void; + + inline auto compare(const void* target, unsigned capacity, const void* source, unsigned size) -> signed; + inline auto compare(const void* target, const void* source, unsigned size) -> signed; + + inline auto icompare(const void* target, unsigned capacity, const void* source, unsigned size) -> signed; + inline auto icompare(const void* target, const void* source, unsigned size) -> signed; + + inline auto copy(void* target, unsigned capacity, const void* source, unsigned size) -> void*; + inline auto copy(void* target, const void* source, unsigned size) -> void*; + + inline auto move(void* target, unsigned capacity, const void* source, unsigned size) -> void*; + inline auto move(void* target, const void* source, unsigned size) -> void*; + + inline auto fill(void* target, unsigned capacity, uint8_t data = 0x00) -> void*; +} + +} + +#include <nall/memory/pool.hpp> + +namespace nall { + +//implementation notes: +//memcmp, memcpy, memmove have terrible performance on small block sizes (FreeBSD 10.0-amd64) +//as this library is used extensively by nall/string, and most strings tend to be small, +//this library hand-codes these functions instead. surprisingly, it's a substantial speedup + +auto memory::allocate(unsigned size) -> void* { + return malloc(size); +} + +auto memory::allocate(unsigned size, uint8_t data) -> void* { + auto result = malloc(size); + if(result) fill(result, size, data); + return result; +} + +auto memory::resize(void* target, unsigned size) -> void* { + return realloc(target, size); +} + +auto memory::free(void* target) -> void { + ::free(target); +} + +auto memory::compare(const void* target, unsigned capacity, const void* source, unsigned size) -> signed { + auto t = (int8_t*)target; + auto s = (int8_t*)source; + auto l = min(capacity, size); + while(l--) { + auto x = *t++; + auto y = *s++; + if(x != y) return x - y; + } + return 0; +} + +auto memory::compare(const void* target, const void* source, unsigned size) -> signed { + return compare(target, size, source, size); +} + +auto memory::icompare(const void* target, unsigned capacity, const void* source, unsigned size) -> signed { + auto t = (int8_t*)target; + auto s = (int8_t*)source; + auto l = min(capacity, size); + while(l--) { + auto x = *t++; + auto y = *s++; + if(x - 'A' < 26) x += 32; + if(y - 'A' < 26) y += 32; + if(x != y) return x - y; + } + return 0; +} + +auto memory::icompare(const void* target, const void* source, unsigned size) -> signed { + return icompare(target, size, source, size); +} + +auto memory::copy(void* target, unsigned capacity, const void* source, unsigned size) -> void* { + auto t = (uint8_t*)target; + auto s = (uint8_t*)source; + auto l = min(capacity, size); + while(l--) *t++ = *s++; + return target; +} + +auto memory::copy(void* target, const void* source, unsigned size) -> void* { + return copy(target, size, source, size); +} + +auto memory::move(void* target, unsigned capacity, const void* source, unsigned size) -> void* { + auto t = (uint8_t*)target; + auto s = (uint8_t*)source; + auto l = min(capacity, size); + if(t < s) { + while(l--) *t++ = *s++; + } else { + t += l; + s += l; + while(l--) *--t = *--s; + } + return target; +} + +auto memory::move(void* target, const void* source, unsigned size) -> void* { + return move(target, size, source, size); +} + +auto memory::fill(void* target, unsigned capacity, uint8_t data) -> void* { + auto t = (uint8_t*)target; + while(capacity--) *t++ = data; + return target; +} + +} + +#endif diff --git a/nall/memory/pool.hpp b/nall/memory/pool.hpp new file mode 100644 index 00000000..8d162886 --- /dev/null +++ b/nall/memory/pool.hpp @@ -0,0 +1,64 @@ +#ifdef NALL_MEMORY_INTERNAL_HPP + +namespace nall { +namespace memory { + +template<unsigned Capacity, unsigned Size> +struct pool_spsc { + signed* list = nullptr; + uint8_t* data = nullptr; + unsigned slot = 0; + + pool_spsc() { + list = (signed*)memory::allocate(Capacity * sizeof(signed)); + data = (uint8_t*)memory::allocate(Capacity * Size); + for(unsigned n = 0; n < Capacity; n++) list[n] = n; + } + + ~pool_spsc() { + memory::free(list); + memory::free(data); + } + + auto allocate(unsigned size) -> void* { + if(size == 0) return nullptr; + if(size > Size) return memory::allocate(size); + signed offset = list[slot]; + if(offset < 0) return memory::allocate(size); + list[slot] = -1; + slot = (slot + 1) % Capacity; + return (void*)(data + offset * Size); + } + + auto allocate(unsigned size, uint8_t data) -> void* { + auto result = allocate(size); + memset(result, data, size); + return result; + } + + auto resize(void* target, unsigned size) -> void* { + if(target == nullptr) return allocate(size); + signed offset = ((uint8_t*)target - data) / Size; + if(offset < 0 || offset >= Capacity) return memory::resize(target, size); + if(size <= Size) return target; + slot = (slot - 1) % Capacity; + list[slot] = offset; + return memory::allocate(size); + } + + auto free(void* target) -> void { + if(target == nullptr) return; + signed offset = ((uint8_t*)target - data) / Size; + if(offset < 0 || offset >= Capacity) return memory::free(target); + slot = (slot - 1) % Capacity; + list[slot] = offset; + } + + pool_spsc(const pool_spsc&) = delete; + pool_spsc& operator=(const pool_spsc&) = delete; +}; + +} +} + +#endif diff --git a/nall/method.hpp b/nall/method.hpp new file mode 100644 index 00000000..c79eab0a --- /dev/null +++ b/nall/method.hpp @@ -0,0 +1,59 @@ +#ifndef NALL_METHOD_HPP +#define NALL_METHOD_HPP + +//provides extension-method and chaining-method support to classes +//extension: class(function, params...); +//chaining: class[function](params...)[function](params...); + +//usage: +//struct object : method<object> { +// using method::operator[]; //if object::operator[] defined +// using method::operator(); //if object::operator() defined +//}; + +//note: extension-methods would be obsolete if C++17 introduces unified function call syntax +//currently proposed as N4165 and N4174 + +namespace nall { + +template<typename T> struct method { + template<typename F> struct chain { + chain(T& self, const F& f) : self(self), f(f) {} + template<typename... P> auto operator()(P&&... p) -> T& { + return f(self, std::forward<P>(p)...), self; + } + private: + T& self; + const F& f; + }; + + template<typename F> struct const_chain { + const_chain(const T& self, const F& f) : self(self), f(f) {} + template<typename... P> auto operator()(P&&... p) const -> const T& { + return f(self, std::forward<P>(p)...), self; + } + private: + const T& self; + const F& f; + }; + + template<typename F, typename = enable_if<is_function<F>>> + auto operator[](const F& f) -> chain<F> { return chain<F>((T&)*this, f); } + + template<typename F, typename = enable_if<is_function<F>>> + auto operator[](const F& f) const -> const_chain<F> { return const_chain<F>((const T&)*this, f); } + + template<typename F, typename... P, typename = enable_if<is_function<F>>> + auto operator()(const F& f, P&&... p) -> decltype(f((T&)*this, std::forward<P>(p)...)) { + return f((T&)*this, std::forward<P>(p)...); + } + + template<typename F, typename... P, typename = enable_if<is_function<F>>> + auto operator()(const F& f, P&&... p) const -> decltype(f((const T&)*this, std::forward<P>(p)...)) { + return f((const T&)*this, std::forward<P>(p)...); + } +}; + +} + +#endif diff --git a/nall/mosaic/context.hpp b/nall/mosaic/context.hpp index ee6b5d53..97719ffa 100644 --- a/nall/mosaic/context.hpp +++ b/nall/mosaic/context.hpp @@ -62,12 +62,11 @@ struct context { lstring list = expression.split(","); for(auto& item : list) { - item.trim(); + item.strip(); if(item.match("f(?*) ?*")) { - item.ltrim<1>("f("); + item.ltrim("f("); lstring part = item.split<1>(") "); - lstring args = part[0].split<3>(";"); - for(auto &item : args) item.trim(); + lstring args = part[0].split<3>(";").strip(); unsigned length = eval(args(0, "0")); unsigned offset = eval(args(1, "0")); @@ -86,14 +85,14 @@ struct context { } } else if(item.match("base64*")) { unsigned offset = 0; - item.ltrim<1>("base64"); + item.ltrim("base64"); if(item.match("(?*) *")) { - item.ltrim<1>("("); + item.ltrim("("); lstring part = item.split<1>(") "); offset = eval(part[0]); item = part(1, ""); } - item.trim(); + item.strip(); for(auto& c : item) { if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0); if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26); @@ -102,8 +101,8 @@ struct context { if(c == '_') buffer.append(offset + 63); } } else if(item.match("file *")) { - item.ltrim<1>("file "); - item.trim(); + item.ltrim("file "); + item.strip(); //... } else if(item.empty() == false) { buffer.append(eval(item)); @@ -116,10 +115,8 @@ struct context { lstring lines = data.split("\n"); for(auto& line : lines) { - lstring part = line.split<1>(":"); + lstring part = line.split<1>(":").strip(); if(part.size() != 2) continue; - part[0].trim(); - part[1].trim(); if(part[0] == "offset") offset = eval(part[1]); if(part[0] == "width") width = eval(part[1]); diff --git a/nall/nall.hpp b/nall/nall.hpp index 3898aa67..6e4264c4 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -1,3 +1,11 @@ +/* nall + * author: byuu + * license: ISC + * + * nall is a header library that provides both fundamental and useful classes + * its goals are portability, consistency, minimalism and reusability + */ + #ifndef NALL_HPP #define NALL_HPP @@ -14,8 +22,6 @@ #include <nall/bitvector.hpp> #include <nall/bmp.hpp> #include <nall/config.hpp> -#include <nall/crc16.hpp> -#include <nall/crc32.hpp> #include <nall/directory.hpp> #include <nall/dl.hpp> #include <nall/endian.hpp> @@ -23,35 +29,41 @@ #include <nall/filemap.hpp> #include <nall/function.hpp> #include <nall/group.hpp> -#include <nall/gzip.hpp> #include <nall/hashset.hpp> #include <nall/hid.hpp> -#include <nall/http.hpp> #include <nall/image.hpp> -#include <nall/inflate.hpp> #include <nall/interpolation.hpp> #include <nall/intrinsics.hpp> #include <nall/invoke.hpp> #include <nall/map.hpp> #include <nall/matrix.hpp> #include <nall/maybe.hpp> -#include <nall/png.hpp> +#include <nall/memory.hpp> #include <nall/property.hpp> #include <nall/random.hpp> +#include <nall/range.hpp> #include <nall/serializer.hpp> #include <nall/set.hpp> -#include <nall/sha256.hpp> +#include <nall/shared-pointer.hpp> #include <nall/sort.hpp> #include <nall/stdint.hpp> +#include <nall/storage.hpp> #include <nall/stream.hpp> #include <nall/string.hpp> #include <nall/thread.hpp> #include <nall/traits.hpp> -#include <nall/unzip.hpp> #include <nall/utility.hpp> #include <nall/varint.hpp> #include <nall/vector.hpp> #include <nall/zip.hpp> +#include <nall/decode/bmp.hpp> +#include <nall/decode/gzip.hpp> +#include <nall/decode/inflate.hpp> +#include <nall/decode/png.hpp> +#include <nall/decode/zip.hpp> +#include <nall/hash/crc16.hpp> +#include <nall/hash/crc32.hpp> +#include <nall/hash/sha256.hpp> #if defined(PLATFORM_WINDOWS) #include <nall/windows/registry.hpp> diff --git a/nall/platform.hpp b/nall/platform.hpp index d6d85da8..2cc2c0c0 100644 --- a/nall/platform.hpp +++ b/nall/platform.hpp @@ -9,13 +9,17 @@ namespace Math { } #if defined(PLATFORM_WINDOWS) - //minimum version needed for _wstat64, etc + //minimum version needed for _wstat64, AI_ADDRCONFIG, etc + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0601 #undef __MSVCRT_VERSION__ - #define __MSVCRT_VERSION__ 0x0601 + #define __MSVCRT_VERSION__ _WIN32_WINNT #include <nall/windows/utf8.hpp> #endif +#include <atomic> #include <limits> +#include <mutex> #include <utility> #include <assert.h> @@ -27,6 +31,7 @@ namespace Math { #include <stdlib.h> #include <string.h> #include <time.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> @@ -36,13 +41,16 @@ namespace Math { #include <direct.h> #include <shlobj.h> #include <wchar.h> - #undef interface - #define dllexport __declspec(dllexport) + #include <winsock2.h> + #include <ws2tcpip.h> #else #include <dlfcn.h> #include <unistd.h> #include <pwd.h> - #define dllexport + #include <grp.h> + #include <sys/socket.h> + #include <netinet/in.h> + #include <netdb.h> #endif #if defined(COMPILER_CL) @@ -50,26 +58,35 @@ namespace Math { #endif #if defined(PLATFORM_WINDOWS) - __declspec(dllimport) int _fileno(FILE*); + #undef interface + #define dllexport __declspec(dllexport) + #define MSG_NOSIGNAL 0 + __declspec(dllimport) auto _fileno(FILE*) -> int; - inline int access(const char* path, int amode) { return _waccess(nall::utf16_t(path), amode); } - inline int fileno(FILE* stream) { return _fileno(stream); } - inline char* getcwd(char* buf, size_t size) { wchar_t wpath[PATH_MAX] = L""; if(!_wgetcwd(wpath, size)) return nullptr; strcpy(buf, nall::utf8_t(wpath)); return buf; } - inline int putenv(char* string) { return _wputenv(nall::utf16_t(string)); } - inline char* realpath(const char* file_name, char* resolved_name) { wchar_t wfile_name[PATH_MAX] = L""; if(!_wfullpath(wfile_name, nall::utf16_t(file_name), PATH_MAX)) return nullptr; strcpy(resolved_name, nall::utf8_t(wfile_name)); return resolved_name; } - inline int rename(const char* oldname, const char* newname) { return _wrename(nall::utf16_t(oldname), nall::utf16_t(newname)); } - inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); } + inline auto access(const char* path, int amode) -> int { return _waccess(nall::utf16_t(path), amode); } + inline auto fileno(FILE* stream) -> int { return _fileno(stream); } + inline auto getcwd(char* buf, size_t size) -> char* { wchar_t wpath[PATH_MAX] = L""; if(!_wgetcwd(wpath, size)) return nullptr; strcpy(buf, nall::utf8_t(wpath)); return buf; } + inline auto mkdir(const char* path, int mode) -> int { return _wmkdir(nall::utf16_t(path)); } + inline auto putenv(const char* value) -> int { return _wputenv(nall::utf16_t(value)); } + inline auto realpath(const char* file_name, char* resolved_name) -> char* { wchar_t wfile_name[PATH_MAX] = L""; if(!_wfullpath(wfile_name, nall::utf16_t(file_name), PATH_MAX)) return nullptr; strcpy(resolved_name, nall::utf8_t(wfile_name)); return resolved_name; } + inline auto rename(const char* oldname, const char* newname) -> int { return _wrename(nall::utf16_t(oldname), nall::utf16_t(newname)); } + inline auto usleep(unsigned milliseconds) -> void { Sleep(milliseconds / 1000); } +#else + #define dllexport #endif #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) #define neverinline __attribute__((noinline)) #define alwaysinline inline __attribute__((always_inline)) + #define deprecated __attribute__((deprecated)) #elif defined(COMPILER_CL) #define neverinline __declspec(noinline) #define alwaysinline inline __forceinline + #define deprecated __declspec(deprecated) #else #define neverinline #define alwaysinline inline + #define deprecated #endif #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) @@ -78,4 +95,12 @@ namespace Math { #define unreachable throw #endif +#if defined(COMPILER_GCC) && __GNUC__ == 4 && __GNUC_MINOR__ <= 7 + //GCC 4.7.x has a bug (#54849) when specifying override with a trailing return type: + //auto function() -> return_type override; //this is the syntax that the C++11 standard requires + //auto function() override -> return_type; //this is the syntax that GCC 4.7.x requires + //in order to compile code correctly with both compilers, we disable the override keyword for GCC + #define override +#endif + #endif diff --git a/nall/range.hpp b/nall/range.hpp new file mode 100644 index 00000000..54efbb25 --- /dev/null +++ b/nall/range.hpp @@ -0,0 +1,48 @@ +#ifndef NALL_RANGE_HPP +#define NALL_RANGE_HPP + +namespace nall { + +struct range_t { + struct iterator { + signed operator*() const { return position; } + bool operator!=(const iterator& source) const { return step > 0 ? position < source.position : position > source.position; } + iterator& operator++() { position += step; return *this; } + iterator(signed position, signed step = 0) : position(position), step(step) {} + + private: + signed position; + const signed step; + }; + + const iterator begin() const { return iterator(origin, stride); } + const iterator end() const { return iterator(target); } + + signed origin; + signed target; + signed stride; +}; + +inline range_t range(signed size) { + return range_t{0, size, 1}; +} + +inline range_t range(signed offset, signed size) { + return range_t{offset, size, 1}; +} + +inline range_t range(signed offset, signed size, signed step) { + return range_t{offset, size, step}; +} + +inline range_t range_reverse(signed size) { + return range_t{size - 1, -1, -1}; +} + +template<typename T> inline range_t range(const vector<T>& container) { + return range_t{0, (signed)container.size(), 1}; +} + +} + +#endif diff --git a/nall/service.hpp b/nall/service.hpp new file mode 100644 index 00000000..19b9f072 --- /dev/null +++ b/nall/service.hpp @@ -0,0 +1,120 @@ +#ifndef NALL_SERVICE_HPP +#define NALL_SERVICE_HPP + +//service model template built on top of shared-memory + +#include <signal.h> +#include <nall/shared-memory.hpp> + +namespace nall { + +struct service { + inline explicit operator bool() const; + inline auto command(const string& name, const string& command) -> bool; + inline auto receive() -> string; + inline auto name() const -> string; + inline auto stop() const -> bool; + +private: + shared_memory shared; + string _name; + bool _stop = false; +}; + +service::operator bool() const { + return (bool)shared; +} + +//returns true on new service process creation (false is not necessarily an error) +auto service::command(const string& name, const string& command) -> bool { + if(!name) return false; + if(!command) return print("[{0}] usage: {service} command\n" + "commands:\n" + " status : query whether service is running\n" + " start : start service if it is not running\n" + " stop : stop service if it is running\n" + " remove : remove semaphore lock if service crashed\n" + " {value} : send custom command to service\n" + "", format{name}), false; + + if(shared.open(name, 4096)) { + if(command == "start") { + print("[{0}] already started\n", format{name}); + } else if(command == "status") { + print("[{0}] running\n", format{name}); + } + if(auto data = shared.acquire()) { + if(command == "stop") print("[{0}] stopped\n", format{name}); + memory::copy(data, command.data(), min(command.size(), 4096)); + shared.release(); + } + if(command == "remove") { + shared.remove(); + print("[{0}] removed\n", format{name}); + } + return false; + } + + if(command == "start") { + if(shared.create(name, 4096)) { + print("[{0}] started\n", format{name}); + auto pid = fork(); + if(pid == 0) { + signal(SIGHUP, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + _name = name; + return true; + } + shared.close(); + } else { + print("[{0}] start failed ({1})\n", format{name, strerror(errno)}); + } + return false; + } + + if(command == "status") { + print("[{0}] stopped\n", format{name}); + return false; + } + + return false; +} + +auto service::receive() -> string { + string command; + if(shared) { + if(auto data = shared.acquire()) { + if(*data) { + command.resize(4095); + memory::copy(command.pointer(), data, 4095); + memory::fill(data, 4096); + } + shared.release(); + if(command == "remove") { + _stop = true; + return ""; + } else if(command == "start") { + return ""; + } else if(command == "status") { + return ""; + } else if(command == "stop") { + _stop = true; + shared.remove(); + return ""; + } + } + } + return command; +} + +auto service::name() const -> string { + return _name; +} + +auto service::stop() const -> bool { + return _stop; +} + +} + +#endif diff --git a/nall/sha256.hpp b/nall/sha256.hpp deleted file mode 100644 index 2be2d7b2..00000000 --- a/nall/sha256.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -#include <nall/stdint.hpp> - -namespace nall { - -#define PTR(t, a) ((t*)(a)) - -#define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ -)) - -#define ST32(a, d) *PTR(uint32_t, a) = (d) -#define ST32BE(a, d) ST32(a, SWAP32(d)) - -#define LD32(a) *PTR(uint32_t, a) -#define LD32BE(a) SWAP32(LD32(a)) - -#define LSL32(x, n) ((uint32_t)(x) << (n)) -#define LSR32(x, n) ((uint32_t)(x) >> (n)) -#define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - -//first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 -static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -}; - -//first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 -static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -}; - -struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; -}; - -inline void sha256_init(sha256_ctx* p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); -} - -static void sha256_block(sha256_ctx* p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; -} - -inline void sha256_chunk(sha256_ctx* p, const uint8_t* s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } -} - -inline void sha256_final(sha256_ctx* p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); -} - -inline void sha256_hash(sha256_ctx* p, uint8_t* s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); -} - -#undef PTR -#undef SWAP32 -#undef ST32 -#undef ST32BE -#undef LD32 -#undef LD32BE -#undef LSL32 -#undef LSR32 -#undef ROR32 - -} - -#endif diff --git a/nall/shared-memory.hpp b/nall/shared-memory.hpp new file mode 100644 index 00000000..ad237613 --- /dev/null +++ b/nall/shared-memory.hpp @@ -0,0 +1,157 @@ +#ifndef NALL_SHARED_MEMORY_HPP +#define NALL_SHARED_MEMORY_HPP + +#include <nall/memory.hpp> +#include <nall/string.hpp> + +#include <semaphore.h> +#include <sys/mman.h> + +namespace nall { + +struct shared_memory { + shared_memory() = default; + shared_memory(const shared_memory&) = delete; + shared_memory& operator=(const shared_memory&) = delete; + + ~shared_memory() { + reset(); + } + + explicit operator bool() const { + return _mode != mode::inactive; + } + + auto empty() const -> bool { + return _mode == mode::inactive; + } + + auto size() const -> unsigned { + return _size; + } + + auto acquired() const -> bool { + return _acquired; + } + + auto acquire() -> uint8_t* { + if(!acquired()) { + sem_wait(_semaphore); + _acquired = true; + } + return _data; + } + + auto release() -> void { + if(acquired()) { + sem_post(_semaphore); + _acquired = false; + } + } + + auto reset() -> void { + release(); + if(_mode == mode::server) return remove(); + if(_mode == mode::client) return close(); + } + + auto create(const string& name, unsigned size) -> bool { + reset(); + + _name = {"/nall::", string{name}.transform("/", ":")}; + _size = size; + + //O_CREAT | O_EXCL seems to throw ENOENT even when semaphore does not exist ... + _semaphore = sem_open(_name, O_CREAT, 0644, 1); + if(_semaphore == SEM_FAILED) return remove(), false; + + _descriptor = shm_open(_name, O_CREAT | O_TRUNC | O_RDWR, 0644); + if(_descriptor < 0) return remove(), false; + + if(ftruncate(_descriptor, _size) != 0) return remove(), false; + + _data = (uint8_t*)mmap(nullptr, _size, PROT_READ | PROT_WRITE, MAP_SHARED, _descriptor, 0); + if(_data == MAP_FAILED) return remove(), false; + + memory::fill(_data, _size); + + _mode = mode::server; + return true; + } + + auto remove() -> void { + if(_data) { + munmap(_data, _size); + _data = nullptr; + } + + if(_descriptor) { + ::close(_descriptor); + shm_unlink(_name); + _descriptor = -1; + } + + if(_semaphore) { + sem_close(_semaphore); + sem_unlink(_name); + _semaphore = nullptr; + } + + _mode = mode::inactive; + _name = ""; + _size = 0; + } + + auto open(const string& name, unsigned size) -> bool { + reset(); + + _name = {"/nall::", string{name}.transform("/", ":")}; + _size = size; + + _semaphore = sem_open(_name, 0, 0644); + if(_semaphore == SEM_FAILED) return close(), false; + + _descriptor = shm_open(_name, O_RDWR, 0644); + if(_descriptor < 0) return close(), false; + + _data = (uint8_t*)mmap(nullptr, _size, PROT_READ | PROT_WRITE, MAP_SHARED, _descriptor, 0); + if(_data == MAP_FAILED) return close(), false; + + _mode = mode::client; + return true; + } + + auto close() -> void { + if(_data) { + munmap(_data, _size); + _data = nullptr; + } + + if(_descriptor) { + ::close(_descriptor); + _descriptor = -1; + } + + if(_semaphore) { + sem_close(_semaphore); + _semaphore = nullptr; + } + + _mode = mode::inactive; + _name = ""; + _size = 0; + } + +private: + enum class mode : unsigned { server, client, inactive } _mode = mode::inactive; + string _name; + sem_t* _semaphore = nullptr; + signed _descriptor = -1; + uint8_t* _data = nullptr; + unsigned _size = 0; + bool _acquired = false; +}; + +} + +#endif diff --git a/nall/shared-pointer.hpp b/nall/shared-pointer.hpp new file mode 100644 index 00000000..f3e6271a --- /dev/null +++ b/nall/shared-pointer.hpp @@ -0,0 +1,268 @@ +#ifndef NALL_SHARED_POINTER_HPP +#define NALL_SHARED_POINTER_HPP + +#include <nall/function.hpp> +#include <nall/maybe.hpp> +#include <nall/traits.hpp> +#include <nall/vector.hpp> + +namespace nall { + +template<typename T> struct shared_pointer; + +struct shared_pointer_manager { + void* pointer = nullptr; + function<void (void*)> deleter; + unsigned strong = 0; + unsigned weak = 0; + + shared_pointer_manager(void* pointer) : pointer(pointer) { + } +}; + +template<typename T> struct shared_pointer; +template<typename T> struct shared_pointer_weak; + +template<typename T> +struct shared_pointer { + using type = T; + shared_pointer_manager* manager = nullptr; + + template<typename U> + struct is_compatible { + static constexpr bool value = is_base_of<T, U>::value || is_base_of<U, T>::value; + }; + + shared_pointer() { + } + + shared_pointer(T* source) { + operator=(source); + } + + shared_pointer(T* source, const function<void (T*)>& deleter) { + operator=(source); + manager->deleter = [=](void* p) { deleter((T*)p); }; + } + + shared_pointer(const shared_pointer& source) { + operator=(source); + } + + shared_pointer(shared_pointer&& source) { + operator=(move(source)); + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer(const shared_pointer<U>& source) { + operator=<U>(source); + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer(shared_pointer<U>&& source) { + operator=<U>(move(source)); + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer(const shared_pointer_weak<U>& source) { + operator=<U>(source); + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer(const shared_pointer<U>& source, T* pointer) { + if((bool)source && (T*)source.manager->pointer == pointer) { + manager = source.manager; + manager->strong++; + } + } + + ~shared_pointer() { + reset(); + } + + shared_pointer& operator=(T* source) { + reset(); + if(source) { + manager = new shared_pointer_manager((void*)source); + manager->strong++; + } + return *this; + } + + shared_pointer& operator=(const shared_pointer& source) { + if(this != &source) { + reset(); + if((bool)source) { + manager = source.manager; + manager->strong++; + } + } + return *this; + } + + shared_pointer& operator=(shared_pointer&& source) { + if(this != &source) { + reset(); + manager = source.manager; + source.manager = nullptr; + } + return *this; + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer& operator=(const shared_pointer<U>& source) { + if((uintptr_t)this != (uintptr_t)&source) { + reset(); + if((bool)source) { + manager = source.manager; + manager->strong++; + } + } + return *this; + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer& operator=(shared_pointer&& source) { + if((uintptr_t)this != (uintptr_t)&source) { + reset(); + manager = source.manager; + source.manager = nullptr; + } + return *this; + } + + template<typename U, typename = enable_if<is_compatible<U>>> + shared_pointer& operator=(const shared_pointer_weak<U>& source) { + reset(); + if((bool)source) { + manager = source.manager; + manager->strong++; + } + return *this; + } + + T* data() { + if(manager) return (T*)manager->pointer; + return nullptr; + } + + const T* data() const { + if(manager) return (T*)manager->pointer; + return nullptr; + } + + T* operator->() { return data(); } + const T* operator->() const { return data(); } + + T& operator*() { return *data(); } + const T& operator*() const { return *data(); } + + T& operator()() { return *data(); } + const T& operator()() const { return *data(); } + + template<typename U> + bool operator==(const shared_pointer<U>& source) const { + return manager == source.manager; + } + + template<typename U> + bool operator!=(const shared_pointer<U>& source) const { + return manager != source.manager; + } + + explicit operator bool() const { + return !empty(); + } + + bool empty() const { + return !manager || !manager->strong; + } + + bool unique() const { + return manager && manager->strong == 1; + } + + void reset() { + if(manager && manager->strong) { + //pointer may contain weak references; if strong==0 it may destroy manager + //as such, we must destroy strong before decrementing it to zero + if(manager->strong == 1) { + if(manager->deleter) { + manager->deleter(manager->pointer); + } else { + delete (T*)manager->pointer; + } + manager->pointer = nullptr; + } + if(--manager->strong == 0) { + if(manager->weak == 0) { + delete manager; + } + } + } + manager = nullptr; + } + + template<typename U> + shared_pointer<U> cast() { + if(auto pointer = dynamic_cast<U*>(data())) { + return {*this, pointer}; + } + return {}; + } +}; + +template<typename T> +struct shared_pointer_weak { + using type = T; + shared_pointer_manager* manager = nullptr; + + shared_pointer_weak() { + } + + shared_pointer_weak(const shared_pointer<T>& source) { + operator=(source); + } + + shared_pointer_weak& operator=(const shared_pointer<T>& source) { + reset(); + if(manager = source.manager) manager->weak++; + return *this; + } + + ~shared_pointer_weak() { + reset(); + } + + explicit operator bool() const { + return !empty(); + } + + bool empty() const { + return !manager || !manager->strong; + } + + shared_pointer<T> acquire() const { + return shared_pointer<T>(*this); + } + + void reset() { + if(manager && --manager->weak == 0) { + if(manager->strong == 0) { + delete manager; + } + } + manager = nullptr; + } +}; + +template<typename T> +struct shared_pointer_new : shared_pointer<T> { + template<typename... P> + shared_pointer_new(P&&... p) : shared_pointer<T>(new T(forward<P>(p)...)) { + } +}; + +} + +#endif diff --git a/nall/smtp.hpp b/nall/smtp.hpp index ce1a02ad..54197e9a 100644 --- a/nall/smtp.hpp +++ b/nall/smtp.hpp @@ -273,7 +273,7 @@ string SMTP::contacts(const vector<Information::Contact>& contacts) { for(auto& contact : contacts) { result.append(this->contact(contact), "; "); } - result.rtrim<1>("; "); + result.rtrim("; "); return result; } diff --git a/nall/storage.hpp b/nall/storage.hpp new file mode 100644 index 00000000..3d9b7bb7 --- /dev/null +++ b/nall/storage.hpp @@ -0,0 +1,95 @@ +#ifndef NALL_STORAGE_HPP +#define NALL_STORAGE_HPP + +//generic abstraction layer for common storage operations against both files and directories +//these functions are not recursive; use directory::create() and directory::remove() for recursion + +#include <nall/platform.hpp> +#include <nall/string.hpp> + +namespace nall { + +struct storage { + enum class time : unsigned { access, modify }; + + static auto exists(const string& name) -> bool; + static auto readable(const string& name) -> bool; + static auto writable(const string& name) -> bool; + static auto executable(const string& name) -> bool; + static auto uid(const string& name) -> unsigned; + static auto gid(const string& name) -> unsigned; + static auto mode(const string& name) -> unsigned; + static auto timestamp(const string& name, storage::time mode = storage::time::modify) -> time_t; + + static auto create(const string& name, unsigned permissions = 0755) -> bool; + static auto rename(const string& name, const string& targetname) -> bool; + static auto remove(const string& name) -> bool; +}; + +inline auto storage::exists(const string& name) -> bool { + return access(name, F_OK) == 0; +} + +inline auto storage::readable(const string& name) -> bool { + return access(name, R_OK) == 0; +} + +inline auto storage::writable(const string& name) -> bool { + return access(name, W_OK) == 0; +} + +inline auto storage::executable(const string& name) -> bool { + return access(name, X_OK) == 0; +} + +inline auto storage::uid(const string& name) -> unsigned { + struct stat data = {0}; + stat(name, &data); + return data.st_uid; +} + +inline auto storage::gid(const string& name) -> unsigned { + struct stat data = {0}; + stat(name, &data); + return data.st_gid; +} + +inline auto storage::mode(const string& name) -> unsigned { + struct stat data = {0}; + stat(name, &data); + return data.st_mode; +} + +inline auto storage::timestamp(const string& name, storage::time mode) -> time_t { + struct stat data = {0}; + stat(name, &data); + switch(mode) { + case storage::time::access: return data.st_atime; + case storage::time::modify: return data.st_mtime; + } + throw; +} + +//returns true if 'name' already exists +inline auto storage::create(const string& name, unsigned permissions) -> bool { + if(storage::exists(name)) return true; + if(name.endsWith("/")) return mkdir(name, permissions) == 0; + int fd = open(name, O_CREAT | O_EXCL, permissions); + if(fd < 0) return false; + return close(fd), true; +} + +//returns false if 'name' and 'targetname' are on different file systems (requires copy) +inline auto storage::rename(const string& name, const string& targetname) -> bool { + return ::rename(name, targetname) == 0; +} + +//returns false if 'name' is a directory that is not empty +inline auto storage::remove(const string& name) -> bool { + if(name.endsWith("/")) return rmdir(name) == 0; + return unlink(name) == 0; +} + +} + +#endif diff --git a/nall/stream.hpp b/nall/stream.hpp index 586ccda7..b43ae41e 100644 --- a/nall/stream.hpp +++ b/nall/stream.hpp @@ -6,18 +6,16 @@ #include <nall/file.hpp> #include <nall/filemap.hpp> -#include <nall/gzip.hpp> -#include <nall/http.hpp> #include <nall/stdint.hpp> #include <nall/string.hpp> -#include <nall/zip.hpp> +#include <nall/decode/gzip.hpp> +#include <nall/decode/zip.hpp> #define NALL_STREAM_INTERNAL_HPP #include <nall/stream/stream.hpp> #include <nall/stream/memory.hpp> #include <nall/stream/mmap.hpp> #include <nall/stream/file.hpp> -#include <nall/stream/http.hpp> #include <nall/stream/gzip.hpp> #include <nall/stream/zip.hpp> #include <nall/stream/auto.hpp> diff --git a/nall/stream/auto.hpp b/nall/stream/auto.hpp index 0e4d8705..a410a975 100644 --- a/nall/stream/auto.hpp +++ b/nall/stream/auto.hpp @@ -6,7 +6,6 @@ namespace nall { #define autostream(...) (*makestream(__VA_ARGS__)) inline std::unique_ptr<stream> makestream(const string& path) { - if(path.ibeginsWith("http://")) return std::unique_ptr<stream>(new httpstream(path, 80)); if(path.iendsWith(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path})); if(path.iendsWith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path})); return std::unique_ptr<stream>(new mmapstream(path)); diff --git a/nall/stream/gzip.hpp b/nall/stream/gzip.hpp index 4af7a24d..9bccbebe 100644 --- a/nall/stream/gzip.hpp +++ b/nall/stream/gzip.hpp @@ -1,7 +1,7 @@ #ifndef NALL_STREAM_GZIP_HPP #define NALL_STREAM_GZIP_HPP -#include <nall/gzip.hpp> +#include <nall/decode/gzip.hpp> namespace nall { @@ -14,7 +14,7 @@ struct gzipstream : memorystream { uint8_t *data = new uint8_t[size]; stream.read(data, size); - gzip archive; + Decode::GZIP archive; bool result = archive.decompress(data, size); delete[] data; if(result == false) return; diff --git a/nall/stream/http.hpp b/nall/stream/http.hpp deleted file mode 100644 index fb38a770..00000000 --- a/nall/stream/http.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef NALL_STREAM_HTTP_HPP -#define NALL_STREAM_HTTP_HPP - -#include <nall/http.hpp> - -namespace nall { - -struct httpstream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return true; } - bool randomaccess() const { return true; } - - unsigned size() const { return psize; } - unsigned offset() const { return poffset; } - void seek(unsigned offset) const { poffset = offset; } - - uint8_t read() const { return pdata[poffset++]; } - void write(uint8_t data) const { pdata[poffset++] = data; } - - uint8_t read(unsigned offset) const { return pdata[offset]; } - void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - httpstream(const string& url, unsigned port) : pdata(nullptr), psize(0), poffset(0) { - string uri = url; - uri.ltrim<1>("http://"); - lstring part = uri.split<1>("/"); - part[1] = { "/", part[1] }; - - http connection; - if(connection.connect(part[0], port) == false) return; - connection.download(part[1], pdata, psize); - } - - ~httpstream() { - if(pdata) delete[] pdata; - } - -private: - mutable uint8_t* pdata; - mutable unsigned psize, poffset; -}; - -} - -#endif diff --git a/nall/stream/stream.hpp b/nall/stream/stream.hpp index 6e78b18a..2b10bf17 100644 --- a/nall/stream/stream.hpp +++ b/nall/stream/stream.hpp @@ -51,7 +51,6 @@ struct stream { string text() const { string buffer; buffer.resize(size() + 1); - buffer[size()] = 0; seek(0); read((uint8_t*)buffer.data(), size()); return buffer; diff --git a/nall/stream/zip.hpp b/nall/stream/zip.hpp index dfb4767b..c7730897 100644 --- a/nall/stream/zip.hpp +++ b/nall/stream/zip.hpp @@ -1,7 +1,7 @@ #ifndef NALL_STREAM_ZIP_HPP #define NALL_STREAM_ZIP_HPP -#include <nall/unzip.hpp> +#include <nall/decode/zip.hpp> namespace nall { @@ -14,7 +14,7 @@ struct zipstream : memorystream { uint8_t* data = new uint8_t[size]; stream.read(data, size); - unzip archive; + Decode::ZIP archive; if(archive.open(data, size) == false) return; delete[] data; diff --git a/nall/string.hpp b/nall/string.hpp index adf86b31..32f15f4c 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -12,34 +12,37 @@ #include <nall/platform.hpp> #include <nall/atoi.hpp> -#include <nall/crc32.hpp> #include <nall/function.hpp> #include <nall/intrinsics.hpp> -#include <nall/sha256.hpp> +#include <nall/memory.hpp> +#include <nall/method.hpp> #include <nall/stdint.hpp> #include <nall/utility.hpp> #include <nall/varint.hpp> #include <nall/vector.hpp> - -#include <nall/windows/utf8.hpp> +#include <nall/hash/crc16.hpp> +#include <nall/hash/crc32.hpp> +#include <nall/hash/sha256.hpp> #define NALL_STRING_INTERNAL_HPP -#include <nall/string/char.hpp> #include <nall/string/base.hpp> #include <nall/string/ref.hpp> #include <nall/string/cast.hpp> +#include <nall/string/compare.hpp> +#include <nall/string/convert.hpp> #include <nall/string/core.hpp> #include <nall/string/datetime.hpp> -#include <nall/string/file.hpp> -#include <nall/string/filename.hpp> +#include <nall/string/find.hpp> #include <nall/string/format.hpp> +#include <nall/string/hash.hpp> #include <nall/string/list.hpp> +#include <nall/string/match.hpp> +#include <nall/string/path.hpp> #include <nall/string/platform.hpp> #include <nall/string/replace.hpp> #include <nall/string/split.hpp> +#include <nall/string/trim.hpp> #include <nall/string/utility.hpp> -#include <nall/string/variadic.hpp> -#include <nall/string/wrapper.hpp> #include <nall/string/eval/node.hpp> #include <nall/string/eval/literal.hpp> #include <nall/string/eval/parser.hpp> @@ -48,6 +51,8 @@ #include <nall/string/markup/bml.hpp> #include <nall/string/markup/xml.hpp> #include <nall/string/markup/document.hpp> +#include <nall/string/transform/cml.hpp> +#include <nall/string/transform/dml.hpp> #undef NALL_STRING_INTERNAL_HPP #endif diff --git a/nall/string/allocator/adaptive.hpp b/nall/string/allocator/adaptive.hpp new file mode 100644 index 00000000..0a9f75fe --- /dev/null +++ b/nall/string/allocator/adaptive.hpp @@ -0,0 +1,123 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +/***** + adaptive allocator + sizeof(string) == SSO + 8 + + aggressively tries to avoid heap allocations + small strings are stored on the stack + large strings are shared via copy-on-write + + SSO alone is very slow on large strings due to copying + SSO alone is very slightly faster than this allocator on small strings + + COW alone is very slow on small strings due to heap allocations + COW alone is very slightly faster than this allocator on large strings + + adaptive is thus very fast for all string sizes +*****/ + +namespace nall { + +string::string() : _data(nullptr), _capacity(SSO - 1), _size(0) { +} + +auto string::pointer() -> char* { + if(_capacity < SSO) return _text; + if(*_refs > 1) _copy(); + return _data; +} + +auto string::data() const -> const char* { + if(_capacity < SSO) return _text; + return _data; +} + +auto string::reset() -> type& { + if(_capacity >= SSO && !--*_refs) memory::free(_data); + _data = nullptr; + _capacity = SSO - 1; + _size = 0; + return *this; +} + +auto string::reserve(unsigned capacity) -> type& { + if(capacity <= _capacity) return *this; + capacity = bit::round(capacity + 1) - 1; + if(_capacity < SSO) { + _capacity = capacity; + _allocate(); + } else if(*_refs > 1) { + _capacity = capacity; + _copy(); + } else { + _capacity = capacity; + _resize(); + } + return *this; +} + +auto string::resize(unsigned size) -> type& { + reserve(size); + pointer()[_size = size] = 0; + return *this; +} + +auto string::operator=(const string& source) -> type& { + if(&source == this) return *this; + reset(); + if(source._capacity >= SSO) { + _data = source._data; + _refs = source._refs; + _capacity = source._capacity; + _size = source._size; + ++*_refs; + } else { + memory::copy(_text, source._text, SSO); + _capacity = source._capacity; + _size = source._size; + } + return *this; +} + +auto string::operator=(string&& source) -> type& { + if(&source == this) return *this; + reset(); + memory::copy(this, &source, sizeof(string)); + source._data = nullptr; + source._capacity = SSO - 1; + source._size = 0; + return *this; +} + +//SSO -> COW +auto string::_allocate() -> void { + char _temp[SSO]; + memory::copy(_temp, _text, SSO); + _data = (char*)memory::allocate(_capacity + 1 + sizeof(unsigned)); + memory::copy(_data, _temp, SSO); + _refs = (unsigned*)(_data + _capacity + 1); //always aligned by 32 via reserve() + *_refs = 1; +} + +//COW -> Unique +auto string::_copy() -> void { + auto _temp = (char*)memory::allocate(_capacity + 1 + sizeof(unsigned)); + memory::copy(_temp, _data, _size = min(_capacity, _size)); + _temp[_size] = 0; + --*_refs; + _data = _temp; + _refs = (unsigned*)(_data + _capacity + 1); + *_refs = 1; +} + +//COW -> Resize +auto string::_resize() -> void { + _data = (char*)memory::resize(_data, _capacity + 1 + sizeof(unsigned)); + _refs = (unsigned*)(_data + _capacity + 1); + *_refs = 1; +} + +} + +#endif diff --git a/nall/string/allocator/copy-on-write.hpp b/nall/string/allocator/copy-on-write.hpp index 3890ce4c..574dde97 100644 --- a/nall/string/allocator/copy-on-write.hpp +++ b/nall/string/allocator/copy-on-write.hpp @@ -1,102 +1,90 @@ #ifdef NALL_STRING_INTERNAL_HPP -/* -copy on write (COW) allocator -sizeof(string) == 24 (amd64) - -utilizes a shared_ptr to reference count strings -allows string copies to execute as fast as string moves -requires extra computations, which will be slower for all string sizes - -pros: -* lower memory usage -* pass-by-value does not require heap allocation; obviates pass-by-const-reference - -cons: -* added overhead to fetch data() -* added heap allocation for reference-count pool -* no potential for in-place resize (always copies) -* larger sizeof(string) - -*/ - namespace nall { -char* string::data() { - if(!_data.unique()) _copy(); - return _data.get(); +string::string() : _data(nullptr), _refs(nullptr), _capacity(0), _size(0) { } -const char* string::data() const { - if(!_data) return ""; - return _data.get(); +auto string::pointer() -> char* { + static char _null[] = ""; + if(!_data) return _null; + if(*_refs > 1) _data = _copy(); //make unique for write operations + return _data; } -//copy _data (to make unique or to grow in size) -void string::_copy() { - auto copy = new char[_capacity + 1]; - if(_data.get()) memcpy(copy, _data.get(), min(_capacity, _size)); - copy[_size] = 0; - copy[_capacity] = 0; - _data.reset(copy); +auto string::data() const -> const char* { + static const char _null[] = ""; + if(!_data) return _null; + return _data; } -//amortize growth to O(log n) -//allocate one extra byte to always store null-terminator for libc usage -void string::reserve(unsigned capacity) { - if(capacity > _capacity) { - _capacity = bit::round(capacity + 1) - 1; - _copy(); +auto string::reset() -> type& { + if(_data && !--*_refs) { + memory::free(_data); + _data = nullptr; //_refs = nullptr; is unnecessary } -} - -void string::resize(unsigned size) { - reserve(size); - data()[_size = size] = 0; -} - -void string::reset() { - _data.reset(); _capacity = 0; _size = 0; -} - -string& string::operator=(const string& source) { - if(&source == this) return *this; - reset(); - _data = source._data; - _capacity = source._capacity; - _size = source._size; return *this; } -string& string::operator=(string&& source) { +auto string::reserve(unsigned capacity) -> type& { + if(capacity > _capacity) { + _capacity = bit::round(max(31u, capacity) + 1) - 1; + _data = _data ? _copy() : _allocate(); + } + return *this; +} + +auto string::resize(unsigned size) -> type& { + reserve(size); + pointer()[_size = size] = 0; + return *this; +} + +auto string::operator=(const string& source) -> string& { if(&source == this) return *this; reset(); - _data = std::move(source._data); + if(source._data) { + _data = source._data; + _refs = source._refs; + _capacity = source._capacity; + _size = source._size; + ++*_refs; + } + return *this; +} + +auto string::operator=(string&& source) -> string& { + if(&source == this) return *this; + reset(); + _data = source._data; + _refs = source._refs; _capacity = source._capacity; _size = source._size; + source._data = nullptr; + source._refs = nullptr; source._capacity = 0; source._size = 0; return *this; } -template<typename T, typename... Args> string::string(T&& source, Args&&... args) { - construct(); - sprint(*this, std::forward<T>(source), std::forward<Args>(args)...); +auto string::_allocate() -> char* { + auto _temp = (char*)memory::allocate(_capacity + 1 + sizeof(unsigned)); + *_temp = 0; + _refs = (unsigned*)(_temp + _capacity + 1); //this will always be aligned by 32 via reserve() + *_refs = 1; + return _temp; } -string::string() { - construct(); -} - -string::~string() { - reset(); -} - -void string::construct() { - _capacity = 0; - _size = 0; +auto string::_copy() -> char* { + auto _temp = (char*)memory::allocate(_capacity + 1 + sizeof(unsigned)); + memory::copy(_temp, _data, _size = min(_capacity, _size)); + _temp[_size] = 0; + --*_refs; + _refs = (unsigned*)(_temp + _capacity + 1); + *_refs = 1; + return _temp; } } diff --git a/nall/string/allocator/small-string-optimization.hpp b/nall/string/allocator/small-string-optimization.hpp index 8e3c4117..0430abbf 100644 --- a/nall/string/allocator/small-string-optimization.hpp +++ b/nall/string/allocator/small-string-optimization.hpp @@ -2,7 +2,7 @@ /* small string optimization (SSO) allocator -sizeof(string) == 16 (amd64) +sizeof(string) == 8 + string::SSO utilizes a union to store small strings directly into text pointer bypasses the need to allocate heap memory for small strings @@ -10,102 +10,86 @@ requires extra computations, which can be slower for large strings pros: * potential for in-place resize -* no heap allocation when (capacity < 8) +* no heap allocation when (capacity < SSO) cons: * added overhead to fetch data() -* 32-bit platforms limited to (capacity < 4) -* pass-by-value requires heap allocation +* pass-by-value requires heap allocation when (capacity >= SSO) */ namespace nall { -char* string::data() { - if(_capacity < SSO) return _text; - return _data; -} - -const char* string::data() const { - if(_capacity < SSO) return _text; - return _data; -} - -void string::reserve(unsigned capacity) { - if(capacity > _capacity) { - if(capacity >= SSO) { - capacity = bit::round(capacity + 1) - 1; - if(_capacity < SSO) { - char temp[SSO]; - memcpy(temp, _text, SSO); - _data = (char*)malloc(capacity + 1); - memcpy(_data, temp, SSO); - } else { - _data = (char*)realloc(_data, capacity + 1); - } - } - _capacity = capacity; - data()[_capacity] = 0; - } -} - -void string::resize(unsigned size) { - reserve(size); - data()[_size = size] = 0; -} - -void string::reset() { - if(_capacity >= SSO) free(_data); +string::string() { _data = nullptr; _capacity = SSO - 1; _size = 0; } -string& string::operator=(const string& source) { - if(&source == this) return *this; - reset(); - if(source._capacity >= SSO) { - _data = (char*)malloc(source._capacity + 1); - _capacity = source._capacity; - _size = source._size; - memcpy(_data, source.data(), source.size() + 1); +auto string::pointer() -> char* { + if(_capacity < SSO) return _text; + return _data; +} + +auto string::data() const -> const char* { + if(_capacity < SSO) return _text; + return _data; +} + +auto string::reset() -> type& { + if(_capacity >= SSO) memory::free(_data); + _data = nullptr; + _capacity = SSO - 1; + _size = 0; + return *this; +} + +auto string::reserve(unsigned capacity) -> type& { + if(capacity <= _capacity) return *this; + capacity = bit::round(capacity + 1) - 1; + if(_capacity < SSO) { + char _temp[SSO]; + memory::copy(_temp, _text, SSO); + _data = (char*)memory::allocate(_capacity = capacity + 1); + memory::copy(_data, _temp, SSO); } else { - memcpy(_text, source._text, SSO); - _capacity = SSO - 1; - _size = strlen(_text); + _data = (char*)memory::resize(_data, _capacity = capacity + 1); } return *this; } -string& string::operator=(string&& source) { +auto string::resize(unsigned size) -> type& { + reserve(size); + pointer()[_size = size] = 0; + return *this; +} + +auto string::operator=(const string& source) -> type& { if(&source == this) return *this; reset(); - memcpy(this, &source, sizeof(string)); + if(source._capacity >= SSO) { + _data = (char*)memory::allocate(source._capacity + 1); + _capacity = source._capacity; + _size = source._size; + memory::copy(_data, source._data, source._size + 1); + } else { + memory::copy(_text, source._text, SSO); + _capacity = SSO - 1; + _size = source._size; + } + return *this; +} + +auto string::operator=(string&& source) -> type& { + if(&source == this) return *this; + reset(); + memory::copy(this, &source, sizeof(string)); source._data = nullptr; source._capacity = SSO - 1; source._size = 0; return *this; } -template<typename T, typename... Args> string::string(T&& source, Args&&... args) { - construct(); - sprint(*this, std::forward<T>(source), std::forward<Args>(args)...); -} - -string::string() { - construct(); -} - -string::~string() { - reset(); -} - -void string::construct() { - _data = nullptr; - _capacity = SSO - 1; - _size = 0; -} - } #endif diff --git a/nall/string/allocator/vector.hpp b/nall/string/allocator/vector.hpp index 7b7aaaaf..856221a5 100644 --- a/nall/string/allocator/vector.hpp +++ b/nall/string/allocator/vector.hpp @@ -19,46 +19,49 @@ cons: namespace nall { -char* string::data() { +auto string::pointer() -> char* { if(_capacity == 0) reserve(1); return _data; } -const char* string::data() const { +auto string::data() const -> const char* { if(_capacity == 0) return ""; return _data; } -void string::reserve(unsigned capacity) { - if(capacity > _capacity) { - _capacity = bit::round(capacity + 1) - 1; - _data = (char*)realloc(_data, _capacity + 1); - _data[_capacity] = 0; - } -} - -void string::resize(unsigned size) { - reserve(size); - data()[_size = size] = 0; -} - -void string::reset() { - if(_data) { free(_data); _data = nullptr; } +auto string::reset() -> type& { + if(_data) { memory::free(_data); _data = nullptr; } _capacity = 0; _size = 0; -} - -string& string::operator=(const string& source) { - if(&source == this) return *this; - reset(); - _data = (char*)malloc(source._size + 1); - _capacity = source._size; - _size = source._size; - memcpy(_data, source.data(), source.size() + 1); return *this; } -string& string::operator=(string&& source) { +auto string::reserve(unsigned capacity) -> type& { + if(capacity > _capacity) { + _capacity = bit::round(capacity + 1) - 1; + _data = (char*)memory::resize(_data, _capacity + 1); + _data[_capacity] = 0; + } + return *this; +} + +auto string::resize(unsigned size) -> type& { + reserve(size); + pointer()[_size = size] = 0; + return *this; +} + +auto string::operator=(const string& source) -> type& { + if(&source == this) return *this; + reset(); + _data = (char*)memory::allocate(source._size + 1); + _capacity = source._size; + _size = source._size; + memory::copy(_data, source.data(), source.size() + 1); + return *this; +} + +auto string::operator=(string&& source) -> type& { if(&source == this) return *this; reset(); _data = source._data; @@ -70,20 +73,7 @@ string& string::operator=(string&& source) { return *this; } -template<typename T, typename... Args> string::string(T&& source, Args&&... args) { - construct(); - sprint(*this, std::forward<T>(source), std::forward<Args>(args)...); -} - string::string() { - construct(); -} - -string::~string() { - reset(); -} - -void string::construct() { _data = nullptr; _capacity = 0; _size = 0; diff --git a/nall/string/base.hpp b/nall/string/base.hpp index 8da9d880..178a77dd 100644 --- a/nall/string/base.hpp +++ b/nall/string/base.hpp @@ -3,19 +3,165 @@ namespace nall { struct string; +struct format; struct stringref; struct lstring; -typedef const stringref& rstring; +using cstring = const string&; +using rstring = const stringref&; +#define NALL_STRING_ALLOCATOR_ADAPTIVE //#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE -#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION +//#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION //#define NALL_STRING_ALLOCATOR_VECTOR +//cast.hpp +template<typename T> struct stringify; + +//compare.hpp +inline auto compare(const string& self, rstring source) -> signed; +inline auto icompare(const string& self, rstring source) -> signed; + +inline auto equals(const string& self, rstring source) -> bool; +inline auto iequals(const string& self, rstring source) -> bool; + +inline auto beginsWith(const string& self, rstring source) -> bool; +inline auto ibeginsWith(const string& self, rstring source) -> bool; + +inline auto endsWith(const string& self, rstring source) -> bool; +inline auto iendsWith(const string& self, rstring source) -> bool; + +//convert.hpp +inline auto downcase(string& self) -> string&; +inline auto qdowncase(string& self) -> string&; + +inline auto upcase(string& self) -> string&; +inline auto qupcase(string& self) -> string&; + +inline auto transform(string& self, rstring from, rstring to) -> string&; + +//core.hpp +template<typename... P> inline auto assign(string& self, P&&... p) -> string&; +template<typename T, typename... P> inline auto append(string& self, const T& value, P&&... p) -> string&; +template<typename... P> inline auto append(string& self, const format& value, P&&... p) -> string&; +inline auto append(string& self) -> string&; +template<typename T> inline auto _append(string& self, const stringify<T>& source) -> string&; +inline auto empty(const string& self) -> bool; +inline auto length(const string& self) -> unsigned; + +//find.hpp +template<bool I, bool Q> inline auto _find(const string& self, signed offset, rstring source) -> maybe<unsigned>; +inline auto find(const string& self, rstring source) -> maybe<unsigned>; +inline auto ifind(const string& self, rstring source) -> maybe<unsigned>; +inline auto qfind(const string& self, rstring source) -> maybe<unsigned>; +inline auto iqfind(const string& self, rstring source) -> maybe<unsigned>; +inline auto findFrom(const string& self, signed offset, rstring source) -> maybe<unsigned>; +inline auto ifindFrom(const string& self, signed offset, rstring source) -> maybe<unsigned>; + +//format.hpp +template<typename... P> inline auto print(P&&...) -> void; +template<signed precision = 0, char padchar = '0'> inline auto integer(intmax_t value) -> string; +template<signed precision = 0, char padchar = '0'> inline auto decimal(uintmax_t value) -> string; +template<signed precision = 0, char padchar = '0'> inline auto hex(uintmax_t value) -> string; +template<signed precision = 0, char padchar = '0'> inline auto octal(uintmax_t value) -> string; +template<signed precision = 0, char padchar = '0'> inline auto binary(uintmax_t value) -> string; +template<signed precision = 0, typename T> inline auto pointer(const T* value) -> string; +template<signed precision = 0> inline auto pointer(uintptr_t value) -> string; +inline auto real(long double value) -> string; + +//hash.hpp +inline auto crc16(const string& self) -> string; +inline auto crc32(const string& self) -> string; +inline auto sha256(const string& self) -> string; + +//match.hpp +inline auto match(const string& self, rstring source) -> bool; +inline auto imatch(const string& self, rstring source) -> bool; +inline auto tokenize(lstring& list, const char* s, const char* p) -> bool; + +//path.hpp +inline auto pathname(const string& self) -> string; +inline auto filename(const string& self) -> string; + +inline auto dirname(const string& self) -> string; +inline auto basename(const string& self) -> string; +inline auto prefixname(const string& self) -> string; +inline auto suffixname(const string& self) -> string; + +//platform.hpp +inline auto activepath() -> string; +inline auto realpath(rstring name) -> string; +inline auto programpath() -> string; +inline auto userpath() -> string; +inline auto configpath() -> string; +inline auto sharedpath() -> string; +inline auto temppath() -> string; + +//replace.hpp +template<unsigned L, bool I, bool Q> inline auto _replace(string& self, rstring from, rstring to) -> string&; +template<unsigned L = ~0u> inline auto replace(string& self, rstring from, rstring to) -> string&; +template<unsigned L = ~0u> inline auto ireplace(string& self, rstring from, rstring to) -> string&; +template<unsigned L = ~0u> inline auto qreplace(string& self, rstring from, rstring to) -> string&; +template<unsigned L = ~0u> inline auto iqreplace(string& self, rstring from, rstring to) -> string&; + +//split.hpp +template<unsigned L, bool I, bool Q> inline auto _split(lstring& self, rstring source, rstring find) -> lstring&; +template<unsigned L = ~0u> inline auto split(string& self, rstring key) -> lstring; +template<unsigned L = ~0u> inline auto isplit(string& self, rstring key) -> lstring; +template<unsigned L = ~0u> inline auto qsplit(string& self, rstring key) -> lstring; +template<unsigned L = ~0u> inline auto iqsplit(string& self, rstring key) -> lstring; + +//trim.hpp +inline auto trim(string& self, rstring lhs, rstring rhs) -> bool; +inline auto ltrim(string& self, rstring lhs) -> bool; +inline auto rtrim(string& self, rstring rhs) -> bool; + +inline auto itrim(string& self, rstring lhs, rstring rhs) -> bool; +inline auto iltrim(string& self, rstring lhs) -> bool; +inline auto irtrim(string& self, rstring rhs) -> bool; + +inline auto strip(string& self) -> bool; +inline auto lstrip(string& self) -> bool; +inline auto rstrip(string& self) -> bool; + +//utility.hpp +inline auto fill(string& self, char fill = ' ') -> string&; +inline auto hash(const string& self) -> unsigned; +inline auto remove(string& self, unsigned offset, unsigned length) -> string&; +inline auto reverse(string& self) -> string&; +inline auto size(string& self, signed length, char fill = ' ') -> string&; +inline auto slice(const string& self, signed offset = 0, signed length = -1) -> string; +inline auto substr(rstring source, signed offset = 0, signed length = -1) -> string; + +inline auto integer(char* result, intmax_t value) -> char*; +inline auto decimal(char* result, uintmax_t value) -> char*; +inline auto real(char* str, long double value) -> unsigned; + struct string { + using type = string; + struct exception_out_of_bounds{}; + protected: + #if defined(NALL_STRING_ALLOCATOR_ADAPTIVE) + enum : unsigned { SSO = 24 }; + union { + struct { //copy-on-write + char* _data; + unsigned* _refs; + }; + struct { //small-string-optimization + char _text[SSO]; + }; + }; + inline auto _allocate() -> void; + inline auto _copy() -> void; + inline auto _resize() -> void; + #endif + #if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE) - inline void _copy(); - std::shared_ptr<char> _data; + char* _data; + mutable unsigned* _refs; + inline auto _allocate() -> char*; + inline auto _copy() -> char*; #endif #if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION) @@ -34,194 +180,213 @@ protected: unsigned _size; public: + inline string(); + inline auto pointer() -> char*; + inline auto data() const -> const char*; + inline auto reset() -> type&; + inline auto reserve(unsigned) -> type&; + inline auto resize(unsigned) -> type&; + inline auto operator=(const string&) -> type&; + inline auto operator=(string&&) -> type&; + + template<typename T, typename... P> string(T&& s, P&&... p) : string() { append(std::forward<T>(s), std::forward<P>(p)...); } + ~string() { reset(); } + + explicit operator bool() const { return _size; } + operator const uint8_t*() const { return (const uint8_t*)data(); } + operator const char*() const { return (const char*)data(); } + + auto binary() const -> const uint8_t* { return (const uint8_t*)data(); } + auto size() const -> unsigned { return _size; } + auto capacity() const -> unsigned { return _capacity; } + + auto operator==(const string& s) const -> bool { return size() == s.size() && memory::compare(data(), s.data(), s.size()) == 0; } + auto operator!=(const string& s) const -> bool { return size() != s.size() || memory::compare(data(), s.data(), s.size()) != 0; } + + auto operator==(const char* s) const -> bool { return strcmp(data(), s) == 0; } + auto operator!=(const char* s) const -> bool { return strcmp(data(), s) != 0; } + auto operator< (const char* s) const -> bool { return strcmp(data(), s) < 0; } + auto operator<=(const char* s) const -> bool { return strcmp(data(), s) <= 0; } + auto operator> (const char* s) const -> bool { return strcmp(data(), s) > 0; } + auto operator>=(const char* s) const -> bool { return strcmp(data(), s) >= 0; } + + string(const string& source) : string() { operator=(source); } + string(string&& source) : string() { operator=(std::move(source)); } + + auto begin() -> char* { return &pointer()[0]; } + auto end() -> char* { return &pointer()[size()]; } + auto begin() const -> const char* { return &data()[0]; } + auto end() const -> const char* { return &data()[size()]; } + + //nall/atoi.hpp + inline auto integer() const -> intmax_t { return nall::integer(*this); } + inline auto decimal() const -> uintmax_t { return nall::decimal(*this); } + inline auto hex() const -> uintmax_t { return nall::hex(*this); } + //core.hpp - inline char* data(); - inline const char* data() const; - inline unsigned length() const; - inline unsigned size() const; - inline unsigned capacity() const; - inline bool empty() const; - - inline void reset(); - inline void reserve(unsigned); - inline void resize(unsigned); - inline void clear(char); - - inline unsigned hash() const; - - template<typename... Args> inline string& assign(Args&&... args); - template<typename... Args> inline string& append(Args&&... args); - - //file.hpp - inline static string read(const string& filename); + inline auto operator[](signed) const -> const char&; //datetime.hpp - inline static string date(); - inline static string time(); - inline static string datetime(); + inline static auto date(time_t = 0) -> string; + inline static auto time(time_t = 0) -> string; + inline static auto datetime(time_t = 0) -> string; - //replace.hpp - template<unsigned Limit = 0> inline string& replace(rstring, rstring); - template<unsigned Limit = 0> inline string& ireplace(rstring, rstring); - template<unsigned Limit = 0> inline string& qreplace(rstring, rstring); - template<unsigned Limit = 0> inline string& iqreplace(rstring, rstring); + //format.hpp + inline auto format(const nall::format& params) -> type&; - //wrapper.hpp - template<unsigned Limit = 0> inline lstring split(rstring) const; - template<unsigned Limit = 0> inline lstring isplit(rstring) const; - template<unsigned Limit = 0> inline lstring qsplit(rstring) const; - template<unsigned Limit = 0> inline lstring iqsplit(rstring) const; + //utility.hpp + inline static auto read(const string& filename) -> string; + template<unsigned L> inline static auto repeat(const string& pattern) -> string; - inline signed compare(rstring) const; - inline signed icompare(rstring) const; + //extension methods + //================= - inline bool equals(rstring) const; - inline bool iequals(rstring) const; + //compare.hpp + auto compare(rstring source) const -> signed { return nall::compare(*this, source); } + auto icompare(rstring source) const -> signed { return nall::compare(*this, source); } - inline bool match(rstring) const; - inline bool imatch(rstring) const; + auto equals(rstring source) const -> bool { return nall::equals(*this, source); } + auto iequals(rstring source) const -> bool { return nall::iequals(*this, source); } - inline bool beginsWith(rstring) const; - inline bool ibeginsWith(rstring) const; - inline bool endsWith(rstring) const; - inline bool iendsWith(rstring) const; + auto beginsWith(rstring source) const -> bool { return nall::beginsWith(*this, source); } + auto ibeginsWith(rstring source) const -> bool { return nall::ibeginsWith(*this, source); } - inline string slice(unsigned offset, unsigned length = ~0u) const; + auto endsWith(rstring source) const -> bool { return nall::endsWith(*this, source); } + auto iendsWith(rstring source) const -> bool { return nall::iendsWith(*this, source); } - inline string& lower(); - inline string& upper(); - inline string& qlower(); - inline string& qupper(); - inline string& transform(rstring before, rstring after); - inline string& reverse(); + //convert.hpp + auto downcase() -> type& { return nall::downcase(*this); } + auto upcase() -> type& { return nall::upcase(*this); } - template<unsigned limit = 0> inline string& ltrim() { return ltrim<limit>(" "); } - template<unsigned limit = 0> inline string& ltrim(rstring key); + auto qdowncase() -> type& { return nall::qdowncase(*this); } + auto qupcase() -> type& { return nall::qupcase(*this); } - template<unsigned limit = 0> inline string& rtrim() { return rtrim<limit>(" "); } - template<unsigned limit = 0> inline string& rtrim(rstring key); - - template<unsigned limit = 0> inline string& trim() { return trim<limit>(" "); } - template<unsigned limit = 0> inline string& trim(rstring key); - template<unsigned limit = 0> inline string& trim(rstring key, rstring rkey); - - inline string& strip(); - - inline maybe<unsigned> find(rstring key) const; - inline maybe<unsigned> ifind(rstring key) const; - inline maybe<unsigned> qfind(rstring key) const; - inline maybe<unsigned> iqfind(rstring key) const; + auto transform(rstring from, rstring to) -> type& { return nall::transform(*this, from, to); } //core.hpp - inline explicit operator bool() const; - inline operator const char*() const; - inline char& operator[](signed); - inline const char& operator[](signed) const; + template<typename... P> auto assign(P&&... p) -> type& { return nall::assign(*this, std::forward<P>(p)...); } + template<typename... P> auto append(P&&... p) -> type& { return nall::append(*this, std::forward<P>(p)...); } + auto empty() const -> bool { return nall::empty(*this); } + auto length() const -> unsigned { return nall::length(*this); } - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; + //find.hpp + auto find(rstring source) const -> maybe<unsigned> { return nall::find(*this, source); } + auto ifind(rstring source) const -> maybe<unsigned> { return nall::ifind(*this, source); } + auto qfind(rstring source) const -> maybe<unsigned> { return nall::qfind(*this, source); } + auto iqfind(rstring source) const -> maybe<unsigned> { return nall::iqfind(*this, source); } - inline string& operator=(const string&); - inline string& operator=(string&&); + auto findFrom(signed offset, rstring source) const -> maybe<unsigned> { return nall::findFrom(*this, offset, source); } + auto ifindFrom(signed offset, rstring source) const -> maybe<unsigned> { return nall::ifindFrom(*this, offset, source); } - template<typename T, typename... Args> inline string(T&& source, Args&&... args); - inline string(); - inline string(const string&); - inline string(string&&); - inline ~string(); + //hash.hpp + auto crc16() const -> string { return nall::crc16(*this); } + auto crc32() const -> string { return nall::crc32(*this); } + auto sha256() const -> string { return nall::sha256(*this); } - inline char* begin() { return &data()[0]; } - inline char* end() { return &data()[size()]; } - inline const char* begin() const { return &data()[0]; } - inline const char* end() const { return &data()[size()]; } + //match.hpp + auto match(rstring source) const -> bool { return nall::match(*this, source); } + auto imatch(rstring source) const -> bool { return nall::imatch(*this, source); } -//protected: - struct exception_out_of_bounds{}; - template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(rstring, rstring); - inline string& _append(const char*); + //path.hpp + auto pathname() const -> string { return nall::pathname(*this); } + auto filename() const -> string { return nall::filename(*this); } -private: - inline void construct(); + auto dirname() const -> string { return nall::dirname(*this); } + auto basename() const -> string { return nall::basename(*this); } + auto prefixname() const -> string { return nall::prefixname(*this); } + auto suffixname() const -> string { return nall::suffixname(*this); } -#if defined(QSTRING_H) -public: + //replace.hpp + template<unsigned L = ~0u> auto replace(rstring from, rstring to) -> type& { return nall::_replace<L, 0, 0>(*this, from, to); } + template<unsigned L = ~0u> auto ireplace(rstring from, rstring to) -> type& { return nall::_replace<L, 1, 0>(*this, from, to); } + template<unsigned L = ~0u> auto qreplace(rstring from, rstring to) -> type& { return nall::_replace<L, 0, 1>(*this, from, to); } + template<unsigned L = ~0u> auto iqreplace(rstring from, rstring to) -> type& { return nall::_replace<L, 1, 1>(*this, from, to); } + + //split.hpp + template<unsigned L = ~0u> inline auto split(rstring key) const -> lstring; + template<unsigned L = ~0u> inline auto isplit(rstring key) const -> lstring; + template<unsigned L = ~0u> inline auto qsplit(rstring key) const -> lstring; + template<unsigned L = ~0u> inline auto iqsplit(rstring key) const -> lstring; + + //trim.hpp + auto trim(rstring lhs, rstring rhs) -> type& { return nall::trim(*this, lhs, rhs), *this; } + auto ltrim(rstring lhs) -> type& { return nall::ltrim(*this, lhs), *this; } + auto rtrim(rstring rhs) -> type& { return nall::rtrim(*this, rhs), *this; } + + auto itrim(rstring lhs, rstring rhs) -> type& { return nall::itrim(*this, lhs, rhs), *this; } + auto iltrim(rstring lhs) -> type& { return nall::iltrim(*this, lhs), *this; } + auto irtrim(rstring rhs) -> type& { return nall::irtrim(*this, rhs), *this; } + + auto strip() -> type& { return nall::strip(*this), *this; } + auto lstrip() -> type& { return nall::lstrip(*this), *this; } + auto rstrip() -> type& { return nall::rstrip(*this), *this; } + + //utility.hpp + auto fill(char fill = ' ') -> type& { return nall::fill(*this, fill); } + auto hash() const -> const type& { return nall::hash(*this), *this; } + auto remove(unsigned offset, unsigned length) -> type& { return nall::remove(*this, offset, length); } + auto reverse() -> type& { return nall::reverse(*this); } + auto size(signed length, char fill = ' ') -> type& { return nall::size(*this, length, fill); } + auto slice(signed offset = 0, signed length = -1) const -> string { return nall::slice(*this, offset, length); } + + #if defined(QSTRING_H) inline operator QString() const; -#endif + #endif }; //list.hpp +template<typename... P> auto append(lstring& self, const string& value, P&&... p) -> lstring&; +inline auto append(lstring& self) -> lstring&; +inline auto find(const lstring& self, const string& source) -> maybe<unsigned>; +inline auto ifind(const lstring& self, const string& source) -> maybe<unsigned>; +inline auto merge(const lstring& self, const string& separator) -> string; +inline auto strip(lstring& self) -> lstring&; + struct lstring : vector<string> { - inline maybe<unsigned> find(rstring) const; - inline string merge(const string&) const; - inline lstring& isort(); - inline lstring& strip(); - inline void append() {} - template<typename... Args> inline void append(const string&, Args&&...); + using type = lstring; - inline bool operator==(const lstring&) const; - inline bool operator!=(const lstring&) const; + lstring(const lstring& source) { vector::operator=(source); } + lstring(lstring& source) { vector::operator=(source); } + lstring(lstring&& source) { vector::operator=(std::move(source)); } + template<typename... P> lstring(P&&... p) { append(std::forward<P>(p)...); } - inline lstring& operator=(const lstring&); - inline lstring& operator=(lstring&); - inline lstring& operator=(lstring&&); + //list.hpp + inline auto operator==(const lstring&) const -> bool; + inline auto operator!=(const lstring&) const -> bool; - template<typename... Args> inline lstring(Args&&... args); - inline lstring(const lstring&); - inline lstring(lstring&); - inline lstring(lstring&&); + inline auto operator=(const lstring& source) -> type& { return vector::operator=(source), *this; } + inline auto operator=(lstring& source) -> type& { return vector::operator=(source), *this; } + inline auto operator=(lstring&& source) -> type& { return vector::operator=(std::move(source)), *this; } + + inline auto isort() -> type&; + + //extension methods + //================= + + //list.hpp + template<typename... P> auto append(P&&... p) -> type& { return nall::append(*this, std::forward<P>(p)...); } + auto find(const string& source) const -> maybe<unsigned> { return nall::find(*this, source); } + auto ifind(const string& source) const -> maybe<unsigned> { return nall::ifind(*this, source); } + auto merge(const string& separator) const -> string { return nall::merge(*this, separator); } + auto strip() -> type& { return nall::strip(*this); } //split.hpp - template<unsigned Limit = 0> inline lstring& split(rstring, rstring); - template<unsigned Limit = 0> inline lstring& isplit(rstring, rstring); - template<unsigned Limit = 0> inline lstring& qsplit(rstring, rstring); - template<unsigned Limit = 0> inline lstring& iqsplit(rstring, rstring); - -protected: - template<unsigned Limit, bool Insensitive, bool Quoted> inline lstring& usplit(rstring, rstring); + template<unsigned L = ~0u> auto split(rstring source, rstring on) -> type& { return nall::_split<L, 0, 0>(*this, source, on); } + template<unsigned L = ~0u> auto isplit(rstring source, rstring on) -> type& { return nall::_split<L, 1, 0>(*this, source, on); } + template<unsigned L = ~0u> auto qsplit(rstring source, rstring on) -> type& { return nall::_split<L, 0, 1>(*this, source, on); } + template<unsigned L = ~0u> auto iqsplit(rstring source, rstring on) -> type& { return nall::_split<L, 1, 1>(*this, source, on); } }; -//filename.hpp -inline string dir(string name); -inline string notdir(string name); -inline string parentdir(string name); -inline string basename(string name); -inline string extension(string name); -inline string tempname(); - //format.hpp -template<signed precision = 0, char padchar = ' '> inline string format(const string& value); -template<signed precision = 0, char padchar = '0'> inline string hex(uintmax_t value); -template<signed precision = 0, char padchar = '0'> inline string octal(uintmax_t value); -template<signed precision = 0, char padchar = '0'> inline string binary(uintmax_t value); +template<typename T, typename... P> inline auto append(format& self, const T& value, P&&... p) -> format&; +inline auto append(format& self) -> format&; -//platform.hpp -inline string activepath(); -inline string realpath(const string& name); -inline string programpath(); -inline string userpath(); -inline string configpath(); -inline string sharedpath(); -inline string temppath(); +struct format : vector<string> { + using type = format; -//utility.hpp -inline string substr(rstring source, unsigned offset = 0, unsigned length = ~0u); -inline string sha256(const uint8_t* data, unsigned size); -inline bool tokenize(lstring& list, const char* s, const char* p); - -inline char* integer(char* result, intmax_t value); -inline char* decimal(char* result, uintmax_t value); - -inline unsigned real(char* str, long double value); -inline string real(long double value); - -//variadic.hpp -inline void sprint(string& output); -template<typename T, typename... Args> inline void sprint(string& output, const T& value, Args&&... args); -template<typename... Args> inline void print(Args&&... args); + template<typename... P> format(P&&... p) { reserve(sizeof...(p)); append(std::forward<P>(p)...); } + template<typename... P> auto append(P&&... p) -> type& { return nall::append(*this, std::forward<P>(p)...); } +}; } diff --git a/nall/string/cast.hpp b/nall/string/cast.hpp index ef79a47d..5b7d13f0 100644 --- a/nall/string/cast.hpp +++ b/nall/string/cast.hpp @@ -1,185 +1,209 @@ #ifdef NALL_STRING_INTERNAL_HPP +//convert any (supported) type to a const char* without constructing a new nall::string +//this is used inside string{...} to build nall::string values + namespace nall { -//convert any (supported) type to a const char* without constructing a new nall::string -//this is used inside istring(...) to build nall::string values -template<typename T> struct stringify; - -// base types +//base types template<> struct stringify<bool> { - bool value; - operator const char*() const { return value ? "true" : "false"; } - stringify(bool value) : value(value) {} + bool _value; + auto data() const -> const char* { return _value ? "true" : "false"; } + auto size() const -> unsigned { return _value ? 4 : 5; } + stringify(bool value) : _value(value) {} }; template<> struct stringify<char> { - char data[2]; - operator const char*() const { return data; } - stringify(char value) { data[0] = value, data[1] = 0; } + char _data[2]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return 1; } + stringify(char source) { _data[0] = source; _data[1] = 0; } }; -// signed integers +//signed integers template<> struct stringify<signed char> { - char data[256]; - operator const char*() const { return data; } - stringify(signed char value) { integer(data, value); } + char _data[2 + sizeof(signed char) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(signed char source) { integer(_data, source); } }; template<> struct stringify<signed short> { - char data[256]; - operator const char*() const { return data; } - stringify(signed short value) { integer(data, value); } + char _data[2 + sizeof(signed short) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(signed short source) { integer(_data, source); } }; template<> struct stringify<signed int> { - char data[256]; - operator const char*() const { return data; } - stringify(signed int value) { integer(data, value); } + char _data[2 + sizeof(signed int) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(signed int source) { integer(_data, source); } }; template<> struct stringify<signed long> { - char data[256]; - operator const char*() const { return data; } - stringify(signed long value) { integer(data, value); } + char _data[2 + sizeof(signed long) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(signed long source) { integer(_data, source); } }; template<> struct stringify<signed long long> { - char data[256]; - operator const char*() const { return data; } - stringify(signed long long value) { integer(data, value); } + char _data[2 + sizeof(signed long long) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(signed long long source) { integer(_data, source); } }; template<unsigned bits> struct stringify<int_t<bits>> { - char data[256]; - operator const char*() const { return data; } - stringify(int_t<bits> value) { integer(data, value); } + char _data[2 + sizeof(intmax_t) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(int_t<bits> source) { integer(_data, source); } }; -// unsigned integers +//unsigned integers template<> struct stringify<unsigned char> { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned char value) { decimal(data, value); } + char _data[1 + sizeof(unsigned char) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(unsigned char source) { decimal(_data, source); } }; template<> struct stringify<unsigned short> { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned short value) { decimal(data, value); } + char _data[1 + sizeof(unsigned short) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(unsigned short source) { decimal(_data, source); } }; template<> struct stringify<unsigned int> { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned int value) { decimal(data, value); } + char _data[1 + sizeof(unsigned int) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(unsigned int source) { decimal(_data, source); } }; template<> struct stringify<unsigned long> { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long value) { decimal(data, value); } + char _data[1 + sizeof(unsigned long) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(unsigned long source) { decimal(_data, source); } }; template<> struct stringify<unsigned long long> { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long long value) { decimal(data, value); } + char _data[1 + sizeof(unsigned long long) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(unsigned long long source) { decimal(_data, source); } }; template<unsigned bits> struct stringify<uint_t<bits>> { - char data[256]; - operator const char*() const { return data; } - stringify(uint_t<bits> value) { decimal(data, value); } + char _data[1 + sizeof(uintmax_t) * 3]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(uint_t<bits> source) { decimal(_data, source); } }; -// floating-point +//floating-point template<> struct stringify<float> { - char data[256]; - operator const char*() const { return data; } - stringify(float value) { real(data, value); } + char _data[256]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(float source) { real(_data, source); } }; template<> struct stringify<double> { - char data[256]; - operator const char*() const { return data; } - stringify(double value) { real(data, value); } + char _data[256]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(double source) { real(_data, source); } }; template<> struct stringify<long double> { - char data[256]; - operator const char*() const { return data; } - stringify(long double value) { real(data, value); } + char _data[256]; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(long double source) { real(_data, source); } }; -// arrays +//arrays template<> struct stringify<vector<uint8_t>> { - char* text; - operator const char*() const { return text; } - stringify(vector<uint8_t> value) { - text = new char[value.size() + 1](); - memcpy(text, value.data(), value.size()); - } - ~stringify() { - delete[] text; + vector<char> _text; + auto data() const -> const char* { return _text.data(); } + auto size() const -> unsigned { return _text.size(); } + stringify(vector<uint8_t> source) { + _text.resize(source.size() + 1); + memory::copy(_text.data(), source.data(), source.size()); + _text[_text.size()] = 0; } }; template<> struct stringify<const vector<uint8_t>&> { - char* text; - operator const char*() const { return text; } - stringify(const vector<uint8_t>& value) { - text = new char[value.size() + 1](); - memcpy(text, value.data(), value.size()); - } - ~stringify() { - delete[] text; + vector<char> _text; + auto data() const -> const char* { return _text.data(); } + auto size() const -> unsigned { return _text.size(); } + stringify(const vector<uint8_t>& source) { + _text.resize(source.size() + 1); + memory::copy(_text.data(), source.data(), source.size()); + _text[_text.size()] = 0; } }; -// strings +//char arrays template<> struct stringify<char*> { - const char* value; - operator const char*() const { return value; } - stringify(char* value) : value(value) {} + const char* _data; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(char* source) : _data(source) {} }; template<> struct stringify<const char*> { - const char* value; - operator const char*() const { return value; } - stringify(const char* value) : value(value) {} + const char* _data; + auto data() const -> const char* { return _data; } + auto size() const -> unsigned { return strlen(_data); } + stringify(const char* source) : _data(source) {} }; +//strings + template<> struct stringify<string> { - const string& value; - operator const char*() const { return value; } - stringify(const string& value) : value(value) {} + const string& _text; + auto data() const -> const char* { return _text.data(); } + auto size() const -> unsigned { return _text.size(); } + stringify(const string& source) : _text(source) {} }; template<> struct stringify<const string&> { - const string& value; - operator const char*() const { return value; } - stringify(const string& value) : value(value) {} + const string& _text; + auto data() const -> const char* { return _text.data(); } + auto size() const -> unsigned { return _text.size(); } + stringify(const string& source) : _text(source) {} }; #if defined(QSTRING_H) +//Qt + template<> struct stringify<QString> { - const QString& value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString& value) : value(value) {} + const QString& _text; + auto data() const -> const char* { return _text.toUtf8().constData(); } + auto size() const -> unsigned { return _text.size(); } + stringify(const QString& source) : _text(source) {} }; template<> struct stringify<const QString&> { - const QString& value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString& value) : value(value) {} + const QString& _text; + auto data() const -> const char* { return _text.toUtf8().constData(); } + auto size() const -> unsigned { return _text.size(); } + stringify(const QString& source) : _text(source) {} }; string::operator QString() const { @@ -190,7 +214,7 @@ string::operator QString() const { // -template<typename T> stringify<T> make_string(T value) { +template<typename T> auto make_string(T value) -> stringify<T> { return stringify<T>(std::forward<T>(value)); } diff --git a/nall/string/char.hpp b/nall/string/char.hpp deleted file mode 100644 index 29ac2c77..00000000 --- a/nall/string/char.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -#include <nall/string/char/base.hpp> -#include <nall/string/char/compare.hpp> -#include <nall/string/char/convert.hpp> -#include <nall/string/char/match.hpp> -#include <nall/string/char/strm.hpp> -#include <nall/string/char/strpos.hpp> -#include <nall/string/char/trim.hpp> -#include <nall/string/char/utf8.hpp> -#include <nall/string/char/utility.hpp> - -#endif diff --git a/nall/string/char/base.hpp b/nall/string/char/base.hpp deleted file mode 100644 index 49b2fc22..00000000 --- a/nall/string/char/base.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//collection of functions to extend libc -//none of these functions require nall::string -//and thus, require no changes when nall::string is modified - -namespace nall { - -//compare.hpp -inline char chrlower(char c); -inline char chrupper(char c); -inline int imemcmp(const char* str1, const char* str2, unsigned size); -inline int istrcmp(const char* str1, const char* str2); -inline bool strbegin(const char* str, const char* key); -inline bool istrbegin(const char* str, const char* key); -inline bool strend(const char* str, const char* key); -inline bool istrend(const char* str, const char* key); - -//convert.hpp -inline char* strlower(char* str); -inline char* strupper(char* str); -inline char* qstrlower(char* str); -inline char* qstrupper(char* str); -inline char* strtr(char* dest, const char* before, const char* after); - -//match.hpp -inline bool strmatch(const char* str, const char* pattern); -inline bool istrmatch(const char* str, const char* pattern); -inline bool tokenize(const char* s, const char* p); - -//strm.hpp -inline unsigned strmcpy(char* target, const char* source, unsigned length); -inline unsigned strmcat(char* target, const char* source, unsigned length); -inline bool strccpy(char* target, const char* source, unsigned length); -inline bool strccat(char* target, const char* source, unsigned length); -inline void strpcpy(char*& target, const char* source, unsigned& length); - -//strpos.hpp -inline maybe<unsigned> strpos(const char* str, const char* key); -inline maybe<unsigned> istrpos(const char* str, const char* key); -inline maybe<unsigned> qstrpos(const char* str, const char* key); -inline maybe<unsigned> iqstrpos(const char* str, const char* key); -template<bool Insensitive = false, bool Quoted = false> inline maybe<unsigned> ustrpos(const char* str, const char* key); - -//trim.hpp -template<unsigned Limit = 0> inline char* ltrim(char* str, const char* key = " "); -template<unsigned Limit = 0> inline char* rtrim(char* str, const char* key = " "); -template<unsigned Limit = 0> inline char* trim(char* str, const char* key = " "); -template<unsigned Limit = 0> inline char* trim(char* str, const char* lkey, const char* rkey); -inline char* strip(char* s); - -//utf8.hpp -struct UTF8 { - unsigned size; //size of encoded codepoint - uint64_t data; //encoded codepoint - unsigned codepoint; //decoded codepoint -}; -inline UTF8 utf8_read(const char* s); -inline void utf8_write(char* s, const UTF8& utf8); - -//utility.hpp -template<bool Insensitive> alwaysinline bool chrequal(char x, char y); -template<bool Quoted, typename T> alwaysinline bool quoteskip(T*& p); -template<bool Quoted, typename T> alwaysinline bool quotecopy(char*& t, T*& p); -inline char* strduplicate(const char* s); - -} - -#endif diff --git a/nall/string/char/compare.hpp b/nall/string/char/compare.hpp deleted file mode 100644 index ff9bf54b..00000000 --- a/nall/string/char/compare.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int imemcmp(const char* str1, const char* str2, unsigned size) { - while(size--) { - if(chrlower(*str1) != chrlower(*str2)) break; - str1++, str2++; - } - return (int)chrlower(*str1) - (int)chrlower(*str2); -} - -int istrcmp(const char* str1, const char* str2) { - while(*str1) { - if(chrlower(*str1) != chrlower(*str2)) break; - str1++, str2++; - } - return (int)chrlower(*str1) - (int)chrlower(*str2); -} - -bool strbegin(const char* str, const char* key) { - if(!str || !key) return false; - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool istrbegin(const char* str, const char* key) { - if(!str || !key) return false; - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char* str, const char* key) { - if(!str || !key) return false; - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool istrend(const char* str, const char* key) { - if(!str || !key) return false; - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/nall/string/char/convert.hpp b/nall/string/char/convert.hpp deleted file mode 100644 index aa003a49..00000000 --- a/nall/string/char/convert.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char* strlower(char* str) { - if(!str) return nullptr; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char* str) { - if(!str) return nullptr; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* qstrlower(char* s) { - if(!s) return nullptr; - char* base = s; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'A' && *s <= 'Z') *s += 0x20; - s++; - } - return base; -} - -char* qstrupper(char* s) { - if(!s) return nullptr; - char* base = s; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'a' && *s <= 'z') *s -= 0x20; - s++; - } - return base; -} - -char* strtr(char* dest, const char* before, const char* after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -} - -#endif diff --git a/nall/string/char/strm.hpp b/nall/string/char/strm.hpp deleted file mode 100644 index 7e2b6e7c..00000000 --- a/nall/string/char/strm.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//return = strlen(target) -unsigned strmcpy(char* target, const char* source, unsigned length) { - const char* origin = target; - if(length) { - while(*source && --length) *target++ = *source++; - *target = 0; - } - return target - origin; -} - -//return = strlen(target) -unsigned strmcat(char* target, const char* source, unsigned length) { - const char* origin = target; - while(*target && length) target++, length--; - return (target - origin) + strmcpy(target, source, length); -} - -//return = true when all of source was copied -bool strccpy(char* target, const char* source, unsigned length) { - return !source[strmcpy(target, source, length)]; -} - -//return = true when all of source was copied -bool strccat(char* target, const char* source, unsigned length) { - while(*target && length) target++, length--; - return !source[strmcpy(target, source, length)]; -} - -//return = reserved for future use -void strpcpy(char*& target, const char* source, unsigned& length) { - unsigned offset = strmcpy(target, source, length); - target += offset, length -= offset; -} - -} - -#endif diff --git a/nall/string/char/strpos.hpp b/nall/string/char/strpos.hpp deleted file mode 100644 index 8c0baa44..00000000 --- a/nall/string/char/strpos.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//usage example: -//if(auto position = strpos(str, key)) print(position(), "\n"); -//prints position of key within str; but only if it is found - -namespace nall { - -template<bool Insensitive, bool Quoted> -maybe<unsigned> ustrpos(const char* str, const char* key) { - const char* base = str; - - while(*str) { - if(quoteskip<Quoted>(str)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) return (unsigned)(str - base); - if(str[n] == 0) return nothing; - if(!chrequal<Insensitive>(str[n], key[n])) break; - } - str++; - } - - return nothing; -} - -maybe<unsigned> strpos(const char* str, const char* key) { return ustrpos<false, false>(str, key); } -maybe<unsigned> istrpos(const char* str, const char* key) { return ustrpos<true, false>(str, key); } -maybe<unsigned> qstrpos(const char* str, const char* key) { return ustrpos<false, true>(str, key); } -maybe<unsigned> iqstrpos(const char* str, const char* key) { return ustrpos<true, true>(str, key); } - -} - -#endif diff --git a/nall/string/char/trim.hpp b/nall/string/char/trim.hpp deleted file mode 100644 index 969b6926..00000000 --- a/nall/string/char/trim.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//limit defaults to zero, which will underflow on first compare; equivalent to no limit -template<unsigned Limit> char* ltrim(char* str, const char* key) { - if(!str || !key || !*key) return str; - unsigned limit = Limit; - while(strbegin(str, key)) { - char* dest = str; - char* src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - if(--limit == 0) break; - } - return str; -} - -template<unsigned Limit> char* rtrim(char* str, const char* key) { - if(!str || !key || !*key) return str; - unsigned limit = Limit; - while(strend(str, key)) { - str[strlen(str) - strlen(key)] = 0; - if(--limit == 0) break; - } - return str; -} - -template<unsigned limit> char* trim(char* str, const char* key) { - return ltrim<limit>(rtrim<limit>(str, key), key); -} - -template<unsigned limit> char* trim(char* str, const char* lkey, const char* rkey) { - return ltrim<limit>(rtrim<limit>(str, rkey), lkey); -} - -//remove whitespace characters from both left and right sides of string -char* strip(char* s) { - if(!s) return nullptr; - - signed n = 0, p = 0; - while(s[n]) { - if(s[n] != ' ' && s[n] != '\t' && s[n] != '\r' && s[n] != '\n') break; - n++; - } - while(s[n]) s[p++] = s[n++]; - s[p--] = 0; - while(p >= 0) { - if(s[p] != ' ' && s[p] != '\t' && s[p] != '\r' && s[p] != '\n') break; - p--; - } - s[++p] = 0; - - return s; -} - -} - -#endif diff --git a/nall/string/char/utf8.hpp b/nall/string/char/utf8.hpp deleted file mode 100644 index 03eb5ef0..00000000 --- a/nall/string/char/utf8.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -UTF8 utf8_read(const char* s) { - UTF8 utf8; - - if((*s & 0xfe) == 0xfc) utf8.size = 6; - else if((*s & 0xfc) == 0xf8) utf8.size = 5; - else if((*s & 0xf8) == 0xf0) utf8.size = 4; - else if((*s & 0xf0) == 0xe0) utf8.size = 3; - else if((*s & 0xe0) == 0xc0) utf8.size = 2; - else utf8.size = 1; - - utf8.data = 0; - for(unsigned n = 0; n < utf8.size; n++) { - utf8.data = (utf8.data << 8) | (uint8_t)s[n]; - } - - static uint8_t mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; - utf8.codepoint = s[0] & mask[utf8.size]; - for(unsigned n = 1; n < utf8.size; n++) { - utf8.codepoint = (utf8.codepoint << 6) | (s[n] & 0x3f); - } - - return utf8; -} - -void utf8_write(char* s, const UTF8& utf8) { - for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) { - s[n] = utf8.data >> shift; - } -} - -} - -#endif diff --git a/nall/string/char/utility.hpp b/nall/string/char/utility.hpp deleted file mode 100644 index bb35c020..00000000 --- a/nall/string/char/utility.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template<bool Insensitive> -bool chrequal(char x, char y) { - if(Insensitive) return chrlower(x) == chrlower(y); - return x == y; -} - -template<bool Quoted, typename T> -bool quoteskip(T*& p) { - if(Quoted == false) return false; - if(*p != '\"') return false; - - while(*p == '\"') { - char x = *p++; - while(*p && *p++ != x); - } - - return true; -} - -template<bool Quoted, typename T> -bool quotecopy(char*& t, T*& p) { - if(Quoted == false) return false; - if(*p != '\"') return false; - - while(*p == '\"') { - char x = *p++; - *t++ = x; - while(*p && *p != x) *t++ = *p++; - *t++ = *p++; - } - - return true; -} - -//strdup() is not a standard function, so recreate it -char* strduplicate(const char* s) { - if(s == nullptr) return nullptr; - unsigned length = strlen(s); - char* result = (char*)malloc(length + 1); - strcpy(result, s); - return result; -} - -} - -#endif diff --git a/nall/string/compare.hpp b/nall/string/compare.hpp new file mode 100644 index 00000000..7c4f49d6 --- /dev/null +++ b/nall/string/compare.hpp @@ -0,0 +1,50 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +template<bool Insensitive> inline auto _compare(const char* target, unsigned capacity, const char* source, unsigned size) -> signed { + if(Insensitive) return memory::icompare(target, capacity, source, size); + return memory::compare(target, capacity, source, size); +} + +auto compare(const string& self, rstring source) -> signed { + return memory::compare(self.data(), self.size(), source.data(), source.size()); +} + +auto icompare(const string& self, rstring source) -> signed { + return memory::icompare(self.data(), self.size(), source.data(), source.size()); +} + +auto equals(const string& self, rstring source) -> bool { + if(self.size() != source.size()) return false; + return memory::compare(self.data(), source.data(), source.size()) == 0; +} + +auto iequals(const string& self, rstring source) -> bool { + if(self.size() != source.size()) return false; + return memory::icompare(self.data(), source.data(), source.size()) == 0; +} + +auto beginsWith(const string& self, rstring source) -> bool { + if(source.size() > self.size()) return false; + return memory::compare(self.data(), source.data(), source.size()) == 0; +} + +auto ibeginsWith(const string& self, rstring source) -> bool { + if(source.size() > self.size()) return false; + return memory::icompare(self.data(), source.data(), source.size()) == 0; +} + +auto endsWith(const string& self, rstring source) -> bool { + if(source.size() > self.size()) return false; + return memory::compare(self.data() + self.size() - source.size(), source.data(), source.size()) == 0; +} + +auto iendsWith(const string& self, rstring source) -> bool { + if(source.size() > self.size()) return false; + return memory::icompare(self.data() + self.size() - source.size(), source.data(), source.size()) == 0; +} + +} + +#endif diff --git a/nall/string/convert.hpp b/nall/string/convert.hpp new file mode 100644 index 00000000..3ffb5a6d --- /dev/null +++ b/nall/string/convert.hpp @@ -0,0 +1,55 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +auto downcase(string& self) -> string& { + char* p = self.pointer(); + for(unsigned n = 0; n < self.size(); n++) { + if(p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20; + } + return self; +} + +auto qdowncase(string& self) -> string& { + char* p = self.pointer(); + for(unsigned n = 0, quoted = 0; n < self.size(); n++) { + if(p[n] == '\"') quoted ^= 1; + if(!quoted && p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20; + } + return self; +} + +auto upcase(string& self) -> string& { + char* p = self.pointer(); + for(unsigned n = 0; n < self.size(); n++) { + if(p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20; + } + return self; +} + +auto qupcase(string& self) -> string& { + char* p = self.pointer(); + for(unsigned n = 0, quoted = 0; n < self.size(); n++) { + if(p[n] == '\"') quoted ^= 1; + if(!quoted && p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20; + } + return self; +} + +auto transform(string& self, rstring from, rstring to) -> string& { + if(from.size() != to.size() || from.size() == 0) return self; //patterns must be the same length + char* p = self.pointer(); + for(unsigned n = 0; n < self.size(); n++) { + for(unsigned s = 0; s < from.size(); s++) { + if(p[n] == from[s]) { + p[n] = to[s]; + break; + } + } + } + return self; +} + +} + +#endif diff --git a/nall/string/core.hpp b/nall/string/core.hpp index 8a00645e..dee9bfd0 100644 --- a/nall/string/core.hpp +++ b/nall/string/core.hpp @@ -3,7 +3,9 @@ //only allocators may access _data or modify _size and _capacity //all other functions must use data(), size(), capacity() -#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE) +#if defined(NALL_STRING_ALLOCATOR_ADAPTIVE) + #include <nall/string/allocator/adaptive.hpp> +#elif defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE) #include <nall/string/allocator/copy-on-write.hpp> #elif defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION) #include <nall/string/allocator/small-string-optimization.hpp> @@ -13,75 +15,44 @@ namespace nall { -unsigned string::length() const { return strlen(data()); } -unsigned string::size() const { return _size; } -unsigned string::capacity() const { return _capacity; } -bool string::empty() const { return _size == 0; } - -void string::clear(char c) { - for(unsigned n = 0; n < size(); n++) data()[n] = c; -} - -unsigned string::hash() const { - const char* p = data(); - unsigned result = 5381; - while(*p) result = (result << 5) + result + *p++; - return result; -} - -template<typename... Args> string& string::assign(Args&&... args) { - resize(0); - sprint(*this, std::forward<Args>(args)...); - return *this; -} - -template<typename... Args> string& string::append(Args&&... args) { - sprint(*this, std::forward<Args>(args)...); - return *this; -} - -string& string::_append(const char* s) { - if(s == nullptr) return *this; - unsigned basesize = size(), length = strlen(s); - reserve(basesize + length); - memcpy(data() + basesize, s, length); - resize(basesize + length); - return *this; -} - -string::operator bool() const { - return !empty(); -} - -string::operator const char*() const { - return data(); -} - -char& string::operator[](signed position) { +auto string::operator[](signed position) const -> const char& { if(position > size() + 1) throw exception_out_of_bounds{}; return data()[position]; } -const char& string::operator[](signed position) const { - if(position > size() + 1) throw exception_out_of_bounds{}; - return data()[position]; +template<typename... P> auto assign(string& self, P&&... p) -> string& { + self.resize(0); + return self.append(std::forward<P>(p)...); } -bool string::operator==(const char* str) const { return strcmp(data(), str) == 0; } -bool string::operator!=(const char* str) const { return strcmp(data(), str) != 0; } -bool string::operator< (const char* str) const { return strcmp(data(), str) < 0; } -bool string::operator<=(const char* str) const { return strcmp(data(), str) <= 0; } -bool string::operator> (const char* str) const { return strcmp(data(), str) > 0; } -bool string::operator>=(const char* str) const { return strcmp(data(), str) >= 0; } - -string::string(const string& source) { - construct(); - operator=(source); +template<typename T, typename... P> auto append(string& self, const T& value, P&&... p) -> string& { + _append(self, make_string(value)); + return self.append(std::forward<P>(p)...); } -string::string(string&& source) { - construct(); - operator=(std::move(source)); +template<typename... P> auto append(string& self, const format& value, P&&... p) -> string& { + self.format(value); + return self.append(std::forward<P>(p)...); +} + +auto append(string& self) -> string& { + return self; +} + +template<typename T> auto _append(string& self, const stringify<T>& source) -> string& { + unsigned size = self.size(); + unsigned length = source.size(); + self.resize(size + length); + memory::copy(self.pointer() + size, source.data(), length); + return self; +} + +auto empty(const string& self) -> bool { + return self.size() == 0; +} + +auto length(const string& self) -> unsigned { + return strlen(self.data()); } } diff --git a/nall/string/datetime.hpp b/nall/string/datetime.hpp index b55659a1..bf27007c 100644 --- a/nall/string/datetime.hpp +++ b/nall/string/datetime.hpp @@ -2,28 +2,29 @@ namespace nall { -string string::date() { - time_t timestamp = ::time(nullptr); +auto string::date(time_t timestamp) -> string { + if(timestamp == 0) timestamp = ::time(nullptr); tm* info = localtime(×tamp); return { - format<4, '0'>(1900 + info->tm_year), "-", - format<2, '0'>(1 + info->tm_mon), "-", - format<2, '0'>(info->tm_mday) + nall::decimal<4>(1900 + info->tm_year), "-", + nall::decimal<2>(1 + info->tm_mon), "-", + nall::decimal<2>(info->tm_mday) }; } -string string::time() { - time_t timestamp = ::time(nullptr); +auto string::time(time_t timestamp) -> string { + if(timestamp == 0) timestamp = ::time(nullptr); tm* info = localtime(×tamp); return { - format<2, '0'>(info->tm_hour), ":", - format<2, '0'>(info->tm_min), ":", - format<2, '0'>(info->tm_sec) + nall::decimal<2>(info->tm_hour), ":", + nall::decimal<2>(info->tm_min), ":", + nall::decimal<2>(info->tm_sec) }; } -string string::datetime() { - return {string::date(), " ", string::time()}; +auto string::datetime(time_t timestamp) -> string { + if(timestamp == 0) timestamp = ::time(nullptr); + return {string::date(timestamp), " ", string::time(timestamp)}; } } diff --git a/nall/string/eval/evaluator.hpp b/nall/string/eval/evaluator.hpp index 8957a30c..5e77ff7f 100644 --- a/nall/string/eval/evaluator.hpp +++ b/nall/string/eval/evaluator.hpp @@ -29,7 +29,7 @@ inline string evaluateExpression(Node* node) { for(auto& link : node->link) { result.append(evaluateExpression(link), ", "); } - return result.rtrim<1>(", ").append(")"); + return result.rtrim(", ").append(")"); } } #undef p diff --git a/nall/string/file.hpp b/nall/string/file.hpp deleted file mode 100644 index 1b809c2f..00000000 --- a/nall/string/file.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -string string::read(const string& filename) { - string result; - - #if !defined(_WIN32) - FILE* fp = fopen(filename, "rb"); - #else - FILE* fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return result; - - fseek(fp, 0, SEEK_END); - unsigned fsize = ftell(fp); - rewind(fp); - char* fdata = new char[fsize + 1]; - unsigned unused = fread(fdata, 1, fsize, fp); - fclose(fp); - fdata[fsize] = 0; - result.resize(fsize); - memcpy(result.data(), fdata, fsize); - delete[] fdata; - - return result; -} - -} - -#endif diff --git a/nall/string/filename.hpp b/nall/string/filename.hpp deleted file mode 100644 index d748a8ba..00000000 --- a/nall/string/filename.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -// "/foo/bar.c" -> "/foo/" -// "/foo/" -> "/foo/" -// "bar.c" -> "./" -string dir(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name.resize(i + 1); - break; - } - if(i == 0) name = "./"; - } - return name; -} - -// "/foo/bar.c" -> "bar.c" -// "/foo/" -> "" -// "bar.c" -> "bar.c" -string notdir(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - return (const char*)name + i + 1; - } - } - return name; -} - -// "/foo/bar/baz" -> "/foo/bar/" -// "/foo/bar/" -> "/foo/" -// "/foo/bar" -> "/foo/" -string parentdir(string name) { - unsigned length = name.length(), paths = 0, prev, last; - for(unsigned i = 0; i < length; i++) { - if(name[i] == '/' || name[i] == '\\') { - paths++; - prev = last; - last = i; - } - } - if(last + 1 == length) last = prev; //if name ends in slash; use previous slash - if(paths > 1) name.resize(last + 1); - return name; -} - -// "/foo/bar.c" -> "/foo/bar" -string basename(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') break; //file has no extension - if(name[i] == '.') { - name.resize(i); - break; - } - } - return name; -} - -// "/foo/bar.c" -> "c" -// "/foo/bar" -> "" -string extension(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') return ""; //file has no extension - if(name[i] == '.') { - return (const char*)name + i + 1; - } - } - return name; -} - -string tempname() { - string path = temppath(); - srand(time(nullptr)); - while(true) { - uint32_t seed = rand(); - string filename = {path, ".temporary-", hex<8>(seed)}; - if(access(filename, F_OK) != 0) return filename; - } -} - -} - -#endif diff --git a/nall/string/find.hpp b/nall/string/find.hpp new file mode 100644 index 00000000..5886b3d3 --- /dev/null +++ b/nall/string/find.hpp @@ -0,0 +1,30 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +template<bool Insensitive, bool Quoted> auto _find(const string& self, signed offset, rstring source) -> maybe<unsigned> { + if(source.size() == 0) return nothing; + + const char* p = self.data(); + unsigned size = self.size(); + + for(unsigned n = offset, quoted = 0; n < size;) { + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } + if(_compare<Insensitive>(p + n, size - n, source.data(), source.size())) { n++; continue; } + return n - offset; + } + + return nothing; +} + +auto find(const string& self, rstring source) -> maybe<unsigned> { return _find<0, 0>(self, 0, source); } +auto ifind(const string& self, rstring source) -> maybe<unsigned> { return _find<1, 0>(self, 0, source); } +auto qfind(const string& self, rstring source) -> maybe<unsigned> { return _find<0, 1>(self, 0, source); } +auto iqfind(const string& self, rstring source) -> maybe<unsigned> { return _find<1, 1>(self, 0, source); } + +auto findFrom(const string& self, signed offset, rstring source) -> maybe<unsigned> { return _find<0, 0>(self, offset, source); } +auto ifindFrom(const string& self, signed offset, rstring source) -> maybe<unsigned> { return _find<1, 0>(self, offset, source); } + +} + +#endif diff --git a/nall/string/format.hpp b/nall/string/format.hpp index 98c0c5b7..827850c5 100644 --- a/nall/string/format.hpp +++ b/nall/string/format.hpp @@ -2,69 +2,176 @@ namespace nall { -template<signed precision, char padchar> string format(const string& value) { - if(precision == 0) return value; +//nall::format is a vector<string> of parameters that can be applied to a string +//each {#} token will be replaced with its appropriate format parameter - bool padright = precision >= 0; - unsigned padding = abs(precision); +auto string::format(const nall::format& params) -> type& { + signed size = this->size(); + char* data = (char*)memory::allocate(size); + memory::copy(data, this->data(), size); - if(padding <= value.size()) { - if(padright) return substr(value, value.size() - padding); - else return substr(value, 0, padding); + signed x = 0; + while(x < size - 2) { //2 = minimum tag length + if(data[x] != '{') { x++; continue; } + + signed y = x + 1; + while(y < size - 1) { //-1 avoids going out of bounds on test after this loop + if(data[y] != '}') { y++; continue; } + break; + } + + if(data[y++] != '}') { x++; continue; } + + static auto isNumeric = [](char* s, char* e) -> bool { + if(s == e) return false; //ignore empty tags: {} + while(s < e) { + if(*s >= '0' && *s <= '9') { s++; continue; } + return false; + } + return true; + }; + if(!isNumeric(&data[x + 1], &data[y - 1])) { x++; continue; } + + unsigned index = nall::decimal(&data[x + 1]); + if(index >= params.size()) { x++; continue; } + + unsigned sourceSize = y - x; + unsigned targetSize = params[index].size(); + unsigned remaining = size - x; + + if(sourceSize > targetSize) { + unsigned difference = sourceSize - targetSize; + memory::move(&data[x], &data[x + difference], remaining); + size -= difference; + } else if(targetSize > sourceSize) { + unsigned difference = targetSize - sourceSize; + data = (char*)realloc(data, size + difference); + size += difference; + memory::move(&data[x + difference], &data[x], remaining); + } + memory::copy(&data[x], params[index].data(), targetSize); + x += targetSize; } - string buffer; - buffer.resize(padding); - buffer.clear(padchar); + resize(size); + memory::copy(pointer(), data, size); + memory::free(data); + return *this; +} - memcpy(buffer.data() + (padright ? padding - value.size() : 0), value, value.size()); +template<typename T, typename... P> auto append(format& self, const T& value, P&&... p) -> format& { + self.vector<string>::append(value); + append(self, std::forward<P>(p)...); +} + +auto append(format& self) -> format& { + return self; +} + +template<typename... P> auto print(P&&... p) -> void { + string s{std::forward<P>(p)...}; + fputs(s.data(), stdout); +} + +template<signed precision, char padchar> auto integer(intmax_t value) -> string { + string buffer; + buffer.resize(1 + sizeof(intmax_t) * 3); + char* p = buffer.pointer(); + + bool negative = value < 0; + value = abs(value); + unsigned size = 0; + do { + p[size++] = '0' + (value % 10); + value /= 10; + } while(value); + if(negative) p[size++] = '-'; + buffer.resize(size); + buffer.reverse(); + if(precision) buffer.size(precision, padchar); return buffer; } -template<signed precision, char padchar> string hex(uintmax_t value) { +template<signed precision, char padchar> auto decimal(uintmax_t value) -> string { + string buffer; + buffer.resize(sizeof(uintmax_t) * 3); + char* p = buffer.pointer(); + + unsigned size = 0; + do { + p[size++] = '0' + (value % 10); + value /= 10; + } while(value); + buffer.resize(size); + buffer.reverse(); + if(precision) buffer.size(precision, padchar); + return buffer; +} + +template<signed precision, char padchar> auto hex(uintmax_t value) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 2); + char* p = buffer.pointer(); unsigned size = 0; do { unsigned n = value & 15; - buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; + p[size++] = n < 10 ? '0' + n : 'a' + n - 10; value >>= 4; } while(value); buffer.resize(size); buffer.reverse(); - - return format<precision, padchar>(buffer); + if(precision) buffer.size(precision, padchar); + return buffer; } -template<signed precision, char padchar> string octal(uintmax_t value) { +template<signed precision, char padchar> auto octal(uintmax_t value) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 3); + char* p = buffer.pointer(); unsigned size = 0; do { - buffer[size++] = '0' + (value & 7); + p[size++] = '0' + (value & 7); value >>= 3; } while(value); buffer.resize(size); buffer.reverse(); - - return format<precision, padchar>(buffer); + if(precision) buffer.size(precision, padchar); + return buffer; } -template<signed precision, char padchar> string binary(uintmax_t value) { +template<signed precision, char padchar> auto binary(uintmax_t value) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 8); + char* p = buffer.pointer(); unsigned size = 0; do { - buffer[size++] = '0' + (value & 1); + p[size++] = '0' + (value & 1); value >>= 1; } while(value); buffer.resize(size); buffer.reverse(); + if(precision) buffer.size(precision, padchar); + return buffer; +} - return format<precision, padchar>(buffer); +template<signed precision, typename T> auto pointer(const T* value) -> string { + if(value == nullptr) return "(null)"; + return {"0x", hex<precision>((uintptr_t)value)}; +} + +template<signed precision> auto pointer(uintptr_t value) -> string { + if(value == 0) return "(null)"; + return {"0x", hex<precision>(value)}; +} + +auto real(long double value) -> string { + string temp; + temp.resize(real(nullptr, value)); + real(temp.pointer(), value); + return temp; } } diff --git a/nall/string/hash.hpp b/nall/string/hash.hpp new file mode 100644 index 00000000..98084ec4 --- /dev/null +++ b/nall/string/hash.hpp @@ -0,0 +1,35 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +namespace Hash { + auto CRC16::digest() -> string { + return hex<4>(value()); + } + + auto CRC32::digest() -> string { + return hex<8>(value()); + } + + auto SHA256::digest() const -> string { + string result; + for(auto n : value()) result.append(hex<2>(n)); + return result; + } +} + +auto crc16(const string& self) -> string { + return Hash::CRC16(self.data(), self.size()).digest(); +} + +auto crc32(const string& self) -> string { + return Hash::CRC32(self.data(), self.size()).digest(); +} + +auto sha256(const string& self) -> string { + return Hash::SHA256(self.data(), self.size()).digest(); +} + +} + +#endif diff --git a/nall/string/list.hpp b/nall/string/list.hpp index 55b2e76e..6b9f4f78 100644 --- a/nall/string/list.hpp +++ b/nall/string/list.hpp @@ -2,42 +2,7 @@ namespace nall { -maybe<unsigned> lstring::find(rstring key) const { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return i; - } - return nothing; -} - -string lstring::merge(const string& separator) const { - string output; - for(unsigned i = 0; i < size(); i++) { - output.append(operator[](i)); - if(i < size() - 1) output.append(separator); - } - return output; -} - -lstring& lstring::isort() { - nall::sort(pool, objectsize, [](const string& x, const string& y) { - return istrcmp(x, y) < 0; - }); - return *this; -} - -lstring& lstring::strip() { - for(unsigned n = 0; n < size(); n++) { - operator[](n).strip(); - } - return *this; -} - -template<typename... Args> void lstring::append(const string& data, Args&&... args) { - vector::append(data); - append(std::forward<Args>(args)...); -} - -bool lstring::operator==(const lstring& source) const { +auto lstring::operator==(const lstring& source) const -> bool { if(this == &source) return true; if(size() != source.size()) return false; for(unsigned n = 0; n < size(); n++) { @@ -46,39 +11,55 @@ bool lstring::operator==(const lstring& source) const { return true; } -bool lstring::operator!=(const lstring& source) const { +auto lstring::operator!=(const lstring& source) const -> bool { return !operator==(source); } -lstring& lstring::operator=(const lstring& source) { - vector::operator=(source); +auto lstring::isort() -> lstring& { + nall::sort(pool, objectsize, [](const string& x, const string& y) { + return memory::icompare(x.data(), x.size(), y.data(), y.size()) < 0; + }); return *this; } -lstring& lstring::operator=(lstring& source) { - vector::operator=(source); - return *this; +template<typename... P> auto append(lstring& self, const string& data, P&&... p) -> lstring& { + self.vector::append(data); + append(self, std::forward<P>(p)...); + return self; } -lstring& lstring::operator=(lstring&& source) { - vector::operator=(std::move(source)); - return *this; +auto append(lstring& self) -> lstring& { + return self; } -template<typename... Args> lstring::lstring(Args&&... args) { - append(std::forward<Args>(args)...); +auto find(const lstring& self, const string& source) -> maybe<unsigned> { + for(unsigned n = 0; n < self.size(); n++) { + if(self[n].equals(source)) return n; + } + return nothing; } -lstring::lstring(const lstring& source) { - vector::operator=(source); +auto ifind(const lstring& self, const string& source) -> maybe<unsigned> { + for(unsigned n = 0; n < self.size(); n++) { + if(self[n].iequals(source)) return n; + } + return nothing; } -lstring::lstring(lstring& source) { - vector::operator=(source); +auto merge(const lstring& self, const string& separator) -> string { + string output; + for(unsigned n = 0; n < self.size(); n++) { + output.append(self[n]); + if(n < self.size() - 1) output.append(separator); + } + return output; } -lstring::lstring(lstring&& source) { - vector::operator=(std::move(source)); +auto strip(lstring& self) -> lstring& { + for(unsigned n = 0; n < self.size(); n++) { + self[n].strip(); + } + return self; } } diff --git a/nall/string/markup/bml.hpp b/nall/string/markup/bml.hpp index 6743a80e..7f5e8252 100644 --- a/nall/string/markup/bml.hpp +++ b/nall/string/markup/bml.hpp @@ -71,7 +71,7 @@ protected: if(length == 0) throw "Invalid attribute name"; node.name = substr(p, 0, length); node.parseData(p += length); - node.data.rtrim<1>("\n"); + node.data.rtrim("\n"); children.append(node); } } @@ -98,7 +98,7 @@ protected: children.append(node); } - data.rtrim<1>("\n"); + data.rtrim("\n"); } //read top-level nodes diff --git a/nall/string/markup/node.hpp b/nall/string/markup/node.hpp index ff7ea3d6..fbf2ae46 100644 --- a/nall/string/markup/node.hpp +++ b/nall/string/markup/node.hpp @@ -20,6 +20,10 @@ struct Node { return string{data}.strip(); } + bool boolean() const { + return text() != "false"; + } + intmax_t integer() const { return numeral(text()); } @@ -93,7 +97,7 @@ struct Node { if(name.match("*[*]")) { lstring side = name.split<1>("["); name = side(0); - side = side(1).rtrim<1>("]").split<1>("-"); + side = side(1).rtrim("]").split<1>("-"); lo = side(0).empty() ? 0u : numeral(side(0)); hi = side(1).empty() ? ~0u : numeral(side(1)); } @@ -101,7 +105,7 @@ struct Node { if(name.match("*(*)")) { lstring side = name.split<1>("("); name = side(0); - rule = side(1).rtrim<1>(")"); + rule = side(1).rtrim(")"); } unsigned position = 0; diff --git a/nall/string/markup/xml.hpp b/nall/string/markup/xml.hpp index 6debcc37..fd9fe787 100644 --- a/nall/string/markup/xml.hpp +++ b/nall/string/markup/xml.hpp @@ -39,34 +39,34 @@ protected: target.reserve(length + 1); #if defined(NALL_XML_LITERAL) - memcpy(target(), source, length); + memory::copy(target.pointer(), source, length); target[length] = 0; return; #endif - char* output = target.data(); + char* output = target.pointer(); while(length) { if(*source == '&') { - if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } - if(!memcmp(source, ">", 4)) { *output++ = '>'; source += 4; length -= 4; continue; } - if(!memcmp(source, "&", 5)) { *output++ = '&'; source += 5; length -= 5; continue; } - if(!memcmp(source, "'", 6)) { *output++ = '\''; source += 6; length -= 6; continue; } - if(!memcmp(source, """, 6)) { *output++ = '\"'; source += 6; length -= 6; continue; } + if(!memory::compare(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } + if(!memory::compare(source, ">", 4)) { *output++ = '>'; source += 4; length -= 4; continue; } + if(!memory::compare(source, "&", 5)) { *output++ = '&'; source += 5; length -= 5; continue; } + if(!memory::compare(source, "'", 6)) { *output++ = '\''; source += 6; length -= 6; continue; } + if(!memory::compare(source, """, 6)) { *output++ = '\"'; source += 6; length -= 6; continue; } } if(attribute == false && source[0] == '<' && source[1] == '!') { //comment - if(!memcmp(source, "<!--", 4)) { + if(!memory::compare(source, "<!--", 4)) { source += 4, length -= 4; - while(memcmp(source, "-->", 3)) source++, length--; + while(memory::compare(source, "-->", 3)) source++, length--; source += 3, length -= 3; continue; } //CDATA - if(!memcmp(source, "<![CDATA[", 9)) { + if(!memory::compare(source, "<![CDATA[", 9)) { source += 9, length -= 9; - while(memcmp(source, "]]>", 3)) *output++ = *source++, length--; + while(memory::compare(source, "]]>", 3)) *output++ = *source++, length--; source += 3, length -= 3; continue; } @@ -81,23 +81,23 @@ protected: if(*(p + 1) != '!') return false; //comment - if(!memcmp(p, "<!--", 4)) { - while(*p && memcmp(p, "-->", 3)) p++; + if(!memory::compare(p, "<!--", 4)) { + while(*p && memory::compare(p, "-->", 3)) p++; if(!*p) throw "unclosed comment"; p += 3; return true; } //CDATA - if(!memcmp(p, "<![CDATA[", 9)) { - while(*p && memcmp(p, "]]>", 3)) p++; + if(!memory::compare(p, "<![CDATA[", 9)) { + while(*p && memory::compare(p, "]]>", 3)) p++; if(!*p) throw "unclosed CDATA"; p += 3; return true; } //DOCTYPE - if(!memcmp(p, "<!DOCTYPE", 9)) { + if(!memory::compare(p, "<!DOCTYPE", 9)) { unsigned counter = 0; do { char n = *p++; @@ -171,7 +171,7 @@ protected: while(*p && *p != '>') p++; if(*p != '>') throw "unclosed closure element"; const char* nameEnd = p++; - if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch"; + if(memory::compare(name.data(), nameStart, nameEnd - nameStart)) throw "closure element name mismatch"; return true; } diff --git a/nall/string/char/match.hpp b/nall/string/match.hpp similarity index 55% rename from nall/string/char/match.hpp rename to nall/string/match.hpp index 2471d1ce..3cff8b8a 100644 --- a/nall/string/char/match.hpp +++ b/nall/string/match.hpp @@ -2,7 +2,12 @@ namespace nall { -bool strmatch(const char* s, const char* p) { +//todo: these functions are not binary-safe + +auto match(const string& self, rstring source) -> bool { + const char* s = self.data(); + const char* p = source.data(); + const char* cp = nullptr; const char* mp = nullptr; while(*s && *p != '*') { @@ -23,7 +28,14 @@ bool strmatch(const char* s, const char* p) { return !*p; } -bool istrmatch(const char* s, const char* p) { +auto imatch(const string& self, rstring source) -> bool { + static auto chrlower = [](char c) -> char { + return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; + }; + + const char* s = self.data(); + const char* p = source.data(); + const char* cp = nullptr; const char* mp = nullptr; while(*s && *p != '*') { @@ -44,7 +56,7 @@ bool istrmatch(const char* s, const char* p) { return !*p; } -bool tokenize(const char* s, const char* p) { +inline bool tokenize(const char* s, const char* p) { while(*s) { if(*p == '*') { while(*s) if(tokenize(s++, p + 1)) return true; @@ -56,6 +68,25 @@ bool tokenize(const char* s, const char* p) { return !*p; } +auto tokenize(lstring& list, const char* s, const char* p) -> bool { + while(*s) { + if(*p == '*') { + const char* b = s; + while(*s) { + if(tokenize(list, s++, p + 1)) { + list.prepend(substr(b, 0, --s - b)); + return true; + } + } + list.prepend(b); + return !*++p; + } + if(*s++ != *p++) return false; + } + while(*p == '*') { list.prepend(s); p++; } + return !*p; +} + } #endif diff --git a/nall/string/path.hpp b/nall/string/path.hpp new file mode 100644 index 00000000..5ef4b7be --- /dev/null +++ b/nall/string/path.hpp @@ -0,0 +1,73 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +// (/parent/child.type/) +// (/parent/child.type/)name.type +auto pathname(const string& self) -> string { + const char* p = self.data() + self.size() - 1; + for(signed offset = self.size() - 1; offset >= 0; offset--, p--) { + if(*p == '/') return slice(self, 0, offset + 1); + } + return ""; +} + +// /parent/child.type/() +// /parent/child.type/(name.type) +auto filename(const string& self) -> string { + const char* p = self.data() + self.size() - 1; + for(signed offset = self.size() - 1; offset >= 0; offset--, p--) { + if(*p == '/') return slice(self, offset + 1); + } + return ""; +} + +// (/parent/)child.type/ +// (/parent/child.type/)name.type +auto dirname(const string& self) -> string { + const char* p = self.data() + self.size() - 1, *last = p; + for(signed offset = self.size() - 1; offset >= 0; offset--, p--) { + if(*p == '/' && p == last) continue; + if(*p == '/') return slice(self, 0, offset + 1); + } + return self; //this is the root directory +} + +// /parent/(child.type/) +// /parent/child.type/(name.type) +auto basename(const string& self) -> string { + const char* p = self.data() + self.size() - 1, *last = p; + for(signed offset = self.size() - 1; offset >= 0; offset--, p--) { + if(*p == '/' && p == last) continue; + if(*p == '/') return slice(self, offset + 1); + } + return ""; +} + +// /parent/(child).type/ +// /parent/child.type/(name).type +auto prefixname(const string& self) -> string { + const char* p = self.data() + self.size() - 1, *last = p; + for(signed offset = self.size() - 1, suffix = 0; offset >= 0; offset--, p--) { + if(*p == '/' && p == last) continue; + if(*p == '/') return slice(self, offset + 1, suffix ? suffix - offset - 1 : 0).rtrim("/"); + if(*p == '.' && suffix == 0) suffix = offset; + } + return ""; +} + +// /parent/child(.type)/ +// /parent/child.type/name(.type) +auto suffixname(const string& self) -> string { + const char* p = self.data() + self.size() - 1, *last = p; + for(signed offset = self.size() - 1; offset >= 0; offset--, p--) { + if(*p == '/' && p == last) continue; + if(*p == '/') break; + if(*p == '.') return slice(self, offset).rtrim("/"); + } + return ""; +} + +} + +#endif diff --git a/nall/string/platform.hpp b/nall/string/platform.hpp index d80060f3..f78de306 100644 --- a/nall/string/platform.hpp +++ b/nall/string/platform.hpp @@ -2,7 +2,7 @@ namespace nall { -string activepath() { +auto activepath() -> string { char path[PATH_MAX] = ""; auto unused = getcwd(path, PATH_MAX); string result = path; @@ -12,17 +12,17 @@ string activepath() { return result; } -string realpath(const string& name) { +auto realpath(rstring name) -> string { string result; char path[PATH_MAX] = ""; - if(::realpath(name, path)) result = dir(path); + if(::realpath(name, path)) result = string{path}.pathname(); if(result.empty()) result = activepath(); result.transform("\\", "/"); if(result.endsWith("/") == false) result.append("/"); return result; } -string programpath() { +auto programpath() -> string { #if defined(PLATFORM_WINDOWS) int argc = 0; wchar_t** argv = CommandLineToArgvW(GetCommandLine(), &argc); @@ -38,7 +38,7 @@ string programpath() { // /home/username/ // c:/users/username/ -string userpath() { +auto userpath() -> string { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path); @@ -55,7 +55,7 @@ string userpath() { // /home/username/.config/ // c:/users/username/appdata/roaming/ -string configpath() { +auto configpath() -> string { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); @@ -74,7 +74,7 @@ string configpath() { // /usr/share // /Library/Application Support/ // c:/ProgramData/ -string sharedpath() { +auto sharedpath() -> string { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); @@ -92,7 +92,7 @@ string sharedpath() { // /tmp // c:/users/username/AppData/Local/Temp/ -string temppath() { +auto temppath() -> string { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; GetTempPathW(PATH_MAX, path); diff --git a/nall/string/ref.hpp b/nall/string/ref.hpp index 19200891..2c07dbbb 100644 --- a/nall/string/ref.hpp +++ b/nall/string/ref.hpp @@ -7,37 +7,54 @@ struct stringref { return _data; } - const char* data() const { + auto data() const -> const char* { return _data; } - unsigned size() const { - if(!_initialized) { - _initialized = true; - _size = strlen(_data); - } + auto size() const -> unsigned { + if(!_initialized) _size = strlen(_data), _initialized = true; return _size; } - stringref() = delete; - stringref(const stringref& source) = delete; - stringref(stringref&& source) = delete; + stringref() { + _string = nullptr; + _data = ""; + _size = 0; + _initialized = true; + } stringref(const char* source) { + _string = nullptr; _data = source; _initialized = false; } stringref(const string& source) { + _string = nullptr; _data = source.data(); _size = source.size(); _initialized = true; } + template<typename... P> stringref(P&&... p) { + _string = new string{std::forward<P>(p)...}; + _data = _string->data(); + _size = _string->size(); + _initialized = true; + } + + ~stringref() { + if(_string) delete _string; + } + + stringref(const stringref& source) = delete; + stringref(stringref&& source) = delete; + protected: + string* _string; const char* _data; - mutable unsigned _size; - mutable bool _initialized; + mutable signed _size; + mutable unsigned _initialized; }; } diff --git a/nall/string/replace.hpp b/nall/string/replace.hpp index 65af7be3..f27b06ad 100644 --- a/nall/string/replace.hpp +++ b/nall/string/replace.hpp @@ -3,52 +3,93 @@ namespace nall { template<unsigned Limit, bool Insensitive, bool Quoted> -string& string::ureplace(rstring key, rstring token) { - if(key.size() == 0) return *this; - enum : unsigned { limit = Limit ? Limit : ~0u }; +auto _replace(string& self, rstring from, rstring to) -> string& { + if(Limit == 0 || from.size() == 0) return self; - const char* p = data(); - unsigned counter = 0; + signed size = self.size(); + signed matches = 0; + signed quoted = 0; - while(*p) { - if(quoteskip<Quoted>(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter++; p += n; break; } - if(!chrequal<Insensitive>(key[n], p[n])) { p++; break; } + //count matches first, so that we only need to reallocate memory once + //(recording matches would also require memory allocation, so this is not done) + { const char* p = self.data(); + for(signed n = 0; n <= size - (signed)from.size();) { + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } + if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; } + + if(++matches >= Limit) break; + n += from.size(); } } - if(counter == 0) return *this; - if(Limit) counter = min(counter, Limit); + if(matches == 0) return self; - char* t = data(); - char* base = nullptr; - signed displacement = token.size() - key.size(); - signed displacementSize = displacement * counter; + //in-place overwrite + if(to.size() == from.size()) { + char* p = self.pointer(); - if(token.size() > key.size()) { - t = base = strduplicate(data()); - reserve((unsigned)(p - data()) + displacementSize); - } - char* o = data(); + for(signed n = 0, remaining = matches, quoted = 0; n <= size - (signed)from.size();) { + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } + if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; } - while(*t && counter) { - if(quotecopy<Quoted>(o, t)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter--; memcpy(o, token, token.size()); t += key.size(); o += token.size(); break; } - if(!chrequal<Insensitive>(key[n], t[n])) { *o++ = *t++; break; } + memory::copy(p + n, to.data(), to.size()); + + if(!--remaining) break; + n += from.size(); } } - do *o++ = *t; while(*t++); - if(base) free(base); - resize(_size + displacementSize); - return *this; + //left-to-right shrink + else if(to.size() < from.size()) { + char* p = self.pointer(); + signed offset = 0; + signed base = 0; + + for(signed n = 0, remaining = matches, quoted = 0; n <= size - (signed)from.size();) { + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } + if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; } + + if(offset) memory::move(p + offset, p + base, n - base); + memory::copy(p + offset + (n - base), to.data(), to.size()); + offset += (n - base) + to.size(); + + n += from.size(); + base = n; + if(!--remaining) break; + } + + memory::move(p + offset, p + base, size - base); + self.resize(size - matches * (from.size() - to.size())); + } + + //right-to-left expand + else if(to.size() > from.size()) { + self.resize(size + matches * (to.size() - from.size())); + char* p = self.pointer(); + + signed offset = self.size(); + signed base = size; + + for(signed n = size, remaining = matches; n >= (signed)from.size();) { //quoted reused from parent scope since we are iterating backward + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n--; continue; } if(quoted) { n--; continue; } } + if(_compare<Insensitive>(p + n - from.size(), size - n + from.size(), from.data(), from.size())) { n--; continue; } + + memory::move(p + offset - (base - n), p + base - (base - n), base - n); + memory::copy(p + offset - (base - n) - to.size(), to.data(), to.size()); + offset -= (base - n) + to.size(); + + if(!--remaining) break; + n -= from.size(); + base = n; + } + } + + return self; } -template<unsigned Limit> string& string::replace(rstring key, rstring token) { return ureplace<Limit, false, false>(key, token); } -template<unsigned Limit> string& string::ireplace(rstring key, rstring token) { return ureplace<Limit, true, false>(key, token); } -template<unsigned Limit> string& string::qreplace(rstring key, rstring token) { return ureplace<Limit, false, true>(key, token); } -template<unsigned Limit> string& string::iqreplace(rstring key, rstring token) { return ureplace<Limit, true, true>(key, token); } +template<unsigned L> auto replace(string& self, rstring from, rstring to) -> string& { return _replace<L, 0, 0>(self, from, to); } +template<unsigned L> auto ireplace(string& self, rstring from, rstring to) -> string& { return _replace<L, 1, 0>(self, from, to); } +template<unsigned L> auto qreplace(string& self, rstring from, rstring to) -> string& { return _replace<L, 0, 1>(self, from, to); } +template<unsigned L> auto iqreplace(string& self, rstring from, rstring to) -> string& { return _replace<L, 1, 1>(self, from, to); } }; diff --git a/nall/string/split.hpp b/nall/string/split.hpp index 90521e1f..f5c5e516 100644 --- a/nall/string/split.hpp +++ b/nall/string/split.hpp @@ -2,36 +2,46 @@ namespace nall { -template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit(rstring key, rstring base) { - reset(); - if(key.size() == 0) return *this; +template<unsigned Limit, bool Insensitive, bool Quoted> auto _split(lstring& self, rstring source, rstring find) -> lstring& { + self.reset(); + if(find.size() == 0) return self; - const char* b = base; - const char* p = base; + const char* p = source.data(); + signed size = source.size(); + signed base = 0; + signed matches = 0; - while(*p) { - if(Limit) if(size() >= Limit) break; - if(quoteskip<Quoted>(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { - append(substr(b, 0, p - b)); - p += n; - b = p; - break; - } - if(!chrequal<Insensitive>(key[n], p[n])) { p++; break; } - } + for(signed n = 0, quoted = 0; n <= size - (signed)find.size();) { + if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } + if(_compare<Insensitive>(p + n, size - n, find.data(), find.size())) { n++; continue; } + if(matches >= Limit) break; + + string& s = self(matches); + s.resize(n - base); + memory::copy(s.pointer(), p + base, n - base); + + n += find.size(); + base = n; + matches++; } - append(b); - return *this; + string& s = self(matches); + s.resize(size - base); + memory::copy(s.pointer(), p + base, size - base); + + return self; } -template<unsigned Limit> lstring& lstring::split(rstring key, rstring src) { return usplit<Limit, false, false>(key, src); } -template<unsigned Limit> lstring& lstring::isplit(rstring key, rstring src) { return usplit<Limit, true, false>(key, src); } -template<unsigned Limit> lstring& lstring::qsplit(rstring key, rstring src) { return usplit<Limit, false, true>(key, src); } -template<unsigned Limit> lstring& lstring::iqsplit(rstring key, rstring src) { return usplit<Limit, true, true>(key, src); } +template<unsigned L> auto split(string& self, rstring on) -> lstring { return lstring().split<L>(self, on); } +template<unsigned L> auto isplit(string& self, rstring on) -> lstring { return lstring().isplit<L>(self, on); } +template<unsigned L> auto qsplit(string& self, rstring on) -> lstring { return lstring().qsplit<L>(self, on); } +template<unsigned L> auto iqsplit(string& self, rstring on) -> lstring { return lstring().iqsplit<L>(self, on); } -}; +template<unsigned L> auto string::split(rstring on) const -> lstring { return lstring().split<L>(*this, on); } +template<unsigned L> auto string::isplit(rstring on) const -> lstring { return lstring().isplit<L>(*this, on); } +template<unsigned L> auto string::qsplit(rstring on) const -> lstring { return lstring().qsplit<L>(*this, on); } +template<unsigned L> auto string::iqsplit(rstring on) const -> lstring { return lstring().iqsplit<L>(*this, on); } + +} #endif diff --git a/nall/string/transform/cml.hpp b/nall/string/transform/cml.hpp new file mode 100644 index 00000000..17a1b266 --- /dev/null +++ b/nall/string/transform/cml.hpp @@ -0,0 +1,93 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +/* CSS Markup Language (CML) v1.0 parser + * revision 0.01 + */ + +namespace nall { namespace { + +struct CML { + CML(const string& filedata, const string& pathname); + CML(const string& filename); + auto output() -> string; + +private: + struct State { + string output; + } state; + + struct Variable { + string name; + string value; + }; + vector<Variable> variables; + + auto parse(const string& filedata, const string& pathname) -> bool; +}; + +CML::CML(const string& filedata, const string& pathname) { + parse(filedata, pathname); +} + +CML::CML(const string& filename) { + parse(string::read(filename), filename.pathname()); +} + +auto CML::output() -> string { + return state.output; +} + +auto CML::parse(const string& filedata, const string& pathname) -> bool { + auto vendorAppend = [&](const string& name, const string& value) { + state.output.append(" -moz-", name, ": ", value, ";\n"); + state.output.append(" -webkit-", name, ": ", value, ";\n"); + }; + + for(auto& block : filedata.split("\n\n")) { + lstring lines = block.rstrip().split("\n"); + string name = lines.takeFirst(); + + if(ltrim(name, "include ")) { + string filename{pathname, name}; + parse(string::read(filename), filename.pathname()); + continue; + } + + if(name == "variables") { + for(auto& line : lines) { + auto data = line.split<1>(":").strip(); + variables.append({data(0), data(1)}); + } + continue; + } + + state.output.append(name, " {\n"); + for(auto& line : lines) { + auto data = line.split<1>(":").strip(); + auto name = data(0), value = data(1); + while(auto offset = value.find("var(")) { + bool found = false; + if(auto length = value.findFrom(*offset, ")")) { + string name = value.slice(*offset + 4, *length - 4); + for(auto& variable : variables) { + if(variable.name == name) { + value = {value.slice(0, *offset), variable.value, value.slice(*offset + *length + 1)}; + found = true; + break; + } + } + } + if(!found) break; + } + state.output.append(" ", name, ": ", value, ";\n"); + if(name == "box-sizing") vendorAppend(name, value); + } + state.output.append("}\n\n"); + } + + return true; +} + +}} + +#endif diff --git a/nall/string/transform/dml.hpp b/nall/string/transform/dml.hpp new file mode 100644 index 00000000..0c5e94d5 --- /dev/null +++ b/nall/string/transform/dml.hpp @@ -0,0 +1,259 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +/* Document Markup Language (DML) v1.0 parser + * revision 0.01 + */ + +namespace nall { namespace { + +struct DML { + struct Settings { + bool allowHTML = true; + bool sectioned = true; + } settings; + + DML(const string& filedata, const string& pathname); + DML(const string& filename); + auto output() -> string; + +private: + struct State { + string output; + unsigned sections = 0; + } state; + + auto parse(const string& filedata, const string& pathname) -> bool; + auto parseBlock(string& block, const string& pathname) -> bool; + auto count(const string& text, char value) -> unsigned; + auto escape(const string& text) -> string; + auto markup(const string& text) -> string; +}; + +DML::DML(const string& filedata, const string& pathname) { + parse(filedata, pathname); +} + +DML::DML(const string& filename) { + parse(string::read(filename), filename.pathname()); +} + +auto DML::output() -> string { + return state.output; +} + +auto DML::parse(const string& filedata, const string& pathname) -> bool { + auto blocks = filedata.split("\n\n"); + for(auto& block : blocks) parseBlock(block, pathname); + if(settings.sectioned && state.sections) state.output.append("</section>\n"); + return true; +} + +auto DML::parseBlock(string& block, const string& pathname) -> bool { + if(block.rstrip().empty()) return true; + auto lines = block.split("\n"); + + //include + if(block.beginsWith("{{include}}")) { + string filename{pathname, block.ltrim("{{include}}").strip()}; + parse(string::read(filename), filename.pathname()); + } + + //html + else if(ltrim(block, "{{html}}") && settings.allowHTML) { + auto data = lines.takeFirst(); + if(ltrim(data, "{{html}} ")) state.output.append(data, "\n"); + for(auto& line : lines) { + if(ltrim(line, " ")) state.output.append(line, "\n"); + } + } + + //header + else if(block.beginsWith("# ")) { + if(settings.sectioned) { + if(state.sections++) state.output.append("</section>"); + state.output.append("<section>"); + } + auto content = lines.takeFirst().ltrim("# ").split<1>(" => "); + auto data = markup(content[0]); + auto name = escape(content(1, data.crc32())); + state.output.append("<header id=\"", name, "\">", data); + for(auto& line : lines) { + if(!line.beginsWith("# ")) continue; + state.output.append("<span>", line.ltrim("# "), "</span>"); + } + state.output.append("</header>\n"); + } + + //subheader + else if(auto depth = count(block, '=')) { + auto content = lines.takeFirst().slice(depth + 1).split<1>(" => "); + auto data = markup(content[0]); + auto name = escape(content(1, data.crc32())); + if(depth <= 6) { + state.output.append("<h", depth, " id=\"", name, "\">", data); + for(auto& line : lines) { + if(count(line, '=') != depth) continue; + state.output.append("<span>", line.slice(depth + 1), "</span>"); + } + state.output.append("</h", depth, ">\n"); + } + } + + //contents + else if(count(block, '-')) { + state.output.append("<nav>\n"); + unsigned level = 0; + for(auto& line : lines) { + if(auto depth = count(line, '-')) { + while(level < depth) level++, state.output.append("<ul>\n"); + while(level > depth) level--, state.output.append("</ul>\n"); + auto content = line.slice(depth + 1).split<1>(" => "); + auto data = markup(content[0]); + auto name = escape(content(1, data.crc32())); + state.output.append("<li><a href=\"#", name, "\">", data, "</a></li>\n"); + } + } + while(level--) state.output.append("</ul>\n"); + state.output.append("</nav>\n"); + } + + //list + else if(count(block, '*')) { + unsigned level = 0; + for(auto& line : lines) { + if(auto depth = count(line, '*')) { + while(level < depth) level++, state.output.append("<ul>\n"); + while(level > depth) level--, state.output.append("</ul>\n"); + auto data = markup(line.slice(depth + 1)); + state.output.append("<li>", data, "</li>\n"); + } + } + while(level--) state.output.append("</ul>\n"); + } + + //quote + else if(count(block, '>')) { + unsigned level = 0; + for(auto& line : lines) { + if(auto depth = count(line, '>')) { + while(level < depth) level++, state.output.append("<blockquote>\n"); + while(level > depth) level--, state.output.append("</blockquote>\n"); + auto data = markup(line.slice(depth + 1)); + state.output.append(data, "\n"); + } + } + while(level--) state.output.append("</blockquote>\n"); + } + + //code + else if(block.beginsWith(" ")) { + state.output.append("<pre>"); + for(auto& line : lines) { + if(!ltrim(line, " ")) continue; + state.output.append(escape(line), "\n"); + } + state.output.rtrim("\n").append("</pre>\n"); + } + + //divider + else if(block.equals("---")) { + state.output.append("<hr>\n"); + } + + //paragraph + else { + state.output.append("<p>", markup(block), "</p>\n"); + } + + return true; +} + +auto DML::count(const string& text, char value) -> unsigned { + for(unsigned n = 0; n < text.size(); n++) { + if(text[n] != value) { + if(text[n] == ' ') return n; + break; + } + } + return 0; +} + +auto DML::escape(const string& text) -> string { + string output; + for(unsigned n = 0; n < text.size();) { + char x = text[n++]; + if(x == '&') { output.append("&"); continue; } + if(x == '<') { output.append("<"); continue; } + if(x == '>') { output.append(">"); continue; } + if(x == '"') { output.append("""); continue; } + output.append(x); + } + return output; +} + +auto DML::markup(const string& text) -> string { + string output; + char flagStrong = 0; + char flagEmphasis = 0; + char flagInsert = 0; + char flagDelete = 0; + char flagCode = 0; + + for(unsigned n = 0; n < text.size();) { + char x = text[n], y = text[n + 1]; + + if(x == '[' && y == '\\') { output.append('['); n += 2; continue; } + + if(x == '[' && y == '*' && flagStrong == 0) { flagStrong = 1; output.append("<strong>"); n += 2; continue; } + if(x == '*' && y == ']' && flagStrong == 1) { flagStrong = 0; output.append("</strong>"); n += 2; continue; } + + if(x == '[' && y == '/' && flagEmphasis == 0) { flagEmphasis = 1; output.append("<em>"); n += 2; continue; } + if(x == '/' && y == ']' && flagEmphasis == 1) { flagEmphasis = 0; output.append("</em>"); n += 2; continue; } + + if(x == '[' && y == '_' && flagInsert == 0) { flagInsert = 1; output.append("<ins>"); n += 2; continue; } + if(x == '_' && y == ']' && flagInsert == 1) { flagInsert = 0; output.append("</ins>"); n += 2; continue; } + + if(x == '[' && y == '-' && flagDelete == 0) { flagDelete = 1; output.append("<del>"); n += 2; continue; } + if(x == '-' && y == ']' && flagDelete == 1) { flagDelete = 0; output.append("</del>"); n += 2; continue; } + + if(x == '[' && y == '|' && flagCode == 0) { flagCode = 1; output.append("<code>"); n += 2; continue; } + if(x == '|' && y == ']' && flagCode == 1) { flagCode = 0; output.append("</code>"); n += 2; continue; } + + if(x == '[' && y == '[') { + if(auto length = text.findFrom(n + 2, "]]")) { + lstring content = text.slice(n + 2, *length).split<1>(" => "); + output.append("<a href=\"", escape(content[0]), "\">", escape(content(1, content[0])), "</a>"); + n += *length + 4; + continue; + } + } + + if(x == '[' && y == '{') { + if(auto length = text.findFrom(n + 2, "}]")) { + lstring content = text.slice(n + 2, *length).split<1>(" => "); + output.append("<img src=\"", escape(content[0]), "\" alt=\"", escape(content(1, "")), "\">"); + n += *length + 4; + continue; + } + } + + if(x == '&') { output.append("&"); n++; continue; } + if(x == '<') { output.append("<"); n++; continue; } + if(x == '>') { output.append(">"); n++; continue; } + if(x == '"') { output.append("""); n++; continue; } + + output.append(x); + n++; + } + + if(flagStrong) output.append("</strong>"); + if(flagEmphasis) output.append("</em>"); + if(flagInsert) output.append("</ins>"); + if(flagDelete) output.append("</del>"); + if(flagCode) output.append("</code>"); + return output; +} + +}} + +#endif diff --git a/nall/string/trim.hpp b/nall/string/trim.hpp new file mode 100644 index 00000000..5aaff55d --- /dev/null +++ b/nall/string/trim.hpp @@ -0,0 +1,82 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +auto trim(string& self, rstring lhs, rstring rhs) -> bool { + if(lhs.size() + rhs.size() > self.size()) return false; + if(memory::compare(self.data(), lhs.data(), lhs.size()) != 0) return false; + if(memory::compare(self.data() + self.size() - rhs.size(), rhs.data(), rhs.size()) != 0) return false; + self.resize(self.size() - rhs.size()); + self.remove(0, lhs.size()); + return true; +} + +auto ltrim(string& self, rstring lhs) -> bool { + if(lhs.size() > self.size()) return false; + if(memory::compare(self.data(), lhs.data(), lhs.size()) != 0) return false; + self.remove(0, lhs.size()); + return true; +} + +auto rtrim(string& self, rstring rhs) -> bool { + if(rhs.size() > self.size()) return false; + if(memory::compare(self.data() + self.size() - rhs.size(), rhs.data(), rhs.size()) != 0) return false; + self.resize(self.size() - rhs.size()); + return true; +} + +auto itrim(string& self, rstring lhs, rstring rhs) -> bool { + if(lhs.size() + rhs.size() > self.size()) return false; + if(memory::icompare(self.data(), lhs.data(), lhs.size()) != 0) return false; + if(memory::icompare(self.data() + self.size() - rhs.size(), rhs.data(), rhs.size()) != 0) return false; + self.resize(self.size() - rhs.size()); + self.remove(0, lhs.size()); + return true; +} + +auto iltrim(string& self, rstring lhs) -> bool { + if(lhs.size() > self.size()) return false; + if(memory::icompare(self.data(), lhs.data(), lhs.size()) != 0) return false; + self.remove(0, lhs.size()); + return true; +} + +auto irtrim(string& self, rstring rhs) -> bool { + if(rhs.size() > self.size()) return false; + if(memory::icompare(self.data() + self.size() - rhs.size(), rhs.data(), rhs.size()) != 0) return false; + self.resize(self.size() - rhs.size()); + return true; +} + +auto strip(string& self) -> bool { + return rstrip(self) | lstrip(self); +} + +auto lstrip(string& self) -> bool { + unsigned size = 0; + while(size < self.size()) { + char input = self[size]; + if(input != ' ' && input != '\t' && input != '\r' && input != '\n') break; + size++; + } + if(size == 0) return false; + self.remove(0, size); + return true; +} + +auto rstrip(string& self) -> bool { + unsigned size = 0; + while(size < self.size()) { + bool matched = false; + char input = self[self.size() - size - 1]; + if(input != ' ' && input != '\t' && input != '\r' && input != '\n') break; + size++; + } + if(size == 0) return false; + self.resize(self.size() - size); + return true; +} + +} + +#endif diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index 429636cd..e4f01107 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -2,46 +2,107 @@ namespace nall { -string substr(rstring source, unsigned offset, unsigned length) { +auto string::read(const string& filename) -> string { + #if !defined(_WIN32) + FILE* fp = fopen(filename, "rb"); + #else + FILE* fp = _wfopen(utf16_t(filename), L"rb"); + #endif + string result; - if(length == ~0u) length = source.size() - offset; - result.resize(length); - memcpy(result.data(), source.data() + offset, length); + if(!fp) return result; + + fseek(fp, 0, SEEK_END); + signed filesize = ftell(fp); + if(filesize < 0) return fclose(fp), result; + + rewind(fp); + result.resize(filesize); + fread(result.pointer(), 1, filesize, fp); + return fclose(fp), result; +} + +template<unsigned L> auto string::repeat(const string& pattern) -> string { + string result; + unsigned times = L; + while(times--) result.append(pattern); return result; } -string sha256(const uint8_t* data, unsigned size) { - sha256_ctx sha; - uint8_t hash[32]; - sha256_init(&sha); - sha256_chunk(&sha, data, size); - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto& byte : hash) result.append(hex<2>(byte)); +auto fill(string& self, char fill) -> string& { + memory::fill(self.pointer(), self.size(), fill); + return self; +} + +auto hash(const string& self) -> unsigned { + const char* p = self.data(); + unsigned size = self.size(); + unsigned result = 5381; + while(size--) result = (result << 5) + result + *p++; return result; } -bool tokenize(lstring& list, const char* s, const char* p) { - while(*s) { - if(*p == '*') { - const char* b = s; - while(*s) { - if(tokenize(list, s++, p + 1)) { - list.prepend(substr(b, 0, --s - b)); - return true; - } - } - list.prepend(b); - return !*++p; - } - if(*s++ != *p++) return false; +auto remove(string& self, unsigned offset, unsigned length) -> string& { + char* p = self.pointer(); + length = min(length, self.size()); + memory::move(p + offset, p + offset + length, self.size() - length); + return self.resize(self.size() - length); +} + +auto reverse(string& self) -> string& { + char* p = self.pointer(); + unsigned size = self.size(); + unsigned pivot = size >> 1; + for(signed x = 0, y = size - 1; x < pivot && y >= 0; x++, y--) std::swap(p[x], p[y]); + return self; +} + +//+length => insert/delete from start (right justify) +//-length => insert/delete from end (left justify) +auto size(string& self, signed length, char fill) -> string& { + unsigned size = self.size(); + if(size == length) return self; + + bool right = length >= 0; + length = abs(length); + + if(size < length) { //expand + self.resize(length); + char* p = self.pointer(); + unsigned displacement = length - size; + if(right) memory::move(p + displacement, p, size); + else p += size; + while(displacement--) *p++ = fill; + } else { //shrink + char* p = self.pointer(); + unsigned displacement = size - length; + if(right) memory::move(p, p + displacement, length); + self.resize(length); } - while(*p == '*') { list.prepend(s); p++; } - return !*p; + + return self; } -char* integer(char* result, intmax_t value) { +auto slice(const string& self, signed offset, signed length) -> string { + string result; + if(offset < self.size()) { + if(length < 0) length = self.size() - offset; + result.resize(length); + memory::copy(result.pointer(), self.data() + offset, length); + } + return result; +} + +//legacy function: required for some library functions, do not use in newly written code +auto substr(rstring source, signed offset, signed length) -> string { + string result; + if(length < 0) length = source.size() - offset; + result.resize(length); + memory::copy(result.pointer(), source.data() + offset, length); + return result; +} + +auto integer(char* result, intmax_t value) -> char* { bool negative = value < 0; if(negative) value = -value; @@ -54,14 +115,13 @@ char* integer(char* result, intmax_t value) { value /= 10; } while(value); if(negative) buffer[size++] = '-'; -//buffer[size++] = negative ? '-' : '+'; for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y]; result[size] = 0; return result; } -char* decimal(char* result, uintmax_t value) { +auto decimal(char* result, uintmax_t value) -> char* { char buffer[64]; unsigned size = 0; @@ -79,7 +139,7 @@ char* decimal(char* result, uintmax_t value) { //using sprintf is certainly not the most ideal method to convert //a double to a string ... but attempting to parse a double by //hand, digit-by-digit, results in subtle rounding errors. -unsigned real(char* str, long double value) { +auto real(char* result, long double value) -> unsigned { char buffer[256]; #ifdef _WIN32 //Windows C-runtime does not support long double via sprintf() @@ -101,17 +161,10 @@ unsigned real(char* str, long double value) { } unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); + if(result) strcpy(result, buffer); return length + 1; } -string real(long double value) { - string temp; - temp.resize(real(nullptr, value)); - real(temp.data(), value); - return temp; -} - } #endif diff --git a/nall/string/variadic.hpp b/nall/string/variadic.hpp deleted file mode 100644 index fed6b7f3..00000000 --- a/nall/string/variadic.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -void sprint(string& output) { -} - -template<typename T, typename... Args> -void sprint(string& output, const T& value, Args&&... args) { - output._append(make_string(value)); - sprint(output, std::forward<Args>(args)...); -} - -template<typename... Args> void print(Args&&... args) { - printf("%s", (const char*)string(std::forward<Args>(args)...)); -} - -} - -#endif diff --git a/nall/string/wrapper.hpp b/nall/string/wrapper.hpp deleted file mode 100644 index 0eadf3dd..00000000 --- a/nall/string/wrapper.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template<unsigned limit> lstring string::split(rstring key) const { lstring result; result.split<limit>(key, data()); return result; } -template<unsigned limit> lstring string::isplit(rstring key) const { lstring result; result.isplit<limit>(key, data()); return result; } -template<unsigned limit> lstring string::qsplit(rstring key) const { lstring result; result.qsplit<limit>(key, data()); return result; } -template<unsigned limit> lstring string::iqsplit(rstring key) const { lstring result; result.iqsplit<limit>(key, data()); return result; } - -bool string::match(rstring source) const { return nall::strmatch(data(), source); } -bool string::imatch(rstring source) const { return nall::istrmatch(data(), source); } - -signed string::compare(rstring source) const { - return strcmp(data(), source.data()); -} - -signed string::icompare(rstring source) const { - return istrcmp(data(), source.data()); -} - -bool string::equals(rstring source) const { - if(size() != source.size()) return false; - return compare(source) == 0; -} - -bool string::iequals(rstring source) const { - if(size() != source.size()) return false; - return icompare(source) == 0; -} - -bool string::beginsWith(rstring source) const { - if(source.size() > size()) return false; - return memcmp(data(), source.data(), source.size()) == 0; -} - -bool string::ibeginsWith(rstring source) const { - if(source.size() > size()) return false; - return imemcmp(data(), source.data(), source.size()) == 0; -} - -bool string::endsWith(rstring source) const { - if(source.size() > size()) return false; - return memcmp(data() + size() - source.size(), source.data(), source.size()) == 0; -} - -bool string::iendsWith(rstring source) const { - if(source.size() > size()) return false; - return imemcmp(data() + size() - source.size(), source.data(), source.size()) == 0; -} - -string string::slice(unsigned offset, unsigned length) const { - if(offset >= size()) return ""; - if(length == ~0u) length = size() - offset; - return substr(data(), offset, length); -} - -string& string::lower() { nall::strlower(data()); return *this; } -string& string::upper() { nall::strupper(data()); return *this; } -string& string::qlower() { nall::qstrlower(data()); return *this; } -string& string::qupper() { nall::qstrupper(data()); return *this; } - -string& string::transform(rstring before, rstring after) { nall::strtr(data(), before, after); return *this; } - -string& string::reverse() { - unsigned length = size(), pivot = length >> 1; - for(signed x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(data()[x], data()[y]); - return *this; -} - -template<unsigned Limit> string& string::ltrim(rstring key) { - if(key.size() == 0) return *this; - unsigned limit = Limit ? Limit : ~0u, offset = 0; - - while(limit && size() - offset >= key.size()) { - if(memcmp(data() + offset, key.data(), key.size())) break; - offset += key.size(); - limit--; - } - - if(offset) memmove(data(), data() + offset, size() - offset); - resize(size() - offset); - return *this; -} - -template<unsigned Limit> string& string::rtrim(rstring key) { - if(key.size() == 0) return *this; - unsigned limit = Limit ? Limit : ~0u, offset = 0; - - while(limit && size() - offset >= key.size()) { - if(memcmp(data() + size() - key.size() - offset, key.data(), key.size())) break; - offset += key.size(); - limit--; - } - - resize(size() - offset); - return *this; -} - -template<unsigned Limit> string& string::trim(rstring key) { - rtrim<Limit>(key); - ltrim<Limit>(key); - return *this; -} - -template<unsigned Limit> string& string::trim(rstring lkey, rstring rkey) { - rtrim<Limit>(rkey); - ltrim<Limit>(lkey); - return *this; -} - -string& string::strip() { - nall::strip(data()); - resize(length()); - return *this; -} - -maybe<unsigned> string::find(rstring key) const { return strpos(data(), key); } -maybe<unsigned> string::ifind(rstring key) const { return istrpos(data(), key); } -maybe<unsigned> string::qfind(rstring key) const { return qstrpos(data(), key); } -maybe<unsigned> string::iqfind(rstring key) const { return iqstrpos(data(), key); } - -} - -#endif diff --git a/nall/thread.hpp b/nall/thread.hpp index 5cd2846c..e07339c6 100644 --- a/nall/thread.hpp +++ b/nall/thread.hpp @@ -1,66 +1,69 @@ #ifndef NALL_THREAD_HPP #define NALL_THREAD_HPP +//simple thread library +//primary rationale is that std::thread does not support custom stack sizes +//this is highly critical in certain applications such as threaded web servers +//an added bonus is that it avoids licensing issues on Windows +//win32-pthreads (needed for std::thread) is licensed under the GPL only + #include <nall/platform.hpp> #include <nall/function.hpp> #include <nall/intrinsics.hpp> -#if defined(PLATFORM_XORG) || defined(PLATFORM_MACOSX) +#if defined(PLATFORM_BSD) || defined(PLATFORM_LINUX) || defined(PLATFORM_MACOSX) #include <pthread.h> namespace nall { -inline void* thread_entry_point(void*); - struct thread { - thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { - initialize(); - pthread_create(&pthread, nullptr, thread_entry_point, (void*)this); - } + inline auto join() -> void; - ~thread() { - join(); - } + static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, unsigned stacksize = 0) -> thread; + static inline auto detach() -> void; + static inline auto exit() -> void; - bool active() const { - return completed == false; - } - - void join() { - if(dead) return; - dead = true; - pthread_join(pthread, nullptr); - } - - static bool primary() { - initialize(); - return pthread_equal(primaryThread(), pthread_self()); - } + struct context { + function<void (uintptr_t)> callback; + uintptr_t parameter = 0; + }; private: - pthread_t pthread; - function<void ()> entryPoint; - volatile bool completed, dead; - friend void* thread_entry_point(void*); - - static void initialize() { - static bool initialized = false; - if(initialized) return; - initialized = true; - primaryThread() = pthread_self(); - } - - static pthread_t& primaryThread() { - static pthread_t thread; - return thread; - } + pthread_t handle; }; -void* thread_entry_point(void* parameter) { - thread* context = (thread*)parameter; - context->entryPoint(); - context->completed = true; +inline auto _threadCallback(void* parameter) -> void* { + auto context = (thread::context*)parameter; + context->callback(context->parameter); + delete context; + return nullptr; +} + +auto thread::join() -> void { + pthread_join(handle, nullptr); +} + +auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, unsigned stacksize) -> thread { + thread instance; + + auto context = new thread::context; + context->callback = callback; + context->parameter = parameter; + + pthread_attr_t attr; + pthread_attr_init(&attr); + if(stacksize) pthread_attr_setstacksize(&attr, max(PTHREAD_STACK_MIN, stacksize)); + + pthread_create(&instance.handle, &attr, _threadCallback, (void*)context); + return instance; +} + +auto thread::detach() -> void { + pthread_detach(pthread_self()); +} + +auto thread::exit() -> void { pthread_exit(nullptr); } @@ -70,60 +73,66 @@ void* thread_entry_point(void* parameter) { namespace nall { -inline DWORD WINAPI thread_entry_point(LPVOID); - struct thread { - thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { - initialize(); - hthread = CreateThread(nullptr, 0, thread_entry_point, (void*)this, 0, nullptr); - } + inline ~thread(); + inline auto join() -> void; - ~thread() { - join(); - } + static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, unsigned stacksize = 0) -> thread; + static inline auto detach() -> void; + static inline auto exit() -> void; - bool active() const { - return completed == false; - } - - void join() { - if(dead) return; - dead = true; - WaitForSingleObject(hthread, INFINITE); - CloseHandle(hthread); - } - - static bool primary() { - initialize(); - return primaryThread() == GetCurrentThreadId(); - } + struct context { + function<void (uintptr_t)> callback; + uintptr_t parameter = 0; + }; private: - HANDLE hthread; - function<void ()> entryPoint; - volatile bool completed, dead; - friend DWORD WINAPI thread_entry_point(LPVOID); - - static void initialize() { - static bool initialized = false; - if(initialized) return; - initialized = true; - primaryThread() = GetCurrentThreadId(); - } - - static DWORD& primaryThread() { - static DWORD thread; - return thread; - } + HANDLE handle = 0; }; -inline DWORD WINAPI thread_entry_point(LPVOID parameter) { - thread *context = (thread*)parameter; - context->entryPoint(); - context->completed = true; +inline auto WINAPI _threadCallback(void* parameter) -> DWORD { + auto context = (thread::context*)parameter; + context->callback(context->parameter); + delete context; return 0; } +thread::~thread() { + if(handle) { + CloseHandle(handle); + handle = 0; + } +} + +auto thread::join() -> void { + if(handle) { + WaitForSingleObject(handle, INFINITE); + CloseHandle(handle); + handle = 0; + } +} + +auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, unsigned stacksize) -> thread { + thread instance; + + auto context = new thread::context; + context->callback = callback; + context->parameter = parameter; + + instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr); + return instance; +} + +auto thread::detach() -> void { + //Windows threads do not use this concept: + //~thread() frees resources via CloseHandle() + //thread continues to run even after handle is closed +} + +auto thread::exit() -> void { + ExitThread(0); +} + } #endif diff --git a/nall/traits.hpp b/nall/traits.hpp index 6a140c2b..8550714c 100644 --- a/nall/traits.hpp +++ b/nall/traits.hpp @@ -2,32 +2,51 @@ #define NALL_TRAITS_HPP #include <type_traits> +#include <utility> namespace nall { + using std::forward; + using std::move; + using std::decay; + using std::declval; -template<typename T> class has_default_constructor { - template<signed> class receive_size{}; - template<typename U> static signed sfinae(receive_size<sizeof U()>*); - template<typename U> static char sfinae(...); + using true_type = std::true_type; + using false_type = std::false_type; -public: - enum : bool { value = sizeof(sfinae<T>(0)) == sizeof(signed) }; -}; + template<typename T, typename U> using is_same = std::is_same<T, U>; + template<typename T, typename U> using is_base_of = std::is_base_of<T, U>; + template<typename T> using is_array = std::is_array<T>; + template<typename T> using is_function = std::is_function<T>; + template<typename T> using is_integral = std::is_integral<T>; +} -template<bool C, typename T = bool> struct enable_if { typedef T type; }; -template<typename T> struct enable_if<false, T> {}; +namespace nall { + template<bool C> struct expression { static constexpr bool value = C; }; +} -template<bool C, typename T, typename F> struct type_if { typedef T type; }; -template<typename T, typename F> struct type_if<false, T, F> { typedef F type; }; +namespace nall { + namespace traits { + enum class enable_type {}; + enum class disable_type {}; -template<bool A, bool B> struct static_and { enum { value = false }; }; -template<> struct static_and<true, true> { enum { value = true }; }; + template<bool C, typename T = void> struct enable_if { using type = T; }; + template<typename T> struct enable_if<false, T> {}; -template<bool A, bool B> struct static_or { enum { value = false }; }; -template<> struct static_or<false, true> { enum { value = true }; }; -template<> struct static_or<true, false> { enum { value = true }; }; -template<> struct static_or<true, true> { enum { value = true }; }; + template<bool C, typename T = void> struct disable_if { using type = T; }; + template<typename T> struct disable_if<true, T> {}; + } + template<typename C, typename T = void> using enable_if = typename traits::enable_if<C::value, T>::type; + template<typename C, typename T = void> using disable_if = typename traits::disable_if<C::value, T>::type; +} + +namespace nall { + namespace traits { + template<bool C, typename T, typename F> struct type_if { using type = T; }; + template<typename T, typename F> struct type_if<false, T, F> { using type = F; }; + } + + template<typename C, typename T, typename F> using type_if = typename traits::type_if<C::value, T, F>::type; } #endif diff --git a/nall/varint.hpp b/nall/varint.hpp index 944e193e..e77ffb30 100644 --- a/nall/varint.hpp +++ b/nall/varint.hpp @@ -52,7 +52,7 @@ struct varint { template<unsigned bits> struct uint_t { private: - typedef typename type_if<bits <= 8 * sizeof(unsigned), unsigned, uintmax_t>::type type_t; + using type_t = type_if<expression<bits <= 8 * sizeof(unsigned)>, unsigned, uintmax_t>; type_t data; public: @@ -84,7 +84,7 @@ public: template<unsigned bits> struct int_t { private: - typedef typename type_if<bits <= 8 * sizeof(signed), signed, intmax_t>::type type_t; + using type_t = type_if<expression<bits <= 8 * sizeof(signed)>, signed, intmax_t>; type_t data; public: diff --git a/nall/vector.hpp b/nall/vector.hpp index d1da089b..2e866bab 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -109,7 +109,10 @@ public: } void insert(unsigned position, const T& data) { - if(position == 0) return prepend(data); + if(position == 0) { + prepend(data); + return; + } append(data); if(position == ~0u) return; for(signed n = objectsize - 1; n > position; n--) { @@ -165,7 +168,7 @@ public: nall::sort(pool + poolbase, objectsize, lessthan); } - maybe<unsigned> find(const T& data) { + maybe<unsigned> find(const T& data) const { for(unsigned n = 0; n < objectsize; n++) if(pool[poolbase + n] == data) return n; return nothing; } @@ -243,6 +246,7 @@ public: //copy inline vector& operator=(const vector& source) { + if(this == &source) return *this; reset(); reserve(source.size()); for(auto& data : source) append(data); @@ -251,6 +255,7 @@ public: //move inline vector& operator=(vector&& source) { + if(this == &source) return *this; reset(); pool = source.pool; poolbase = source.poolbase; diff --git a/nall/windows/detour.hpp b/nall/windows/detour.hpp index 34a5d3f8..ce583912 100644 --- a/nall/windows/detour.hpp +++ b/nall/windows/detour.hpp @@ -75,7 +75,7 @@ bool detour::insert(const string& moduleName, const string& functionName, void*& #if 1 string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " }; for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " "); - output.rtrim<1>(" "); + output.rtrim(" "); MessageBoxA(0, output, "nall::detour", MB_OK); #endif return false; diff --git a/nall/windows/registry.hpp b/nall/windows/registry.hpp index f702afe4..7c9aff2c 100644 --- a/nall/windows/registry.hpp +++ b/nall/windows/registry.hpp @@ -92,7 +92,7 @@ struct registry { wchar_t name[NWR_SIZE] = L""; DWORD size = NWR_SIZE * sizeof(wchar_t); RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); - result.append({(const char*)utf8_t(name), "/"}); + result.append(string{(const char*)utf8_t(name), "/"}); } for(unsigned n = 0; n < nodes; n++) { wchar_t name[NWR_SIZE] = L""; diff --git a/nall/windows/utf8.hpp b/nall/windows/utf8.hpp index dc3ea3bb..d6e8a480 100644 --- a/nall/windows/utf8.hpp +++ b/nall/windows/utf8.hpp @@ -6,11 +6,9 @@ #if defined(_WIN32) -#undef UNICODE -#undef _WIN32_WINNT -#undef NOMINMAX +#undef UNICODE #define UNICODE -#define _WIN32_WINNT 0x0501 +#undef NOMINMAX #define NOMINMAX #include <winsock2.h> #include <windows.h> diff --git a/nall/zip.hpp b/nall/zip.hpp index 2c27a328..a0f05e30 100644 --- a/nall/zip.hpp +++ b/nall/zip.hpp @@ -3,8 +3,8 @@ //creates uncompressed ZIP archives -#include <nall/crc32.hpp> #include <nall/string.hpp> +#include <nall/hash/crc32.hpp> namespace nall { @@ -21,7 +21,7 @@ struct zip { //append file: append("path/file", data, size); void append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) { filename.transform("\\", "/"); - uint32_t checksum = crc32_calculate(data, size); + uint32_t checksum = Hash::CRC32(data, size).value(); directory.append({filename, checksum, size, fp.offset()}); fp.writel(0x04034b50, 4); //signature diff --git a/out/.gitignore b/out/.gitignore index cc3f712d..98f54497 100644 --- a/out/.gitignore +++ b/out/.gitignore @@ -1,2 +1 @@ higan -loki diff --git a/phoenix/Makefile b/phoenix/Makefile deleted file mode 100644 index 957e361b..00000000 --- a/phoenix/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -ifeq ($(platform),) - phoenixflags = $(cppflags) $(flags) -DPHOENIX_REFERENCE - phoenixlink = -else ifeq ($(platform),windows) - phoenixflags = $(cppflags) $(flags) -DPHOENIX_WINDOWS - phoenixlink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi -else ifeq ($(platform),macosx) - phoenixflags = $(objcppflags) $(flags) -DPHOENIX_COCOA - phoenixlink = -framework Cocoa -framework Carbon -else - ifeq ($(phoenix),) - phoenix := gtk - endif - - ifeq ($(phoenix),gtk) - phoenixflags = $(cppflags) $(flags) -DPHOENIX_GTK `pkg-config --cflags gtk+-2.0` - phoenixlink = `pkg-config --libs gtk+-2.0` - endif - - ifeq ($(phoenix),qt) - phoenixflags = $(cppflags) $(flags) -DPHOENIX_QT `pkg-config --cflags QtCore QtGui` - phoenixlink = `pkg-config --libs QtCore QtGui` - endif -endif diff --git a/phoenix/core/core.cpp b/phoenix/core/core.cpp deleted file mode 100644 index ac4cd54b..00000000 --- a/phoenix/core/core.cpp +++ /dev/null @@ -1,2046 +0,0 @@ -#if defined(PHOENIX_WINDOWS) - #include "../windows/header.hpp" -#elif defined(PHOENIX_QT) - #include "../qt/header.hpp" -#elif defined(PHOENIX_GTK) - #include "../gtk/header.hpp" -#elif defined(PHOENIX_COCOA) - #include "../cocoa/header.hpp" -#elif defined(PHOENIX_REFERENCE) - #include "../reference/header.hpp" -#endif - -#include "core.hpp" -using namespace nall; - -namespace phoenix { - #include "state.hpp" - #include "layout/fixed-layout.cpp" - #include "layout/horizontal-layout.cpp" - #include "layout/vertical-layout.cpp" -} - -#if defined(PHOENIX_WINDOWS) - #include "../windows/platform.cpp" -#elif defined(PHOENIX_QT) - #include "../qt/platform.cpp" -#elif defined(PHOENIX_GTK) - #include "../gtk/platform.cpp" -#elif defined(PHOENIX_COCOA) - #include "../cocoa/platform.cpp" -#elif defined(PHOENIX_REFERENCE) - #include "../reference/platform.cpp" -#endif - -namespace phoenix { - -//Application -//=========== - -function<void ()> Application::main; - -function<void ()> Application::Windows::onModalBegin; -function<void ()> Application::Windows::onModalEnd; - -function<void ()> Application::Cocoa::onAbout; -function<void ()> Application::Cocoa::onActivate; -function<void ()> Application::Cocoa::onPreferences; -function<void ()> Application::Cocoa::onQuit; - -void Application::run() { - return pApplication::run(); -} - -bool Application::pendingEvents() { - return pApplication::pendingEvents(); -} - -void Application::processEvents() { - return pApplication::processEvents(); -} - -void Application::quit() { - applicationState.quit = true; - return pApplication::quit(); -} - -void Application::setName(const string& name) { - applicationState.name = name; -} - -void Application::initialize() { - static bool initialized = false; - if(initialized == false) { - initialized = true; - return pApplication::initialize(); - } -} - -//Color -//===== - -uint32_t Color::rgb() const { - return (255 << 24) + (red << 16) + (green << 8) + (blue << 0); -} - -uint32_t Color::argb() const { - return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0); -} - -//Geometry -//======== - -Position Geometry::position() const { - return {x, y}; -} - -Size Geometry::size() const { - return {width, height}; -} - -string Geometry::text() const { - return {x, ",", y, ",", width, ",", height}; -} - -Geometry::Geometry(const string& text) { - lstring part = text.split(","); - x = integer(part(0, "256")); - y = integer(part(1, "256")); - width = decimal(part(2, "256")); - height = decimal(part(3, "256")); -} - -//Font -//==== - -string Font::serif(unsigned size, const string& style) { - return pFont::serif(size, style); -} - -string Font::sans(unsigned size, const string& style) { - return pFont::sans(size, style); -} - -string Font::monospace(unsigned size, const string& style) { - return pFont::monospace(size, style); -} - -Size Font::size(const string& font, const string& text) { - return pFont::size(font, text); -} - -//Desktop -//======= - -Size Desktop::size() { - return pDesktop::size(); -} - -Geometry Desktop::workspace() { - return pDesktop::workspace(); -} - -//Monitor -//======= - -unsigned Monitor::count() { - return pMonitor::count(); -} - -Geometry Monitor::geometry(unsigned monitor) { - return pMonitor::geometry(monitor); -} - -unsigned Monitor::primary() { - return pMonitor::primary(); -} - -//Keyboard -//======== - -bool Keyboard::pressed(Keyboard::Scancode scancode) { - return pKeyboard::pressed(scancode); -} - -bool Keyboard::released(Keyboard::Scancode scancode) { - return !pressed(scancode); -} - -vector<bool> Keyboard::state() { - return pKeyboard::state(); -} - -//Mouse -//===== - -Position Mouse::position() { - return pMouse::position(); -} - -bool Mouse::pressed(Mouse::Button button) { - return pMouse::pressed(button); -} - -bool Mouse::released(Mouse::Button button) { - return !pressed(button); -} - -//BrowserWindow -//============= - -string BrowserWindow::directory() { - return pBrowserWindow::directory(state); -} - -string BrowserWindow::open() { - return pBrowserWindow::open(state); -} - -string BrowserWindow::save() { - return pBrowserWindow::save(state); -} - -BrowserWindow& BrowserWindow::setFilters(const lstring& filters) { - state.filters = filters; - return *this; -} - -BrowserWindow& BrowserWindow::setParent(Window& parent) { - state.parent = &parent; - return *this; -} - -BrowserWindow& BrowserWindow::setPath(const string& path) { - state.path = path; - return *this; -} - -BrowserWindow& BrowserWindow::setTitle(const string& title) { - state.title = title; - return *this; -} - -BrowserWindow::BrowserWindow(): -state(*new State) { -} - -BrowserWindow::~BrowserWindow() { - delete &state; -} - -//MessageWindow -//============= - -MessageWindow::Response MessageWindow::error(MessageWindow::Buttons buttons) { - state.buttons = buttons; - return pMessageWindow::error(state); -} - -MessageWindow::Response MessageWindow::information(MessageWindow::Buttons buttons) { - state.buttons = buttons; - return pMessageWindow::information(state); -} - -MessageWindow::Response MessageWindow::question(MessageWindow::Buttons buttons) { - state.buttons = buttons; - return pMessageWindow::question(state); -} - -MessageWindow& MessageWindow::setParent(Window& parent) { - state.parent = &parent; - return *this; -} - -MessageWindow& MessageWindow::setText(const string& text) { - state.text = text; - return *this; -} - -MessageWindow& MessageWindow::setTitle(const string& title) { - state.title = title; - return *this; -} - -MessageWindow::Response MessageWindow::warning(MessageWindow::Buttons buttons) { - state.buttons = buttons; - return pMessageWindow::warning(state); -} - -MessageWindow::MessageWindow(const string& text): -state(*new State) { - state.text = text; -} - -MessageWindow::~MessageWindow() { - delete &state; -} - -//Object -//====== - -Object::Object(pObject& p): -p(p) { - Application::initialize(); - p.constructor(); -} - -Object::~Object() { - p.destructor(); - delete &p; -} - -//Timer -//===== - -bool Timer::enabled() const { - return state.enabled; -} - -unsigned Timer::interval() const { - return state.interval; -} - -void Timer::setEnabled(bool enabled) { - state.enabled = enabled; - return p.setEnabled(enabled); -} - -void Timer::setInterval(unsigned interval) { - state.interval = interval; - return p.setInterval(interval); -} - -Timer::Timer(): -state(*new State), -base_from_member<pTimer&>(*new pTimer(*this)), -Object(base_from_member<pTimer&>::value), -p(base_from_member<pTimer&>::value) { - p.constructor(); -} - -Timer::~Timer() { - p.destructor(); - delete &state; -} - -//Window -//====== - -void Window::append(Layout& layout) { - if(state.layout.append(layout)) { - layout.Sizable::state.parent = nullptr; - layout.Sizable::state.window = this; - p.append(layout); - layout.synchronizeLayout(); - } -} - -void Window::append(Menu& menu) { - if(state.menu.append(menu)) { - menu.Action::state.window = this; - p.append(menu); - } -} - -void Window::append(Widget& widget) { - if(state.widget.append(widget)) { - widget.Sizable::state.window = this; - p.append(widget); - widget.synchronizeLayout(); - } -} - -Color Window::backgroundColor() const { - return state.backgroundColor; -} - -bool Window::droppable() const { - return state.droppable; -} - -Geometry Window::frameGeometry() { - Geometry geometry = p.geometry(); - Geometry margin = p.frameMargin(); - return { - geometry.x - margin.x, geometry.y - margin.y, - geometry.width + margin.width, geometry.height + margin.height - }; -} - -Geometry Window::frameMargin() { - return p.frameMargin(); -} - -bool Window::focused() { - return p.focused(); -} - -bool Window::fullScreen() const { - return state.fullScreen; -} - -Geometry Window::geometry() { - return p.geometry(); -} - -string Window::menuFont() const { - return state.menuFont; -} - -bool Window::menuVisible() const { - return state.menuVisible; -} - -bool Window::modal() const { - return state.modal; -} - -void Window::remove(Layout& layout) { - if(state.layout.remove(layout)) { - p.remove(layout); - layout.Sizable::state.window = nullptr; - } -} - -void Window::remove(Menu& menu) { - if(state.menu.remove(menu)) { - p.remove(menu); - menu.Action::state.window = nullptr; - } -} - -void Window::remove(Widget& widget) { - if(state.widget.remove(widget)) { - p.remove(widget); - widget.Sizable::state.window = nullptr; - } -} - -bool Window::resizable() const { - return state.resizable; -} - -void Window::setBackgroundColor(Color color) { - state.backgroundColorOverride = true; - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void Window::setDroppable(bool droppable) { - state.droppable = droppable; - return p.setDroppable(droppable); -} - -void Window::setFrameGeometry(Geometry geometry) { - Geometry margin = p.frameMargin(); - return setGeometry({ - geometry.x + margin.x, geometry.y + margin.y, - geometry.width - margin.width, geometry.height - margin.height - }); -} - -void Window::setFocused() { - return p.setFocused(); -} - -void Window::setFullScreen(bool fullScreen) { - state.fullScreen = fullScreen; - return p.setFullScreen(fullScreen); -} - -void Window::setGeometry(Geometry geometry) { - state.geometry = geometry; - return p.setGeometry(geometry); -} - -void Window::setMenuFont(const string& font) { - state.menuFont = font; - return p.setMenuFont(font); -} - -void Window::setMenuVisible(bool visible) { - state.menuVisible = visible; - return p.setMenuVisible(visible); -} - -void Window::setModal(bool modal) { - state.modal = modal; - return p.setModal(modal); -} - -void Window::setResizable(bool resizable) { - state.resizable = resizable; - return p.setResizable(resizable); -} - -void Window::setStatusFont(const string& font) { - state.statusFont = font; - return p.setStatusFont(font); -} - -void Window::setStatusText(const string& text) { - state.statusText = text; - return p.setStatusText(text); -} - -void Window::setStatusVisible(bool visible) { - state.statusVisible = visible; - return p.setStatusVisible(visible); -} - -void Window::setTitle(const string& text) { - state.title = text; - return p.setTitle(text); -} - -void Window::setVisible(bool visible) { - state.visible = visible; - synchronizeLayout(); - return p.setVisible(visible); -} - -void Window::setWidgetFont(const string& font) { - state.widgetFont = font; - return p.setWidgetFont(font); -} - -void Window::setWindowGeometry(Geometry geometry) { - Geometry margin = p.frameMargin(); - return setGeometry({ - geometry.x + margin.x, geometry.y + margin.y, - geometry.width, geometry.height - }); -} - -string Window::statusFont() const { - return state.statusFont; -} - -string Window::statusText() const { - return state.statusText; -} - -bool Window::statusVisible() const { - return state.statusVisible; -} - -void Window::synchronizeLayout() { - if(visible() && applicationState.quit == false) setGeometry(geometry()); -} - -string Window::title() const { - return state.title; -} - -bool Window::visible() const { - return state.visible; -} - -string Window::widgetFont() const { - return state.widgetFont; -} - -Window::Window(): -state(*new State), -base_from_member<pWindow&>(*new pWindow(*this)), -Object(base_from_member<pWindow&>::value), -p(base_from_member<pWindow&>::value) { - p.constructor(); -} - -Window::~Window() { - p.destructor(); - delete &state; -} - -//Action -//====== - -bool Action::enabled() const { - return state.enabled; -} - -void Action::setEnabled(bool enabled) { - state.enabled = enabled; - return p.setEnabled(enabled); -} - -void Action::setVisible(bool visible) { - state.visible = visible; - return p.setVisible(visible); -} - -bool Action::visible() const { - return state.visible; -} - -Action::Action(pAction& p): -state(*new State), -Object(p), -p(p) { - p.constructor(); -} - -Action::~Action() { - p.destructor(); - delete &state; -} - -//Menu -//==== - -void Menu::append(const group<Action>& list) { - for(auto& action : list) { - if(state.action.append(action)) { - action.state.menu = this; - p.append(action); - } - } -} - -image Menu::image() const { - return state.image; -} - -void Menu::remove(const group<Action>& list) { - for(auto& action : list) { - if(state.action.remove(action)) { - action.state.menu = nullptr; - return p.remove(action); - } - } -} - -void Menu::setImage(const nall::image& image) { - state.image = image; - return p.setImage(image); -} - -void Menu::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string Menu::text() const { - return state.text; -} - -Menu::Menu(): -state(*new State), -base_from_member<pMenu&>(*new pMenu(*this)), -Action(base_from_member<pMenu&>::value), -p(base_from_member<pMenu&>::value) { - p.constructor(); -} - -Menu::~Menu() { - p.destructor(); - delete &state; -} - -//Separator -//========= - -Separator::Separator(): -base_from_member<pSeparator&>(*new pSeparator(*this)), -Action(base_from_member<pSeparator&>::value), -p(base_from_member<pSeparator&>::value) { - p.constructor(); -} - -Separator::~Separator() { - p.destructor(); -} - -//Item -//==== - -image Item::image() const { - return state.image; -} - -void Item::setImage(const nall::image& image) { - state.image = image; - return p.setImage(image); -} - -void Item::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string Item::text() const { - return state.text; -} - -Item::Item(): -state(*new State), -base_from_member<pItem&>(*new pItem(*this)), -Action(base_from_member<pItem&>::value), -p(base_from_member<pItem&>::value) { - p.constructor(); -} - -Item::~Item() { - p.destructor(); - delete &state; -} - -//CheckItem -//========= - -bool CheckItem::checked() const { - return state.checked; -} - -void CheckItem::setChecked(bool checked) { - state.checked = checked; - return p.setChecked(checked); -} - -void CheckItem::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string CheckItem::text() const { - return state.text; -} - -CheckItem::CheckItem(): -state(*new State), -base_from_member<pCheckItem&>(*new pCheckItem(*this)), -Action(base_from_member<pCheckItem&>::value), -p(base_from_member<pCheckItem&>::value) { - p.constructor(); -} - -CheckItem::~CheckItem() { - p.destructor(); - delete &state; -} - -//RadioItem -//========= - -void RadioItem::group(const nall::group<RadioItem>& list) { - for(auto& item : list) item.p.setGroup(item.state.group = list); - if(list.size()) list.first().setChecked(); -} - -bool RadioItem::checked() const { - return state.checked; -} - -void RadioItem::setChecked() { - for(auto& item : state.group) item.state.checked = false; - state.checked = true; - return p.setChecked(); -} - -void RadioItem::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string RadioItem::text() const { - return state.text; -} - -RadioItem::RadioItem(): -state(*new State), -base_from_member<pRadioItem&>(*new pRadioItem(*this)), -Action(base_from_member<pRadioItem&>::value), -p(base_from_member<pRadioItem&>::value) { - p.constructor(); -} - -RadioItem::~RadioItem() { - for(auto& item : state.group) { - if(&item != this) item.state.group.remove(*this); - } - p.destructor(); - delete &state; -} - -//Sizable -//======= - -bool Sizable::enabled() const { - return state.enabled; -} - -bool Sizable::enabledToAll() const { - if(state.enabled == false) return false; - if(state.parent) return state.parent->enabledToAll(); - return true; -} - -Layout* Sizable::layout() const { - if(state.parent && dynamic_cast<Layout*>(state.parent)) return (Layout*)state.parent; - return nullptr; -} - -Sizable* Sizable::parent() const { - return state.parent; -} - -bool Sizable::visible() const { - return state.visible; -} - -bool Sizable::visibleToAll() const { - if(state.visible == false) return false; - if(state.parent) return state.parent->visibleToAll(); - return true; -} - -Window* Sizable::window() const { - return state.window; -} - -Sizable::Sizable(pSizable& p): -state(*new State), -Object(p), -p(p) { - p.constructor(); -} - -Sizable::~Sizable() { - if(layout()) layout()->remove(*this); - p.destructor(); - delete &state; -} - -//Layout -//====== - -void Layout::append(Sizable& sizable) { - sizable.state.parent = this; - sizable.state.window = Sizable::state.window; - - if(dynamic_cast<Layout*>(&sizable)) { - Layout& layout = (Layout&)sizable; - layout.synchronizeLayout(); - } - - if(dynamic_cast<Widget*>(&sizable)) { - Widget& widget = (Widget&)sizable; - if(sizable.window()) sizable.window()->append(widget); - } -} - -void Layout::remove(Sizable& sizable) { - if(dynamic_cast<Widget*>(&sizable)) { - Widget& widget = (Widget&)sizable; - if(sizable.window()) sizable.window()->remove(widget); - } - - sizable.state.parent = nullptr; - sizable.state.window = nullptr; -} - -void Layout::reset() { -} - -Layout::Layout(): -state(*new State), -base_from_member<pLayout&>(*new pLayout(*this)), -Sizable(base_from_member<pLayout&>::value), -p(base_from_member<pLayout&>::value) { -} - -Layout::Layout(pLayout& p): -state(*new State), -base_from_member<pLayout&>(p), -Sizable(p), -p(p) { -} - -Layout::~Layout() { - if(layout()) layout()->remove(*this); - if(window()) window()->remove(*this); - p.destructor(); - delete &state; -} - -//Widget -//====== - -bool Widget::focused() { - return p.focused(); -} - -string Widget::font() const { - return state.font; -} - -Geometry Widget::geometry() const { - return state.geometry; -} - -Size Widget::minimumSize() { - return p.minimumSize(); -} - -void Widget::setEnabled(bool enabled) { - Sizable::state.enabled = enabled; - return p.setEnabled(enabled); -} - -void Widget::setFocused() { - return p.setFocused(); -} - -void Widget::setFont(const string& font) { - state.font = font; - return p.setFont(font); -} - -void Widget::setGeometry(Geometry geometry) { - state.geometry = geometry; - return p.setGeometry(geometry); -} - -void Widget::setVisible(bool visible) { - Sizable::state.visible = visible; - return p.setVisible(visible); -} - -void Widget::synchronizeLayout() { -} - -Widget::Widget(): -state(*new State), -base_from_member<pWidget&>(*new pWidget(*this)), -Sizable(base_from_member<pWidget&>::value), -p(base_from_member<pWidget&>::value) { - state.abstract = true; - p.constructor(); -} - -Widget::Widget(pWidget& p): -state(*new State), -base_from_member<pWidget&>(p), -Sizable(base_from_member<pWidget&>::value), -p(base_from_member<pWidget&>::value) { - p.constructor(); -} - -Widget::~Widget() { - p.destructor(); - delete &state; -} - -//Button -//====== - -image Button::image() const { - return state.image; -} - -Orientation Button::orientation() const { - return state.orientation; -} - -void Button::setImage(const nall::image& image, Orientation orientation) { - state.image = image; - state.orientation = orientation; - return p.setImage(image, orientation); -} - -void Button::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -nall::string Button::text() const { - return state.text; -} - -Button::Button(): -state(*new State), -base_from_member<pButton&>(*new pButton(*this)), -Widget(base_from_member<pButton&>::value), -p(base_from_member<pButton&>::value) { - p.constructor(); -} - -Button::~Button() { - p.destructor(); - delete &state; -} - -//Canvas -//====== - -Color Canvas::color() const { - return state.color; -} - -uint32_t* Canvas::data() const { - return state.data; -} - -bool Canvas::droppable() const { - return state.droppable; -} - -vector<Color> Canvas::gradient() const { - return state.gradient; -} - -image Canvas::image() const { - return state.image; -} - -Canvas::Mode Canvas::mode() const { - return state.mode; -} - -void Canvas::setColor(Color color) { - state.color = color; - return setMode(Canvas::Mode::Color); -} - -void Canvas::setData() { - if(state.width == 0 || state.height == 0) return; //dynamic sizing not supported in Mode::Data - return setMode(Canvas::Mode::Data); -} - -void Canvas::setDroppable(bool droppable) { - state.droppable = droppable; - return p.setDroppable(droppable); -} - -void Canvas::setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) { - state.gradient[0] = topLeft; - state.gradient[1] = topRight; - state.gradient[2] = bottomLeft; - state.gradient[3] = bottomRight; - return setMode(Canvas::Mode::Gradient); -} - -void Canvas::setHorizontalGradient(Color left, Color right) { - state.gradient[0] = state.gradient[2] = left; - state.gradient[1] = state.gradient[3] = right; - return setMode(Canvas::Mode::Gradient); -} - -void Canvas::setImage(const nall::image& image) { - state.image = image; - return setMode(Canvas::Mode::Image); -} - -void Canvas::setMode(Mode mode) { - state.mode = mode; - return p.setMode(mode); -} - -void Canvas::setSize(Size size) { - if(size.width == Size::Maximum) size.width = 0; - if(size.height == Size::Maximum) size.height = 0; - state.width = size.width; - state.height = size.height; - delete[] state.data; - state.data = new uint32_t[state.width * state.height](); - return setMode(state.mode); -} - -void Canvas::setVerticalGradient(Color top, Color bottom) { - state.gradient[0] = state.gradient[1] = top; - state.gradient[2] = state.gradient[3] = bottom; - return setMode(Canvas::Mode::Gradient); -} - -Size Canvas::size() const { - return {state.width, state.height}; -} - -Canvas::Canvas(): -state(*new State), -base_from_member<pCanvas&>(*new pCanvas(*this)), -Widget(base_from_member<pCanvas&>::value), -p(base_from_member<pCanvas&>::value) { - state.data = new uint32_t[state.width * state.height](); - p.constructor(); -} - -Canvas::~Canvas() { - p.destructor(); - delete[] state.data; - delete &state; -} - -//CheckButton -//=========== - -bool CheckButton::checked() const { - return state.checked; -} - -image CheckButton::image() const { - return state.image; -} - -void CheckButton::setChecked(bool checked) { - state.checked = checked; - return p.setChecked(checked); -} - -void CheckButton::setImage(const nall::image& image, Orientation orientation) { - state.image = image; - state.orientation = orientation; - return p.setImage(image, orientation); -} - -void CheckButton::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string CheckButton::text() const { - return state.text; -} - -CheckButton::CheckButton(): -state(*new State), -base_from_member<pCheckButton&>(*new pCheckButton(*this)), -Widget(base_from_member<pCheckButton&>::value), -p(base_from_member<pCheckButton&>::value) { - p.constructor(); -} - -CheckButton::~CheckButton() { - p.destructor(); - delete &state; -} - -//CheckLabel -//========== - -bool CheckLabel::checked() const { - return state.checked; -} - -void CheckLabel::setChecked(bool checked) { - state.checked = checked; - return p.setChecked(checked); -} - -void CheckLabel::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string CheckLabel::text() const { - return state.text; -} - -CheckLabel::CheckLabel(): -state(*new State), -base_from_member<pCheckLabel&>(*new pCheckLabel(*this)), -Widget(base_from_member<pCheckLabel&>::value), -p(base_from_member<pCheckLabel&>::value) { - p.constructor(); -} - -CheckLabel::~CheckLabel() { - p.destructor(); - delete &state; -} - - -//ComboButton -//=========== - -void ComboButton::append(const string& text) { - state.text.append(text); - return p.append(text); -} - -void ComboButton::remove(unsigned selection) { - if(selection >= state.text.size()) return; - state.text.remove(selection); - p.remove(selection); -} - -void ComboButton::reset() { - state.selection = 0; - state.text.reset(); - return p.reset(); -} - -unsigned ComboButton::rows() const { - return state.text.size(); -} - -unsigned ComboButton::selection() const { - return state.selection; -} - -void ComboButton::setSelection(unsigned selection) { - if(selection >= state.text.size()) return; - state.selection = selection; - return p.setSelection(selection); -} - -void ComboButton::setText(unsigned selection, const string& text) { - if(selection >= state.text.size()) return; - state.text[selection] = text; - p.setText(selection, text); -} - -string ComboButton::text() const { - if(state.text.empty()) return ""; - return state.text[state.selection]; -} - -string ComboButton::text(unsigned selection) const { - if(selection >= state.text.size()) return ""; - return state.text[selection]; -} - -ComboButton::ComboButton(): -state(*new State), -base_from_member<pComboButton&>(*new pComboButton(*this)), -Widget(base_from_member<pComboButton&>::value), -p(base_from_member<pComboButton&>::value) { - p.constructor(); -} - -ComboButton::~ComboButton() { - p.destructor(); - delete &state; -} - -//Console -//======= - -Color Console::backgroundColor() const { - return state.backgroundColor; -} - -Color Console::foregroundColor() const { - return state.foregroundColor; -} - -void Console::print(const string& text) { - return p.print(text); -} - -string Console::prompt() const { - return state.prompt; -} - -void Console::reset() { - return p.reset(); -} - -void Console::setBackgroundColor(Color color) { - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void Console::setForegroundColor(Color color) { - state.foregroundColor = color; - return p.setForegroundColor(color); -} - -void Console::setPrompt(const string& prompt) { - state.prompt = prompt; - return p.setPrompt(prompt); -} - -Console::Console(): -state(*new State), -base_from_member<pConsole&>(*new pConsole(*this)), -Widget(base_from_member<pConsole&>::value), -p(base_from_member<pConsole&>::value) { - p.constructor(); -} - -Console::~Console() { - p.destructor(); - delete &state; -} - -//Frame -//===== - -void Frame::setLayout(Layout& layout) { - state.layout = &layout; - synchronizeLayout(); -} - -void Frame::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -void Frame::synchronizeLayout() { - if(state.layout == nullptr) return; - state.layout->Sizable::state.window = Sizable::state.window; - state.layout->Sizable::state.parent = this; - state.layout->state.widget = this; - state.layout->synchronizeLayout(); -} - -string Frame::text() const { - return state.text; -} - -Frame::Frame(): -state(*new State), -base_from_member<pFrame&>(*new pFrame(*this)), -Widget(base_from_member<pFrame&>::value), -p(base_from_member<pFrame&>::value) { - p.constructor(); -} - -Frame::~Frame() { - p.destructor(); - delete &state; -} - -//HexEdit -//======= - -Color HexEdit::backgroundColor() const { - return state.backgroundColor; -} - -unsigned HexEdit::columns() const { - return state.columns; -} - -Color HexEdit::foregroundColor() const { - return state.foregroundColor; -} - -unsigned HexEdit::length() const { - return state.length; -} - -unsigned HexEdit::offset() const { - return state.offset; -} - -unsigned HexEdit::rows() const { - return state.rows; -} - -void HexEdit::setBackgroundColor(Color color) { - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void HexEdit::setColumns(unsigned columns) { - state.columns = columns; - return p.setColumns(columns); -} - -void HexEdit::setForegroundColor(Color color) { - state.foregroundColor = color; - return p.setForegroundColor(color); -} - -void HexEdit::setLength(unsigned length) { - state.length = length; - return p.setLength(length); -} - -void HexEdit::setOffset(unsigned offset) { - state.offset = offset; - return p.setOffset(offset); -} - -void HexEdit::setRows(unsigned rows) { - state.rows = rows; - return p.setRows(rows); -} - -void HexEdit::update() { - return p.update(); -} - -HexEdit::HexEdit(): -state(*new State), -base_from_member<pHexEdit&>(*new pHexEdit(*this)), -Widget(base_from_member<pHexEdit&>::value), -p(base_from_member<pHexEdit&>::value) { - p.constructor(); -} - -HexEdit::~HexEdit() { - p.destructor(); - delete &state; -} - -//HorizontalScroller -//================== - -unsigned HorizontalScroller::length() const { - return state.length; -} - -unsigned HorizontalScroller::position() const { - return state.position; -} - -void HorizontalScroller::setLength(unsigned length) { - state.length = length; - return p.setLength(length); -} - -void HorizontalScroller::setPosition(unsigned position) { - state.position = position; - return p.setPosition(position); -} - -HorizontalScroller::HorizontalScroller(): -state(*new State), -base_from_member<pHorizontalScroller&>(*new pHorizontalScroller(*this)), -Widget(base_from_member<pHorizontalScroller&>::value), -p(base_from_member<pHorizontalScroller&>::value) { - p.constructor(); -} - -HorizontalScroller::~HorizontalScroller() { - p.destructor(); - delete &state; -} - -//HorizontalSlider -//================ - -unsigned HorizontalSlider::length() const { - return state.length; -} - -unsigned HorizontalSlider::position() const { - return state.position; -} - -void HorizontalSlider::setLength(unsigned length) { - state.length = length; - return p.setLength(length); -} - -void HorizontalSlider::setPosition(unsigned position) { - state.position = position; - return p.setPosition(position); -} - -HorizontalSlider::HorizontalSlider(): -state(*new State), -base_from_member<pHorizontalSlider&>(*new pHorizontalSlider(*this)), -Widget(base_from_member<pHorizontalSlider&>::value), -p(base_from_member<pHorizontalSlider&>::value) { - p.constructor(); -} - -HorizontalSlider::~HorizontalSlider() { - p.destructor(); - delete &state; -} - -//Label -//===== - -void Label::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string Label::text() const { - return state.text; -} - -Label::Label(): -state(*new State), -base_from_member<pLabel&>(*new pLabel(*this)), -Widget(base_from_member<pLabel&>::value), -p(base_from_member<pLabel&>::value) { - p.constructor(); -} - -Label::~Label() { - p.destructor(); - delete &state; -} - -//LineEdit -//======== - -Color LineEdit::backgroundColor() const { - return state.backgroundColor; -} - -bool LineEdit::editable() const { - return state.editable; -} - -Color LineEdit::foregroundColor() const { - return state.foregroundColor; -} - -void LineEdit::setBackgroundColor(Color color) { - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void LineEdit::setEditable(bool editable) { - state.editable = editable; - return p.setEditable(editable); -} - -void LineEdit::setForegroundColor(Color color) { - state.foregroundColor = color; - return p.setForegroundColor(color); -} - -void LineEdit::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string LineEdit::text() { - return p.text(); -} - -LineEdit::LineEdit(): -state(*new State), -base_from_member<pLineEdit&>(*new pLineEdit(*this)), -Widget(base_from_member<pLineEdit&>::value), -p(base_from_member<pLineEdit&>::value) { - p.constructor(); -} - -LineEdit::~LineEdit() { - p.destructor(); - delete &state; -} - -//ListView -//======== - -void ListView::append(const lstring& text) { - state.checked.append(false); - state.image.append({}); - state.text.append(text); - return p.append(text); -} - -void ListView::autoSizeColumns() { - return p.autoSizeColumns(); -} - -Color ListView::backgroundColor() const { - return state.backgroundColor; -} - -bool ListView::checkable() const { - return state.checkable; -} - -bool ListView::checked(unsigned selection) const { - if(selection >= state.text.size()) return false; - return state.checked[selection]; -} - -unsigned ListView::columns() const { - return max(1u, state.headerText.size()); -} - -Color ListView::foregroundColor() const { - return state.foregroundColor; -} - -bool ListView::headerVisible() const { - return state.headerVisible; -} - -image ListView::image(unsigned selection, unsigned position) const { - if(selection >= state.text.size()) return {}; - return state.image[selection](position); -} - -void ListView::remove(unsigned selection) { - if(selection >= state.text.size()) return; - state.checked.remove(selection); - state.image.remove(selection); - state.text.remove(selection); - return p.remove(selection); -} - -void ListView::reset() { - state.checked.reset(); - state.image.reset(); - state.selected = false; - state.selection = 0; - state.text.reset(); - return p.reset(); -} - -unsigned ListView::rows() const { - return state.text.size(); -} - -bool ListView::selected() const { - return state.selected; -} - -unsigned ListView::selection() const { - return state.selection; -} - -void ListView::setBackgroundColor(Color color) { - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void ListView::setCheckable(bool checkable) { - state.checkable = checkable; - return p.setCheckable(checkable); -} - -void ListView::setChecked(unsigned selection, bool checked) { - if(selection >= state.text.size()) return; - state.checked[selection] = checked; - return p.setChecked(selection, checked); -} - -void ListView::setForegroundColor(Color color) { - state.foregroundColor = color; - return p.setForegroundColor(color); -} - -void ListView::setHeaderText(const lstring& text) { - state.headerText = text; - return p.setHeaderText(text); -} - -void ListView::setHeaderVisible(bool visible) { - state.headerVisible = visible; - return p.setHeaderVisible(visible); -} - -void ListView::setImage(unsigned selection, unsigned position, const nall::image& image) { - if(selection >= state.text.size()) return; - state.image[selection](position) = image; - return p.setImage(selection, position, image); -} - -void ListView::setSelected(bool selected) { - state.selected = selected; - return p.setSelected(selected); -} - -void ListView::setSelection(unsigned selection) { - if(selection >= state.text.size()) return; - state.selected = true; - state.selection = selection; - return p.setSelection(selection); -} - -void ListView::setText(unsigned selection, const lstring& text) { - if(selection >= state.text.size()) return; - for(unsigned position = 0; position < text.size(); position++) { - setText(selection, position, text[position]); - } -} - -void ListView::setText(unsigned selection, unsigned position, const string& text) { - if(selection >= state.text.size()) return; - state.text[selection](position) = text; - return p.setText(selection, position, text); -} - -string ListView::text(unsigned selection, unsigned position) const { - if(selection >= state.text.size()) return ""; - return state.text[selection](position); -} - -ListView::ListView(): -state(*new State), -base_from_member<pListView&>(*new pListView(*this)), -Widget(base_from_member<pListView&>::value), -p(base_from_member<pListView&>::value) { - p.constructor(); -} - -ListView::~ListView() { - p.destructor(); - delete &state; -} - -//ProgressBar -//=========== - -unsigned ProgressBar::position() const { - return state.position; -} - -void ProgressBar::setPosition(unsigned position) { - state.position = position; - return p.setPosition(position); -} - -ProgressBar::ProgressBar(): -state(*new State), -base_from_member<pProgressBar&>(*new pProgressBar(*this)), -Widget(base_from_member<pProgressBar&>::value), -p(base_from_member<pProgressBar&>::value) { - p.constructor(); -} - -ProgressBar::~ProgressBar() { - p.destructor(); - delete &state; -} - -//RadioButton -//=========== - -void RadioButton::group(const nall::group<RadioButton>& list) { - for(auto& item : list) item.p.setGroup(item.state.group = list); - if(list.size()) list.first().setChecked(); -} - -bool RadioButton::checked() const { - return state.checked; -} - -image RadioButton::image() const { - return state.image; -} - -void RadioButton::setChecked() { - for(auto& item : state.group) item.state.checked = false; - state.checked = true; - return p.setChecked(); -} - -void RadioButton::setImage(const nall::image& image, Orientation orientation) { - state.image = image; - state.orientation = orientation; - return p.setImage(image, orientation); -} - -void RadioButton::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string RadioButton::text() const { - return state.text; -} - -RadioButton::RadioButton(): -state(*new State), -base_from_member<pRadioButton&>(*new pRadioButton(*this)), -Widget(base_from_member<pRadioButton&>::value), -p(base_from_member<pRadioButton&>::value) { - p.constructor(); -} - -RadioButton::~RadioButton() { - for(auto& item : state.group) { - if(&item != this) item.state.group.remove(*this); - } - p.destructor(); - delete &state; -} - -//RadioLabel -//========== - -void RadioLabel::group(const nall::group<RadioLabel>& list) { - for(auto& item : list) item.p.setGroup(item.state.group = list); - if(list.size()) list.first().setChecked(); -} - -bool RadioLabel::checked() const { - return state.checked; -} - -void RadioLabel::setChecked() { - for(auto &item : state.group) item.state.checked = false; - state.checked = true; - return p.setChecked(); -} - -void RadioLabel::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -string RadioLabel::text() const { - return state.text; -} - -RadioLabel::RadioLabel(): -state(*new State), -base_from_member<pRadioLabel&>(*new pRadioLabel(*this)), -Widget(base_from_member<pRadioLabel&>::value), -p(base_from_member<pRadioLabel&>::value) { - p.constructor(); -} - -RadioLabel::~RadioLabel() { - for(auto& item : state.group) { - if(&item != this) item.state.group.remove(*this); - } - p.destructor(); - delete &state; -} - -//TabFrame -//======== - -void TabFrame::append(const string& text, const nall::image& image) { - state.image.append(image); - state.layout.append(nullptr); - state.text.append(text); - return p.append(text, image); -} - -image TabFrame::image(unsigned selection) const { - if(selection >= state.text.size()) return {}; - return state.image[selection]; -} - -void TabFrame::remove(unsigned selection) { - if(selection >= state.text.size()) return; - state.image.remove(selection); - state.layout.remove(selection); - state.text.remove(selection); - return p.remove(selection); -} - -unsigned TabFrame::selection() const { - return state.selection; -} - -void TabFrame::setImage(unsigned selection, const nall::image& image) { - if(selection >= state.text.size()) return; - state.image[selection] = image; - return p.setImage(selection, image); -} - -void TabFrame::setLayout(unsigned selection, Layout& layout) { - if(selection >= state.text.size()) return; - state.layout[selection] = &layout; - synchronizeLayout(); -} - -void TabFrame::setSelection(unsigned selection) { - state.selection = selection; - return p.setSelection(selection); -} - -void TabFrame::setText(unsigned selection, const string& text) { - if(selection >= state.text.size()) return; - state.text[selection] = text; - return p.setText(selection, text); -} - -void TabFrame::synchronizeLayout() { - for(unsigned n = 0; n < state.layout.size(); n++) { - Layout* layout = state.layout[n]; - if(layout == nullptr) continue; - layout->Sizable::state.parent = this; - layout->Sizable::state.window = Sizable::state.window; - layout->state.widget = this; - layout->state.widgetSelection = n; - layout->synchronizeLayout(); - } -} - -unsigned TabFrame::tabs() const { - return state.text.size(); -} - -string TabFrame::text(unsigned selection) const { - if(selection >= state.text.size()) return ""; - return state.text[selection]; -} - -TabFrame::TabFrame(): -state(*new State), -base_from_member<pTabFrame&>(*new pTabFrame(*this)), -Widget(base_from_member<pTabFrame&>::value), -p(base_from_member<pTabFrame&>::value) { - p.constructor(); -} - -TabFrame::~TabFrame() { - p.destructor(); - delete &state; -} - -//TextEdit -//======== - -Color TextEdit::backgroundColor() const { - return state.backgroundColor; -} - -bool TextEdit::editable() const { - return state.editable; -} - -Color TextEdit::foregroundColor() const { - return state.foregroundColor; -} - -void TextEdit::setBackgroundColor(Color color) { - state.backgroundColor = color; - return p.setBackgroundColor(color); -} - -void TextEdit::setCursorPosition(unsigned position) { - state.cursorPosition = position; - return p.setCursorPosition(position); -} - -void TextEdit::setEditable(bool editable) { - state.editable = editable; - return p.setEditable(editable); -} - -void TextEdit::setForegroundColor(Color color) { - state.foregroundColor = color; - return p.setForegroundColor(color); -} - -void TextEdit::setText(const string& text) { - state.text = text; - return p.setText(text); -} - -void TextEdit::setWordWrap(bool wordWrap) { - state.wordWrap = wordWrap; - return p.setWordWrap(wordWrap); -} - -string TextEdit::text() { - return p.text(); -} - -bool TextEdit::wordWrap() const { - return state.wordWrap; -} - -TextEdit::TextEdit(): -state(*new State), -base_from_member<pTextEdit&>(*new pTextEdit(*this)), -Widget(base_from_member<pTextEdit&>::value), -p(base_from_member<pTextEdit&>::value) { - p.constructor(); -} - -TextEdit::~TextEdit() { - p.destructor(); - delete &state; -} - -//VerticalScroller -//================ - -unsigned VerticalScroller::length() const { - return state.length; -} - -unsigned VerticalScroller::position() const { - return state.position; -} - -void VerticalScroller::setLength(unsigned length) { - state.length = length; - return p.setLength(length); -} - -void VerticalScroller::setPosition(unsigned position) { - state.position = position; - return p.setPosition(position); -} - -VerticalScroller::VerticalScroller(): -state(*new State), -base_from_member<pVerticalScroller&>(*new pVerticalScroller(*this)), -Widget(base_from_member<pVerticalScroller&>::value), -p(base_from_member<pVerticalScroller&>::value) { - p.constructor(); -} - -VerticalScroller::~VerticalScroller() { - p.destructor(); - delete &state; -} - -//VerticalSlider -//============== - -unsigned VerticalSlider::length() const { - return state.length; -} - -unsigned VerticalSlider::position() const { - return state.position; -} - -void VerticalSlider::setLength(unsigned length) { - state.length = length; - return p.setLength(length); -} - -void VerticalSlider::setPosition(unsigned position) { - state.position = position; - return p.setPosition(position); -} - -VerticalSlider::VerticalSlider(): -state(*new State), -base_from_member<pVerticalSlider&>(*new pVerticalSlider(*this)), -Widget(base_from_member<pVerticalSlider&>::value), -p(base_from_member<pVerticalSlider&>::value) { - p.constructor(); -} - -VerticalSlider::~VerticalSlider() { - p.destructor(); - delete &state; -} - -//Viewport -//======== - -bool Viewport::droppable() const { - return state.droppable; -} - -uintptr_t Viewport::handle() { - return p.handle(); -} - -void Viewport::setDroppable(bool droppable) { - state.droppable = droppable; - return p.setDroppable(droppable); -} - -Viewport::Viewport(): -state(*new State), -base_from_member<pViewport&>(*new pViewport(*this)), -Widget(base_from_member<pViewport&>::value), -p(base_from_member<pViewport&>::value) { - p.constructor(); -} - -Viewport::~Viewport() { - p.destructor(); - delete &state; -} - -} diff --git a/phoenix/core/core.hpp b/phoenix/core/core.hpp deleted file mode 100644 index cc25c5ba..00000000 --- a/phoenix/core/core.hpp +++ /dev/null @@ -1,826 +0,0 @@ -#include <nall/platform.hpp> -#include <nall/config.hpp> -#include <nall/directory.hpp> -#include <nall/function.hpp> -#include <nall/group.hpp> -#include <nall/image.hpp> -#include <nall/map.hpp> -#include <nall/stdint.hpp> -#include <nall/string.hpp> -#include <nall/utility.hpp> -#include <nall/vector.hpp> - -namespace phoenix { - -struct Application; -struct Font; -struct Window; -struct Menu; -struct Sizable; -struct Layout; -struct Widget; - -struct pApplication; -struct pFont; -struct pObject; -struct pTimer; -struct pWindow; -struct pAction; -struct pMenu; -struct pSeparator; -struct pItem; -struct pCheckItem; -struct pRadioItem; -struct pSizable; -struct pLayout; -struct pWidget; -struct pButton; -struct pCanvas; -struct pCheckButton; -struct pCheckLabel; -struct pComboButton; -struct pConsole; -struct pFrame; -struct pHexEdit; -struct pHorizontalScroller; -struct pHorizontalSlider; -struct pLabel; -struct pLineEdit; -struct pListView; -struct pProgressBar; -struct pRadioButton; -struct pRadioLabel; -struct pTabFrame; -struct pTextEdit; -struct pVerticalScroller; -struct pVerticalSlider; -struct pViewport; - -struct Application { - static nall::function<void ()> main; - - static void run(); - static bool pendingEvents(); - static void processEvents(); - static void quit(); - static void setName(const nall::string& name); - - Application() = delete; - struct State; - static void initialize(); - - struct Windows { - static nall::function<void ()> onModalBegin; - static nall::function<void ()> onModalEnd; - }; - - struct Cocoa { - static nall::function<void ()> onAbout; - static nall::function<void ()> onActivate; - static nall::function<void ()> onPreferences; - static nall::function<void ()> onQuit; - }; -}; - -struct Color { - uint8_t red, green, blue, alpha; - uint32_t rgb() const; - uint32_t argb() const; - inline Color() : alpha(255), red(0), green(0), blue(0) {} - inline Color(uint8_t red, uint8_t green, uint8_t blue) : alpha(255), red(red), green(green), blue(blue) {} - inline Color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue) : alpha(alpha), red(red), green(green), blue(blue) {} -}; - -struct Position { - signed x, y; - inline Position() : x(0), y(0) {} - template<typename X, typename Y> inline Position(X x, Y y) : x(x), y(y) {} -}; - -struct Size { - static const unsigned Maximum = ~0u; - static const unsigned Minimum = 0u; - - unsigned width, height; - inline Size() : width(0), height(0) {} - template<typename W, typename H> inline Size(W width, H height) : width(width), height(height) {} -}; - -struct Geometry { - signed x, y; - unsigned width, height; - Position position() const; - Size size() const; - nall::string text() const; - inline Geometry() : x(0), y(0), width(0), height(0) {} - inline Geometry(Position position, Size size) : x(position.x), y(position.y), width(size.width), height(size.height) {} - template<typename X, typename Y, typename W, typename H> inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {} - Geometry(const nall::string& text); -}; - -enum class Orientation : unsigned { Horizontal, Vertical }; - -struct Font { - static nall::string serif(unsigned size = 0, const nall::string& style = ""); - static nall::string sans(unsigned size = 0, const nall::string& style = ""); - static nall::string monospace(unsigned size = 0, const nall::string& style = ""); - static Size size(const nall::string& font, const nall::string& text); - Font() = delete; -}; - -struct Desktop { - static Size size(); - static Geometry workspace(); - Desktop() = delete; -}; - -struct Monitor { - static unsigned count(); - static Geometry geometry(unsigned monitor); - static unsigned primary(); -}; - -struct Keyboard { - #include "keyboard.hpp" - static bool pressed(Scancode scancode); - static bool released(Scancode scancode); - static nall::vector<bool> state(); - Keyboard() = delete; -}; - -struct Mouse { - enum class Button : unsigned { Left, Middle, Right }; - static Position position(); - static bool pressed(Button); - static bool released(Button); - Mouse() = delete; -}; - -struct BrowserWindow { - nall::string directory(); - nall::string open(); - nall::string save(); - BrowserWindow& setFilters(const nall::lstring& filters); - BrowserWindow& setParent(Window& parent); - BrowserWindow& setPath(const nall::string& path); - BrowserWindow& setTitle(const nall::string& title); - - BrowserWindow(); - ~BrowserWindow(); - struct State; - State& state; -}; - -struct MessageWindow { - enum class Buttons : unsigned { - Ok, - OkCancel, - YesNo, - YesNoCancel, - }; - - enum class Response : unsigned { - Ok, - Cancel, - Yes, - No, - }; - - Response error(Buttons = Buttons::Ok); - Response information(Buttons = Buttons::Ok); - Response question(Buttons = Buttons::YesNo); - MessageWindow& setParent(Window& parent); - MessageWindow& setText(const nall::string& text); - MessageWindow& setTitle(const nall::string& title); - Response warning(Buttons = Buttons::Ok); - - MessageWindow(const nall::string& text = ""); - ~MessageWindow(); - struct State; - State& state; -}; - -struct Object { - Object(pObject& p); - Object& operator=(const Object&) = delete; - Object(const Object&) = delete; - virtual ~Object(); - pObject& p; -}; - -struct Timer : private nall::base_from_member<pTimer&>, Object { - nall::function<void ()> onActivate; - - bool enabled() const; - unsigned interval() const; - void setEnabled(bool enabled = true); - void setInterval(unsigned interval); //in milliseconds - - Timer(); - ~Timer(); - struct State; - State& state; - pTimer& p; -}; - -struct Window : private nall::base_from_member<pWindow&>, Object { - nall::function<void ()> onClose; - nall::function<void (nall::lstring)> onDrop; - nall::function<void (Keyboard::Keycode)> onKeyPress; - nall::function<void (Keyboard::Keycode)> onKeyRelease; - nall::function<void ()> onMove; - nall::function<void ()> onSize; - - void append(Layout& layout); - void append(Menu& menu); - void append(Widget& widget); - Color backgroundColor() const; - bool droppable() const; - Geometry frameGeometry(); - Geometry frameMargin(); - bool focused(); - bool fullScreen() const; - Geometry geometry(); - nall::string menuFont() const; - bool menuVisible() const; - bool modal() const; - void remove(Layout& layout); - void remove(Menu& menu); - void remove(Widget& widget); - bool resizable() const; - void setBackgroundColor(Color color); - void setDroppable(bool droppable = true); - void setFrameGeometry(Geometry geometry); - void setFocused(); - void setFullScreen(bool fullScreen = true); - void setGeometry(Geometry geometry); - void setMenuFont(const nall::string& font); - void setMenuVisible(bool visible = true); - void setModal(bool modal = true); - void setResizable(bool resizable = true); - void setStatusFont(const nall::string& font); - void setStatusText(const nall::string& text); - void setStatusVisible(bool visible = true); - void setTitle(const nall::string& text); - void setVisible(bool visible = true); - void setWidgetFont(const nall::string& font); - void setWindowGeometry(Geometry geometry); - nall::string statusFont() const; - nall::string statusText() const; - bool statusVisible() const; - void synchronizeLayout(); - nall::string title() const; - bool visible() const; - nall::string widgetFont() const; - - Window(); - ~Window(); - struct State; - State& state; - pWindow& p; -}; - -struct Action : Object { - bool enabled() const; - void setEnabled(bool enabled = true); - void setVisible(bool visible = true); - bool visible() const; - - Action(pAction& p); - ~Action(); - struct State; - State& state; - pAction& p; -}; - -struct Menu : private nall::base_from_member<pMenu&>, Action { - void append(const nall::group<Action>& list); - nall::image image() const; - void remove(const nall::group<Action>& list); - void setImage(const nall::image& image = nall::image{}); - void setText(const nall::string& text); - nall::string text() const; - - Menu(); - ~Menu(); - struct State; - State& state; - pMenu& p; -}; - -struct Separator : private nall::base_from_member<pSeparator&>, Action { - Separator(); - ~Separator(); - pSeparator& p; -}; - -struct Item : private nall::base_from_member<pItem&>, Action { - nall::function<void ()> onActivate; - - nall::image image() const; - void setImage(const nall::image& image = nall::image{}); - void setText(const nall::string& text); - nall::string text() const; - - Item(); - ~Item(); - struct State; - State& state; - pItem& p; -}; - -struct CheckItem : private nall::base_from_member<pCheckItem&>, Action { - nall::function<void ()> onToggle; - - bool checked() const; - void setChecked(bool checked = true); - void setText(const nall::string& text); - nall::string text() const; - - CheckItem(); - ~CheckItem(); - struct State; - State& state; - pCheckItem& p; -}; - -struct RadioItem : private nall::base_from_member<pRadioItem&>, Action { - template<typename... Args> static void group(Args&&... args) { group({std::forward<Args>(args)...}); } - static void group(const nall::group<RadioItem>& list); - - nall::function<void ()> onActivate; - - bool checked() const; - void setChecked(); - void setText(const nall::string& text); - nall::string text() const; - - RadioItem(); - ~RadioItem(); - struct State; - State& state; - pRadioItem& p; -}; - -struct Sizable : Object { - bool enabled() const; - bool enabledToAll() const; - Layout* layout() const; - virtual Size minimumSize() = 0; - Sizable* parent() const; - virtual void setEnabled(bool enabled = true) = 0; - virtual void setGeometry(Geometry geometry) = 0; - virtual void setVisible(bool visible = true) = 0; - virtual void synchronizeLayout() = 0; - bool visible() const; - bool visibleToAll() const; - Window* window() const; - - Sizable(pSizable& p); - ~Sizable(); - struct State; - State& state; - pSizable& p; -}; - -struct Layout : private nall::base_from_member<pLayout&>, Sizable { - virtual void append(Sizable& sizable); - virtual void remove(Sizable& sizable); - virtual void reset(); - - Layout(); - Layout(pLayout& p); - ~Layout(); - struct State; - State& state; - pLayout& p; -}; - -struct Widget : private nall::base_from_member<pWidget&>, Sizable { - nall::function<void ()> onSize; - - bool focused(); - nall::string font() const; - Geometry geometry() const; - Size minimumSize(); - void setEnabled(bool enabled = true); - void setFocused(); - void setFont(const nall::string& font); - void setGeometry(Geometry geometry); - void setVisible(bool visible = true); - void synchronizeLayout(); - - Widget(); - Widget(pWidget& p); - ~Widget(); - struct State; - State& state; - pWidget& p; -}; - -struct Button : private nall::base_from_member<pButton&>, Widget { - nall::function<void ()> onActivate; - - nall::image image() const; - Orientation orientation() const; - void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal); - void setText(const nall::string& text); - nall::string text() const; - - Button(); - ~Button(); - struct State; - State& state; - pButton& p; -}; - -struct Canvas : private nall::base_from_member<pCanvas&>, Widget { - enum class Mode : unsigned { Color, Gradient, Image, Data }; - - nall::function<void (nall::lstring)> onDrop; - nall::function<void ()> onMouseLeave; - nall::function<void (Position)> onMouseMove; - nall::function<void (Mouse::Button)> onMousePress; - nall::function<void (Mouse::Button)> onMouseRelease; - - Color color() const; - uint32_t* data() const; - bool droppable() const; - nall::vector<Color> gradient() const; - nall::image image() const; - Mode mode() const; - void setColor(Color color); - void setData(); - void setDroppable(bool droppable = true); - void setHorizontalGradient(Color left, Color right); - void setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight); - void setImage(const nall::image& image); - void setMode(Mode mode); - void setSize(Size size); - void setVerticalGradient(Color top, Color bottom); - Size size() const; - - Canvas(); - ~Canvas(); - struct State; - State& state; - pCanvas& p; -}; - -struct CheckButton : private nall::base_from_member<pCheckButton&>, Widget { - nall::function<void ()> onToggle; - - bool checked() const; - nall::image image() const; - void setChecked(bool checked = true); - void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal); - void setText(const nall::string& text); - nall::string text() const; - - CheckButton(); - ~CheckButton(); - struct State; - State& state; - pCheckButton& p; -}; - -struct CheckLabel : private nall::base_from_member<pCheckLabel&>, Widget { - nall::function<void ()> onToggle; - - bool checked() const; - void setChecked(bool checked = true); - void setText(const nall::string& text); - nall::string text() const; - - CheckLabel(); - ~CheckLabel(); - struct State; - State& state; - pCheckLabel& p; -}; - -struct ComboButton : private nall::base_from_member<pComboButton&>, Widget { - nall::function<void ()> onChange; - - void append(const nall::string& text = ""); - void remove(unsigned selection); - void reset(); - unsigned rows() const; - unsigned selection() const; - void setSelection(unsigned selection); - void setText(unsigned selection, const nall::string& text); - nall::string text() const; - nall::string text(unsigned selection) const; - - ComboButton(); - ~ComboButton(); - struct State; - State& state; - pComboButton& p; -}; - -struct Console : private nall::base_from_member<pConsole&>, Widget { - nall::function<void (nall::string)> onActivate; - - template<typename... Args> void print(Args&&... args) { print({args...}); } - - Color backgroundColor() const; - Color foregroundColor() const; - void print(const nall::string& text); - nall::string prompt() const; - void reset(); - void setBackgroundColor(Color color); - void setForegroundColor(Color color); - void setPrompt(const nall::string& prompt); - - Console(); - ~Console(); - struct State; - State& state; - pConsole& p; -}; - -struct Frame : private nall::base_from_member<pFrame&>, Widget { - void setLayout(Layout& layout); - void setText(const nall::string& text); - void synchronizeLayout(); - nall::string text() const; - - Frame(); - ~Frame(); - struct State; - State& state; - pFrame& p; -}; - -struct HexEdit : private nall::base_from_member<pHexEdit&>, Widget { - nall::function<uint8_t (unsigned)> onRead; - nall::function<void (unsigned, uint8_t)> onWrite; - - Color backgroundColor() const; - unsigned columns() const; - Color foregroundColor() const; - unsigned length() const; - unsigned offset() const; - unsigned rows() const; - void setBackgroundColor(Color color); - void setColumns(unsigned columns); - void setForegroundColor(Color color); - void setLength(unsigned length); - void setOffset(unsigned offset); - void setRows(unsigned rows); - void update(); - - HexEdit(); - ~HexEdit(); - struct State; - State& state; - pHexEdit& p; -}; - -struct HorizontalScroller : private nall::base_from_member<pHorizontalScroller&>, Widget { - nall::function<void ()> onChange; - - unsigned length() const; - unsigned position() const; - void setLength(unsigned length); - void setPosition(unsigned position); - - HorizontalScroller(); - ~HorizontalScroller(); - struct State; - State& state; - pHorizontalScroller& p; -}; - -struct HorizontalSlider : private nall::base_from_member<pHorizontalSlider&>, Widget { - nall::function<void ()> onChange; - - unsigned length() const; - unsigned position() const; - void setLength(unsigned length); - void setPosition(unsigned position); - - HorizontalSlider(); - ~HorizontalSlider(); - struct State; - State& state; - pHorizontalSlider& p; -}; - -struct Label : private nall::base_from_member<pLabel&>, Widget { - void setText(const nall::string& text); - nall::string text() const; - - Label(); - ~Label(); - struct State; - State& state; - pLabel& p; -}; - -struct LineEdit : private nall::base_from_member<pLineEdit&>, Widget { - nall::function<void ()> onActivate; - nall::function<void ()> onChange; - - Color backgroundColor() const; - bool editable() const; - Color foregroundColor() const; - void setBackgroundColor(Color color); - void setEditable(bool editable = true); - void setForegroundColor(Color color); - void setText(const nall::string& text); - nall::string text(); - - LineEdit(); - ~LineEdit(); - struct State; - State& state; - pLineEdit& p; -}; - -struct ListView : private nall::base_from_member<pListView&>, Widget { - nall::function<void ()> onActivate; - nall::function<void ()> onChange; - nall::function<void (unsigned)> onToggle; - - void append(const nall::lstring& text); - void autoSizeColumns(); - Color backgroundColor() const; - bool checkable() const; - bool checked(unsigned selection) const; - unsigned columns() const; - Color foregroundColor() const; - bool headerVisible() const; - nall::image image(unsigned selection, unsigned position) const; - void remove(unsigned selection); - void reset(); - unsigned rows() const; - bool selected() const; - unsigned selection() const; - void setBackgroundColor(Color color); - void setCheckable(bool checkable = true); - void setChecked(unsigned selection, bool checked = true); - void setForegroundColor(Color color); - void setHeaderText(const nall::lstring& text); - void setHeaderVisible(bool visible = true); - void setImage(unsigned selection, unsigned position, const nall::image& image = nall::image{}); - void setSelected(bool selected = true); - void setSelection(unsigned selection); - void setText(unsigned selection, const nall::lstring& text); - void setText(unsigned selection, unsigned position, const nall::string& text); - nall::string text(unsigned selection, unsigned position) const; - - ListView(); - ~ListView(); - struct State; - State& state; - pListView& p; -}; - -struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget { - unsigned position() const; - void setPosition(unsigned position); - - ProgressBar(); - ~ProgressBar(); - struct State; - State& state; - pProgressBar& p; -}; - -struct RadioButton : private nall::base_from_member<pRadioButton&>, Widget { - template<typename... Args> static void group(Args&&... args) { group({std::forward<Args>(args)...}); } - static void group(const nall::group<RadioButton>& list); - - nall::function<void ()> onActivate; - - bool checked() const; - nall::image image() const; - void setChecked(); - void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal); - void setText(const nall::string& text); - nall::string text() const; - - RadioButton(); - ~RadioButton(); - struct State; - State& state; - pRadioButton& p; -}; - -struct RadioLabel : private nall::base_from_member<pRadioLabel&>, Widget { - template<typename... Args> static void group(Args&&... args) { group({std::forward<Args>(args)...}); } - static void group(const nall::group<RadioLabel>& list); - - nall::function<void ()> onActivate; - - bool checked() const; - void setChecked(); - void setText(const nall::string& text); - nall::string text() const; - - RadioLabel(); - ~RadioLabel(); - struct State; - State& state; - pRadioLabel& p; -}; - -struct TabFrame : private nall::base_from_member<pTabFrame&>, Widget { - nall::function<void ()> onChange; - - void append(const nall::string& text = "", const nall::image& image = nall::image{}); - nall::image image(unsigned selection) const; - void remove(unsigned selection); - unsigned selection() const; - void setImage(unsigned selection, const nall::image& image = nall::image{}); - void setLayout(unsigned selection, Layout& layout); - void setSelection(unsigned selection); - void setText(unsigned selection, const nall::string& text); - void synchronizeLayout(); - unsigned tabs() const; - nall::string text(unsigned selection) const; - - TabFrame(); - ~TabFrame(); - struct State; - State& state; - pTabFrame& p; -}; - -struct TextEdit : private nall::base_from_member<pTextEdit&>, Widget { - nall::function<void ()> onChange; - - Color backgroundColor() const; - bool editable() const; - Color foregroundColor() const; - void setBackgroundColor(Color color); - void setCursorPosition(unsigned position); - void setEditable(bool editable = true); - void setForegroundColor(Color color); - void setText(const nall::string& text); - void setWordWrap(bool wordWrap = true); - nall::string text(); - bool wordWrap() const; - - TextEdit(); - ~TextEdit(); - struct State; - State& state; - pTextEdit& p; -}; - -struct VerticalScroller : private nall::base_from_member<pVerticalScroller&>, Widget { - nall::function<void ()> onChange; - - unsigned length() const; - unsigned position() const; - void setLength(unsigned length); - void setPosition(unsigned position); - - VerticalScroller(); - ~VerticalScroller(); - struct State; - State& state; - pVerticalScroller& p; -}; - -struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget { - nall::function<void ()> onChange; - - unsigned length() const; - unsigned position() const; - void setLength(unsigned length); - void setPosition(unsigned position); - - VerticalSlider(); - ~VerticalSlider(); - struct State; - State& state; - pVerticalSlider& p; -}; - -struct Viewport : private nall::base_from_member<pViewport&>, Widget { - nall::function<void (nall::lstring)> onDrop; - nall::function<void ()> onMouseLeave; - nall::function<void (Position)> onMouseMove; - nall::function<void (Mouse::Button)> onMousePress; - nall::function<void (Mouse::Button)> onMouseRelease; - - bool droppable() const; - uintptr_t handle(); - void setDroppable(bool droppable = true); - - Viewport(); - ~Viewport(); - struct State; - State& state; - pViewport& p; -}; - -#include "layout/fixed-layout.hpp" -#include "layout/horizontal-layout.hpp" -#include "layout/vertical-layout.hpp" - -} diff --git a/phoenix/core/keyboard.hpp b/phoenix/core/keyboard.hpp deleted file mode 100644 index ed04ec05..00000000 --- a/phoenix/core/keyboard.hpp +++ /dev/null @@ -1,45 +0,0 @@ -//each code refers to a physical key -//names are taken assuming: NumLock on, CapsLock off, Shift off -//layout uses US-104 keyboard -enum class Scancode : unsigned { - None, - - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, - Insert, Delete, Home, End, PageUp, PageDown, - Up, Down, Left, Right, - - Grave, Number1, Number2, Number3, Number4, Number5, Number6, Number7, Number8, Number9, Number0, Minus, Equal, Backspace, - BracketLeft, BracketRight, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Tab, CapsLock, Return, ShiftLeft, ShiftRight, ControlLeft, ControlRight, SuperLeft, SuperRight, AltLeft, AltRight, Space, Menu, - A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - - NumLock, Divide, Multiply, Subtract, Add, Enter, Point, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - - Limit, -}; - -//each enum refers to a translated scancode (eg Shift+1 = !) -enum class Keycode : unsigned { - None, - - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, SysRq, ScrollLock, Pause, Break, - Insert, Delete, Home, End, PageUp, PageDown, - Up, Down, Left, Right, - - Grave, Number1, Number2, Number3, Number4, Number5, Number6, Number7, Number8, Number9, Number0, Minus, Equal, Backspace, - Tilde, Exclamation, At, Pound, Dollar, Percent, Power, Ampersand, Asterisk, ParenthesisLeft, ParenthesisRight, Underscore, Plus, - BracketLeft, BracketRight, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - BraceLeft, BraceRight, Pipe, Colon, Quote, CaretLeft, CaretRight, Question, - Tab, CapsLock, Return, ShiftLeft, ShiftRight, ControlLeft, ControlRight, SuperLeft, SuperRight, AltLeft, AltRight, Space, Menu, - A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, - - NumLock, Divide, Multiply, Subtract, Add, Enter, Point, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - KeypadInsert, KeypadDelete, KeypadHome, KeypadEnd, KeypadPageUp, KeypadPageDown, KeypadUp, KeypadDown, KeypadLeft, KeypadRight, KeypadCenter, - - Limit, -}; diff --git a/phoenix/core/layout/fixed-layout.cpp b/phoenix/core/layout/fixed-layout.cpp deleted file mode 100644 index d29189e5..00000000 --- a/phoenix/core/layout/fixed-layout.cpp +++ /dev/null @@ -1,68 +0,0 @@ -void FixedLayout::append(Sizable& sizable, Geometry geometry) { - children.append({&sizable, geometry}); - synchronizeLayout(); - if(window()) window()->synchronizeLayout(); -} - -void FixedLayout::append(Sizable& sizable) { - for(auto& child : children) if(child.sizable == &sizable) return; - Layout::append(sizable); - if(window()) window()->synchronizeLayout(); -} - -Size FixedLayout::minimumSize() { - unsigned width = Size::Minimum, height = Size::Minimum; - for(auto& child : children) { - width = max(width, child.sizable->minimumSize().width); - height = max(height, child.sizable->minimumSize().height); - } - return {width, height}; -} - -void FixedLayout::remove(Sizable& sizable) { - for(unsigned n = 0; n < children.size(); n++) { - if(children[n].sizable == &sizable) { - children.remove(n); - Layout::remove(sizable); - if(window()) window()->synchronizeLayout(); - break; - } - } -} - -void FixedLayout::reset() { - for(auto& child : children) { - if(window() && dynamic_cast<Widget*>(child.sizable)) window()->remove((Widget&)*child.sizable); - } -} - -void FixedLayout::setEnabled(bool enabled) { - Sizable::state.enabled = enabled; - for(auto& child : children) { - child.sizable->setEnabled(child.sizable->enabled()); - } -} - -void FixedLayout::setGeometry(Geometry geometry) { -} - -void FixedLayout::setVisible(bool visible) { - Sizable::state.visible = visible; - for(auto& child : children) { - child.sizable->setVisible(child.sizable->visible()); - } -} - -void FixedLayout::synchronizeLayout() { - for(auto& child : children) { - Layout::append(*child.sizable); - Geometry childGeometry = child.geometry; - if((signed)childGeometry.width < 1) childGeometry.width = 1; - if((signed)childGeometry.height < 1) childGeometry.height = 1; - child.sizable->setGeometry(childGeometry); - } -} - -FixedLayout::~FixedLayout() { - while(children.size()) remove(*children[0].sizable); -} diff --git a/phoenix/core/layout/fixed-layout.hpp b/phoenix/core/layout/fixed-layout.hpp deleted file mode 100644 index 881bee76..00000000 --- a/phoenix/core/layout/fixed-layout.hpp +++ /dev/null @@ -1,19 +0,0 @@ -struct FixedLayout : Layout { - void append(Sizable& sizable, Geometry geometry); - void append(Sizable& sizable); - Size minimumSize(); - void remove(Sizable& sizable); - void reset(); - void setEnabled(bool enabled = true); - void setGeometry(Geometry geometry); - void setVisible(bool visible = true); - void synchronizeLayout(); - ~FixedLayout(); - -//private: - struct Children { - Sizable* sizable; - Geometry geometry; - }; - nall::vector<Children> children; -}; diff --git a/phoenix/core/layout/horizontal-layout.cpp b/phoenix/core/layout/horizontal-layout.cpp deleted file mode 100644 index 574d48e3..00000000 --- a/phoenix/core/layout/horizontal-layout.cpp +++ /dev/null @@ -1,127 +0,0 @@ -void HorizontalLayout::append(Sizable& sizable, Size size, unsigned spacing) { - for(auto& child : children) if(child.sizable == &sizable) return; - children.append({&sizable, size.width, size.height, spacing}); - synchronizeLayout(); - if(window()) window()->synchronizeLayout(); -} - -void HorizontalLayout::append(Sizable& sizable) { - for(auto& child : children) if(child.sizable == &sizable) return; - Layout::append(sizable); - if(window()) window()->synchronizeLayout(); -} - -Size HorizontalLayout::minimumSize() { - unsigned width = 0, height = 0; - - for(auto& child : children) { - width += child.spacing; - if(child.width == Size::Minimum || child.width == Size::Maximum) { - width += child.sizable->minimumSize().width; - continue; - } - width += child.width; - } - - for(auto& child : children) { - if(child.height == Size::Minimum || child.height == Size::Maximum) { - height = max(height, child.sizable->minimumSize().height); - continue; - } - height = max(height, child.height); - } - - return {state.margin * 2 + width, state.margin * 2 + height}; -} - -void HorizontalLayout::remove(Sizable& sizable) { - for(unsigned n = 0; n < children.size(); n++) { - if(children[n].sizable == &sizable) { - if(dynamic_cast<Layout*>(children[n].sizable)) { - Layout* layout = (Layout*)children[n].sizable; - layout->reset(); - } - children.remove(n); - Layout::remove(sizable); - if(window()) window()->synchronizeLayout(); - break; - } - } -} - -void HorizontalLayout::reset() { - for(auto& child : children) { - if(window() && dynamic_cast<Layout*>(child.sizable)) ((Layout*)child.sizable)->reset(); - if(window() && dynamic_cast<Widget*>(child.sizable)) window()->remove((Widget&)*child.sizable); - } -} - -void HorizontalLayout::setAlignment(double alignment) { - state.alignment = max(0.0, min(1.0, alignment)); -} - -void HorizontalLayout::setEnabled(bool enabled) { - Sizable::state.enabled = enabled; - for(auto& child : children) { - child.sizable->setEnabled(child.sizable->enabled()); - } -} - -void HorizontalLayout::setGeometry(Geometry containerGeometry) { - auto children = this->children; - for(auto& child : children) { - if(child.width == Size::Minimum) child.width = child.sizable->minimumSize().width; - if(child.height == Size::Minimum) child.height = child.sizable->minimumSize().height; - } - - Geometry geometry = containerGeometry; - geometry.x += state.margin; - geometry.y += state.margin; - geometry.width -= state.margin * 2; - geometry.height -= state.margin * 2; - - unsigned minimumWidth = 0, maximumWidthCounter = 0; - for(auto& child : children) { - if(child.width == Size::Maximum) maximumWidthCounter++; - if(child.width != Size::Maximum) minimumWidth += child.width; - minimumWidth += child.spacing; - } - - for(auto& child : children) { - if(child.width == Size::Maximum) child.width = (geometry.width - minimumWidth) / maximumWidthCounter; - if(child.height == Size::Maximum) child.height = geometry.height; - } - - unsigned maximumHeight = 0; - for(auto& child : children) maximumHeight = max(maximumHeight, child.height); - - for(auto& child : children) { - unsigned pivot = (maximumHeight - child.height) * state.alignment; - Geometry childGeometry = {geometry.x, geometry.y + pivot, child.width, child.height}; - if((signed)childGeometry.width < 1) childGeometry.width = 1; - if((signed)childGeometry.height < 1) childGeometry.height = 1; - child.sizable->setGeometry(childGeometry); - - geometry.x += child.width + child.spacing; - geometry.width -= child.width + child.spacing; - } -} - -void HorizontalLayout::setMargin(unsigned margin) { - state.margin = margin; -} - -void HorizontalLayout::setVisible(bool visible) { - Sizable::state.visible = visible; - for(auto& child : children) { - child.sizable->setVisible(child.sizable->visible()); - } -} - -void HorizontalLayout::synchronizeLayout() { - for(auto& child : children) Layout::append(*child.sizable); -} - -HorizontalLayout::~HorizontalLayout() { - while(children.size()) remove(*children[0].sizable); -} diff --git a/phoenix/core/layout/horizontal-layout.hpp b/phoenix/core/layout/horizontal-layout.hpp deleted file mode 100644 index c12eda8b..00000000 --- a/phoenix/core/layout/horizontal-layout.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct HorizontalLayout : public Layout { - void append(Sizable& sizable, Size size, unsigned spacing = 0); - void append(Sizable& sizable); - Size minimumSize(); - void remove(Sizable& sizable); - void reset(); - void setAlignment(double alignment); - void setEnabled(bool enabled = true); - void setGeometry(Geometry geometry); - void setMargin(unsigned margin); - void setVisible(bool visible = true); - void synchronizeLayout(); - ~HorizontalLayout(); - -//private: - struct State { - double alignment = 0.5; - unsigned margin = 0; - } state; - - struct Children { - Sizable* sizable; - unsigned width, height, spacing; - }; - nall::vector<Children> children; -}; diff --git a/phoenix/core/layout/vertical-layout.cpp b/phoenix/core/layout/vertical-layout.cpp deleted file mode 100644 index 804a26db..00000000 --- a/phoenix/core/layout/vertical-layout.cpp +++ /dev/null @@ -1,127 +0,0 @@ -void VerticalLayout::append(Sizable& sizable, Size size, unsigned spacing) { - for(auto& child : children) if(child.sizable == &sizable) return; - children.append({&sizable, size.width, size.height, spacing}); - synchronizeLayout(); - if(window()) window()->synchronizeLayout(); -} - -void VerticalLayout::append(Sizable& sizable) { - for(auto& child : children) if(child.sizable == &sizable) return; - Layout::append(sizable); - if(window()) window()->synchronizeLayout(); -} - -Size VerticalLayout::minimumSize() { - unsigned width = 0, height = 0; - - for(auto& child : children) { - if(child.width == Size::Minimum || child.width == Size::Maximum) { - width = max(width, child.sizable->minimumSize().width); - continue; - } - width = max(width, child.width); - } - - for(auto& child : children) { - height += child.spacing; - if(child.height == Size::Minimum || child.height == Size::Maximum) { - height += child.sizable->minimumSize().height; - continue; - } - height += child.height; - } - - return {state.margin * 2 + width, state.margin * 2 + height}; -} - -void VerticalLayout::remove(Sizable& sizable) { - for(unsigned n = 0; n < children.size(); n++) { - if(children[n].sizable == &sizable) { - if(dynamic_cast<Layout*>(children[n].sizable)) { - Layout* layout = (Layout*)children[n].sizable; - layout->reset(); - } - children.remove(n); - Layout::remove(sizable); - if(window()) window()->synchronizeLayout(); - break; - } - } -} - -void VerticalLayout::reset() { - for(auto& child : children) { - if(window() && dynamic_cast<Layout*>(child.sizable)) ((Layout*)child.sizable)->reset(); - if(window() && dynamic_cast<Widget*>(child.sizable)) window()->remove((Widget&)*child.sizable); - } -} - -void VerticalLayout::setAlignment(double alignment) { - state.alignment = max(0.0, min(1.0, alignment)); -} - -void VerticalLayout::setEnabled(bool enabled) { - Sizable::state.enabled = enabled; - for(auto& child : children) { - child.sizable->setEnabled(child.sizable->enabled()); - } -} - -void VerticalLayout::setGeometry(Geometry containerGeometry) { - auto children = this->children; - for(auto& child : children) { - if(child.width == Size::Minimum) child.width = child.sizable->minimumSize().width; - if(child.height == Size::Minimum) child.height = child.sizable->minimumSize().height; - } - - Geometry geometry = containerGeometry; - geometry.x += state.margin; - geometry.y += state.margin; - geometry.width -= state.margin * 2; - geometry.height -= state.margin * 2; - - unsigned minimumHeight = 0, maximumHeightCounter = 0; - for(auto& child : children) { - if(child.height == Size::Maximum) maximumHeightCounter++; - if(child.height != Size::Maximum) minimumHeight += child.height; - minimumHeight += child.spacing; - } - - for(auto& child : children) { - if(child.width == Size::Maximum) child.width = geometry.width; - if(child.height == Size::Maximum) child.height = (geometry.height - minimumHeight) / maximumHeightCounter; - } - - unsigned maximumWidth = 0; - for(auto& child : children) maximumWidth = max(maximumWidth, child.width); - - for(auto& child : children) { - unsigned pivot = (maximumWidth - child.width) * state.alignment; - Geometry childGeometry = {geometry.x + pivot, geometry.y, child.width, child.height}; - if((signed)childGeometry.width < 1) childGeometry.width = 1; - if((signed)childGeometry.height < 1) childGeometry.height = 1; - child.sizable->setGeometry(childGeometry); - - geometry.y += child.height + child.spacing; - geometry.height -= child.height + child.spacing; - } -} - -void VerticalLayout::setMargin(unsigned margin) { - state.margin = margin; -} - -void VerticalLayout::setVisible(bool visible) { - Sizable::state.visible = visible; - for(auto& child : children) { - child.sizable->setVisible(child.sizable->visible()); - } -} - -void VerticalLayout::synchronizeLayout() { - for(auto& child : children) Layout::append(*child.sizable); -} - -VerticalLayout::~VerticalLayout() { - while(children.size()) remove(*children[0].sizable); -} diff --git a/phoenix/core/layout/vertical-layout.hpp b/phoenix/core/layout/vertical-layout.hpp deleted file mode 100644 index db96d6e7..00000000 --- a/phoenix/core/layout/vertical-layout.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct VerticalLayout : public Layout { - void append(Sizable& sizable, Size size, unsigned spacing = 0); - void append(Sizable& sizable); - Size minimumSize(); - void remove(Sizable& sizable); - void reset(); - void setAlignment(double alignment); - void setEnabled(bool enabled = true); - void setGeometry(Geometry geometry); - void setMargin(unsigned margin); - void setVisible(bool visible = true); - void synchronizeLayout(); - ~VerticalLayout(); - -//private: - struct State { - double alignment = 0.0; - unsigned margin = 0; - } state; - - struct Children { - Sizable* sizable; - unsigned width, height, spacing; - }; - nall::vector<Children> children; -}; diff --git a/phoenix/core/state.hpp b/phoenix/core/state.hpp deleted file mode 100644 index 3a48de87..00000000 --- a/phoenix/core/state.hpp +++ /dev/null @@ -1,227 +0,0 @@ -struct Application::State { - string name; - bool quit = false; -} applicationState; - -struct Timer::State { - bool enabled = false; - unsigned interval = 0; -}; - -struct BrowserWindow::State { - lstring filters; - Window* parent = nullptr; - string path; - string title; -}; - -struct MessageWindow::State { - MessageWindow::Buttons buttons = MessageWindow::Buttons::Ok; - Window* parent = nullptr; - string text; - string title; -}; - -struct Window::State { - bool backgroundColorOverride = false; - Color backgroundColor = {0, 0, 0}; - bool droppable = false; - bool fullScreen = false; - Geometry geometry = {128, 128, 256, 256}; - group<Layout> layout; - group<Menu> menu; - string menuFont; - bool menuVisible = false; - bool modal = false; - bool resizable = true; - string statusFont; - string statusText; - bool statusVisible = false; - string title; - bool visible = false; - group<Widget> widget; - string widgetFont; -}; - -struct Action::State { - bool enabled = true; - Menu* menu = nullptr; - bool visible = true; - Window* window = nullptr; -}; - -struct Menu::State { - group<Action> action; - nall::image image; - string text; -}; - -struct Item::State { - nall::image image; - string text; -}; - -struct CheckItem::State { - bool checked = false; - string text; -}; - -struct RadioItem::State { - bool checked = true; - nall::group<RadioItem> group; - string text; -}; - -struct Sizable::State { - bool enabled = true; - Sizable* parent = nullptr; - bool visible = true; - Window* window = nullptr; -}; - -struct Layout::State { - Widget* widget = nullptr; - unsigned widgetSelection = 0; -}; - -struct Widget::State { - bool abstract = false; - string font; - Geometry geometry = {0, 0, 0, 0}; -}; - -struct Button::State { - nall::image image; - Orientation orientation = Orientation::Horizontal; - string text; -}; - -struct Canvas::State { - Color color; - uint32_t* data = nullptr; - bool droppable = false; - vector<Color> gradient = {{}, {}, {}, {}}; - nall::image image; - Canvas::Mode mode = Canvas::Mode::Color; - unsigned width = 0; - unsigned height = 0; -}; - -struct CheckButton::State { - bool checked = false; - nall::image image; - Orientation orientation = Orientation::Horizontal; - string text; -}; - -struct CheckLabel::State { - bool checked = false; - string text; -}; - -struct ComboButton::State { - unsigned selection = 0; - vector<string> text; -}; - -struct Console::State { - Color backgroundColor = {255, 255, 255}; - Color foregroundColor = {0, 0, 0}; - string prompt; -}; - -struct Frame::State { - Layout* layout = nullptr; - string text; -}; - -struct HexEdit::State { - Color backgroundColor = {255, 255, 255}; - unsigned columns = 16; - Color foregroundColor = {0, 0, 0}; - unsigned length = 0; - unsigned offset = 0; - unsigned rows = 16; -}; - -struct HorizontalScroller::State { - unsigned length = 101; - unsigned position = 0; -}; - -struct HorizontalSlider::State { - unsigned length = 101; - unsigned position = 0; -}; - -struct Label::State { - string text; -}; - -struct LineEdit::State { - Color backgroundColor = {255, 255, 255}; - bool editable = true; - Color foregroundColor = {0, 0, 0}; - string text; -}; - -struct ListView::State { - Color backgroundColor = {255, 255, 255}; - bool checkable = false; - vector<bool> checked; - Color foregroundColor = {0, 0, 0}; - lstring headerText; - bool headerVisible = false; - vector<vector<nall::image>> image; - bool selected = false; - unsigned selection = 0; - vector<lstring> text; -}; - -struct ProgressBar::State { - unsigned position = 0; -}; - -struct RadioButton::State { - bool checked = true; - nall::group<RadioButton> group; - nall::image image; - Orientation orientation = Orientation::Horizontal; - string text; -}; - -struct RadioLabel::State { - bool checked = true; - nall::group<RadioLabel> group; - string text; -}; - -struct TabFrame::State { - vector<nall::image> image; - vector<Layout*> layout; - unsigned selection = 0; - lstring text; -}; - -struct TextEdit::State { - Color backgroundColor = {255, 255, 255}; - unsigned cursorPosition = 0; - bool editable = true; - Color foregroundColor = {0, 0, 0}; - string text; - bool wordWrap = true; -}; - -struct VerticalScroller::State { - unsigned length = 101; - unsigned position = 0; -}; - -struct VerticalSlider::State { - unsigned length = 101; - unsigned position = 0; -}; - -struct Viewport::State { - bool droppable = false; -}; diff --git a/phoenix/gtk/action/check-item.cpp b/phoenix/gtk/action/check-item.cpp deleted file mode 100644 index 59d6299b..00000000 --- a/phoenix/gtk/action/check-item.cpp +++ /dev/null @@ -1,34 +0,0 @@ -namespace phoenix { - -static void CheckItem_toggle(GtkCheckMenuItem* gtkCheckMenuItem, CheckItem* self) { - self->state.checked = gtk_check_menu_item_get_active(gtkCheckMenuItem); - if(!self->p.locked && self->onToggle) self->onToggle(); -} - -void pCheckItem::setChecked(bool checked) { - locked = true; - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), checked); - locked = false; -} - -void pCheckItem::setText(string text) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), mnemonic(text)); -} - -void pCheckItem::constructor() { - widget = gtk_check_menu_item_new_with_mnemonic(""); - setChecked(checkItem.state.checked); - setText(checkItem.state.text); - g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_toggle), (gpointer)&checkItem); -} - -void pCheckItem::destructor() { - gtk_widget_destroy(widget); -} - -void pCheckItem::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/action/item.cpp b/phoenix/gtk/action/item.cpp deleted file mode 100644 index 29b053e4..00000000 --- a/phoenix/gtk/action/item.cpp +++ /dev/null @@ -1,35 +0,0 @@ -namespace phoenix { - -static void Item_activate(Item* self) { - if(self->onActivate) self->onActivate(); -} - -void pItem::setImage(const image& image) { - if(image.empty() == false) { - GtkImage* gtkImage = CreateImage(image, true); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage); - } else { - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr); - } -} - -void pItem::setText(string text) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), mnemonic(text)); -} - -void pItem::constructor() { - widget = gtk_image_menu_item_new_with_mnemonic(""); - g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_activate), (gpointer)&item); - setText(item.state.text); -} - -void pItem::destructor() { - gtk_widget_destroy(widget); -} - -void pItem::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/action/menu.cpp b/phoenix/gtk/action/menu.cpp deleted file mode 100644 index c0e4b375..00000000 --- a/phoenix/gtk/action/menu.cpp +++ /dev/null @@ -1,55 +0,0 @@ -namespace phoenix { - -void pMenu::append(Action& action) { - action.state.window = this->action.state.window; - - gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), action.p.widget); - if(action.state.window && action.state.window->state.menuFont != "") { - action.p.setFont(action.state.window->state.menuFont); - } - gtk_widget_show(action.p.widget); -} - -void pMenu::remove(Action& action) { - action.p.orphan(); - action.state.window = nullptr; -} - -void pMenu::setImage(const image& image) { - if(image.empty() == false) { - GtkImage* gtkImage = CreateImage(image, true); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage); - } else { - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr); - } -} - -void pMenu::setText(string text) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), mnemonic(text)); -} - -void pMenu::constructor() { - gtkMenu = gtk_menu_new(); - widget = gtk_image_menu_item_new_with_mnemonic(""); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), gtkMenu); - setText(menu.state.text); -} - -void pMenu::destructor() { - gtk_widget_destroy(gtkMenu); - gtk_widget_destroy(widget); -} - -void pMenu::orphan() { - for(auto& action : menu.state.action) action.p.orphan(); - destructor(); - constructor(); - for(auto& action : menu.state.action) append(action); -} - -void pMenu::setFont(string font) { - pAction::setFont(font); - for(auto& item : menu.state.action) item.p.setFont(font); -} - -} diff --git a/phoenix/gtk/action/radio-item.cpp b/phoenix/gtk/action/radio-item.cpp deleted file mode 100644 index f00f9a76..00000000 --- a/phoenix/gtk/action/radio-item.cpp +++ /dev/null @@ -1,62 +0,0 @@ -namespace phoenix { - -static void RadioItem_activate(GtkCheckMenuItem* gtkCheckMenuItem, RadioItem* self) { - self->p.onActivate(); -} - -void pRadioItem::setChecked() { - parent().locked = true; - for(auto& item : radioItem.state.group) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), false); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), true); - parent().locked = false; -} - -void pRadioItem::setGroup(const group<RadioItem>& group) { - parent().locked = true; - for(auto& item : group) { - if(&item == &group.first()) continue; - GSList* currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group.first().p.widget)); - if(currentGroup != gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item.p.widget))) { - gtk_radio_menu_item_set_group(GTK_RADIO_MENU_ITEM(item.p.widget), currentGroup); - } - } - parent().locked = false; -} - -void pRadioItem::setText(string text) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), mnemonic(text)); -} - -void pRadioItem::constructor() { - widget = gtk_radio_menu_item_new_with_mnemonic(0, ""); - setGroup(radioItem.state.group); - setText(radioItem.state.text); - for(auto& item : radioItem.state.group) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), item.state.checked); - } - g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_activate), (gpointer)&radioItem); -} - -void pRadioItem::destructor() { - gtk_widget_destroy(widget); -} - -void pRadioItem::orphan() { - destructor(); - constructor(); -} - -void pRadioItem::onActivate() { - if(parent().locked) return; - bool wasChecked = radioItem.state.checked; - radioItem.setChecked(); - if(wasChecked) return; - if(radioItem.onActivate) radioItem.onActivate(); -} - -pRadioItem& pRadioItem::parent() { - if(radioItem.state.group.size()) return radioItem.state.group.first().p; - return *this; -} - -} diff --git a/phoenix/gtk/action/separator.cpp b/phoenix/gtk/action/separator.cpp deleted file mode 100644 index 0db95b2c..00000000 --- a/phoenix/gtk/action/separator.cpp +++ /dev/null @@ -1,16 +0,0 @@ -namespace phoenix { - -void pSeparator::constructor() { - widget = gtk_separator_menu_item_new(); -} - -void pSeparator::destructor() { - gtk_widget_destroy(widget); -} - -void pSeparator::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/application.cpp b/phoenix/gtk/application.cpp deleted file mode 100644 index 35091107..00000000 --- a/phoenix/gtk/application.cpp +++ /dev/null @@ -1,60 +0,0 @@ -namespace phoenix { - -XlibDisplay* pApplication::display = nullptr; - -void pApplication::run() { - if(Application::main) { - while(applicationState.quit == false) { - processEvents(); - Application::main(); - } - } else { - gtk_main(); - } -} - -bool pApplication::pendingEvents() { - return gtk_events_pending(); -} - -void pApplication::processEvents() { - while(pendingEvents()) gtk_main_iteration_do(false); -} - -void pApplication::quit() { - //if gtk_main() was invoked, call gtk_main_quit() - if(gtk_main_level()) gtk_main_quit(); -} - -void pApplication::initialize() { - display = XOpenDisplay(nullptr); - - settings = new Settings; - settings->load(); - - int argc = 1; - char* argv[] = {new char[8], nullptr}; - strcpy(argv[0], "phoenix"); - char** argvp = argv; - gtk_init(&argc, &argvp); - - GtkSettings* gtkSettings = gtk_settings_get_default(); -//g_object_set(gtkSettings, "gtk-button-images", true, nullptr); - - gtk_rc_parse_string(R"( - style "phoenix-gtk" - { - GtkWindow::resize-grip-width = 0 - GtkWindow::resize-grip-height = 0 - GtkTreeView::vertical-separator = 0 - GtkComboBox::appears-as-list = 1 - } - class "GtkWindow" style "phoenix-gtk" - class "GtkTreeView" style "phoenix-gtk" - # class "GtkComboBox" style "phoenix-gtk" - )"); - - pKeyboard::initialize(); -} - -} diff --git a/phoenix/gtk/platform.hpp b/phoenix/gtk/platform.hpp deleted file mode 100644 index ead42f24..00000000 --- a/phoenix/gtk/platform.hpp +++ /dev/null @@ -1,640 +0,0 @@ -namespace phoenix { - -struct pApplication { - static XlibDisplay* display; - - static void run(); - static bool pendingEvents(); - static void processEvents(); - static void quit(); - - static void initialize(); -}; - -struct Settings : Configuration::Document { - bimap<Keyboard::Scancode, unsigned> keymap; - - struct Geometry : Configuration::Node { - unsigned frameX; - unsigned frameY; - unsigned frameWidth; - unsigned frameHeight; - unsigned menuHeight; - unsigned statusHeight; - } geometry; - - struct Window : Configuration::Node { - unsigned backgroundColor; - } window; - - void load(); - void save(); - Settings(); -}; - -struct pWindow; -struct pMenu; -struct pLayout; -struct pWidget; - -struct pFont { - static string serif(unsigned size, string style); - static string sans(unsigned size, string style); - static string monospace(unsigned size, string style); - static Size size(string font, string text); - - static PangoFontDescription* create(string description); - static void free(PangoFontDescription* font); - static Size size(PangoFontDescription* font, string text); - static void setFont(GtkWidget* widget, string font); - static void setFont(GtkWidget* widget, gpointer font); -}; - -struct pDesktop { - static Size size(); - static Geometry workspace(); -}; - -struct pMonitor { - static unsigned count(); - static Geometry geometry(unsigned monitor); - static unsigned primary(); -}; - -struct pKeyboard { - static bool pressed(Keyboard::Scancode scancode); - static vector<bool> state(); - - static void initialize(); -}; - -struct pMouse { - static Position position(); - static bool pressed(Mouse::Button button); -}; - -struct pBrowserWindow { - static string directory(BrowserWindow::State& state); - static string open(BrowserWindow::State& state); - static string save(BrowserWindow::State& state); -}; - -struct pMessageWindow { - static MessageWindow::Response error(MessageWindow::State& state); - static MessageWindow::Response information(MessageWindow::State& state); - static MessageWindow::Response question(MessageWindow::State& state); - static MessageWindow::Response warning(MessageWindow::State& state); -}; - -struct pObject { - Object& object; - bool locked; - - pObject(Object& object) : object(object), locked(false) {} - virtual ~pObject() {} - - void constructor() {} - void destructor() {} -}; - -struct pTimer : public pObject { - Timer& timer; - - void setEnabled(bool enabled); - void setInterval(unsigned interval); - - pTimer(Timer& timer) : pObject(timer), timer(timer) {} - void constructor(); -}; - -struct pWindow : public pObject { - Window& window; - GtkWidget* widget; - GtkWidget* menuContainer; - GtkWidget* formContainer; - GtkWidget* statusContainer; - GtkWidget* menu; - GtkWidget* status; - GtkAllocation lastAllocation; - bool onSizePending; - - static Window& none(); - - void append(Layout& layout); - void append(Menu& menu); - void append(Widget& widget); - bool focused(); - Geometry frameMargin(); - Geometry geometry(); - void remove(Layout& layout); - void remove(Menu& menu); - void remove(Widget& widget); - void setBackgroundColor(Color color); - void setDroppable(bool droppable); - void setFocused(); - void setFullScreen(bool fullScreen); - void setGeometry(Geometry geometry); - void setMenuFont(string font); - void setMenuVisible(bool visible); - void setModal(bool modal); - void setResizable(bool resizable); - void setStatusFont(string font); - void setStatusText(string text); - void setStatusVisible(bool visible); - void setTitle(string text); - void setVisible(bool visible); - void setWidgetFont(string font); - - pWindow(Window& window) : pObject(window), window(window) {} - void constructor(); - unsigned menuHeight(); - unsigned statusHeight(); -}; - -struct pAction : public pObject { - Action& action; - GtkWidget* widget; - - void setEnabled(bool enabled); - void setVisible(bool visible); - - pAction(Action& action) : pObject(action), action(action) {} - void constructor(); - virtual void orphan(); - string mnemonic(string text); - virtual void setFont(string font); -}; - -struct pMenu : public pAction { - Menu& menu; - GtkWidget* gtkMenu; - - void append(Action& action); - void remove(Action& action); - void setImage(const image& image); - void setText(string text); - - pMenu(Menu &menu) : pAction(menu), menu(menu) {} - void constructor(); - void destructor(); - void orphan(); - void setFont(string font); -}; - -struct pSeparator : public pAction { - Separator& separator; - - pSeparator(Separator& separator) : pAction(separator), separator(separator) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pItem : public pAction { - Item& item; - - void setImage(const image& image); - void setText(string text); - - pItem(Item& item) : pAction(item), item(item) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pCheckItem : public pAction { - CheckItem& checkItem; - - void setChecked(bool checked); - void setText(string text); - - pCheckItem(CheckItem& checkItem) : pAction(checkItem), checkItem(checkItem) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pRadioItem : public pAction { - RadioItem& radioItem; - - void setChecked(); - void setGroup(const group<RadioItem>& group); - void setText(string text); - - pRadioItem(RadioItem& radioItem) : pAction(radioItem), radioItem(radioItem) {} - void constructor(); - void destructor(); - void orphan(); - void onActivate(); - pRadioItem& parent(); -}; - -struct pSizable : public pObject { - Sizable& sizable; - - virtual Position displacement() { return {0, 0}; } - - pSizable(Sizable &sizable) : pObject(sizable), sizable(sizable) {} -}; - -struct pLayout : public pSizable { - Layout& layout; - - pLayout(Layout& layout) : pSizable(layout), layout(layout) {} -}; - -struct pWidget : public pSizable { - Widget& widget; - GtkWidget* gtkWidget = nullptr; - GtkWidget* gtkParent = nullptr; - - virtual GtkWidget* container(Widget& widget); - virtual bool focused(); - virtual Size minimumSize(); - virtual void setEnabled(bool enabled); - virtual void setFocused(); - virtual void setFont(string font); - virtual void setGeometry(Geometry geometry); - virtual void setVisible(bool visible); - - pWidget(Widget& widget) : pSizable(widget), widget(widget) {} - void constructor(); - void destructor(); - virtual void orphan(); -}; - -struct pButton : public pWidget { - Button& button; - - Size minimumSize(); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pButton(Button& button) : pWidget(button), button(button) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pCanvas : public pWidget { - Canvas& canvas; - GdkPixbuf* surface = nullptr; - unsigned surfaceWidth = 0; - unsigned surfaceHeight = 0; - - Size minimumSize(); - void setDroppable(bool droppable); - void setGeometry(Geometry geometry); - void setMode(Canvas::Mode mode); - void setSize(Size size); - - pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {} - void constructor(); - void destructor(); - void orphan(); - void onExpose(GdkEventExpose* event); - void rasterize(); - void redraw(); - void release(); -}; - -struct pCheckButton : public pWidget { - CheckButton& checkButton; - - Size minimumSize(); - void setChecked(bool checked); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {} - void constructor(); - void destructor(); - void orphan(); - void onToggle(); -}; - -struct pCheckLabel : public pWidget { - CheckLabel& checkLabel; - - Size minimumSize(); - void setChecked(bool checked); - void setText(string text); - - pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pComboButton : public pWidget { - ComboButton& comboButton; - unsigned itemCounter; - - void append(string text); - Size minimumSize(); - void remove(unsigned selection); - void reset(); - void setSelection(unsigned selection); - void setText(unsigned selection, string text); - - pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pConsole : public pWidget { - Console& console; - GtkWidget* subWidget; - GtkTextBuffer* textBuffer; - string previousPrompt; - lstring history; - unsigned historyOffset = 0; - - void print(string text); - void reset(); - void setBackgroundColor(Color color); - void setForegroundColor(Color color); - void setPrompt(string prompt); - - pConsole(Console& console) : pWidget(console), console(console) {} - void constructor(); - void destructor(); - void orphan(); - bool keyPress(unsigned scancode, unsigned mask); - void seekToEnd(); - void seekToMark(); -}; - -struct pFrame : public pWidget { - Frame& frame; - - GtkWidget* container(Widget& widget); - Position containerOffset(); - void setEnabled(bool enabled); - void setGeometry(Geometry geometry); - void setText(string text); - void setVisible(bool visible); - - pFrame(Frame& frame) : pWidget(frame), frame(frame) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pHexEdit : public pWidget { - HexEdit& hexEdit; - GtkWidget* container; - GtkWidget* subWidget; - GtkWidget* scrollBar; - GtkTextBuffer* textBuffer; - GtkTextMark* textCursor; - - bool focused(); - void setBackgroundColor(Color color); - void setColumns(unsigned columns); - void setForegroundColor(Color color); - void setLength(unsigned length); - void setOffset(unsigned offset); - void setRows(unsigned rows); - void update(); - - pHexEdit(HexEdit& hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {} - void constructor(); - void destructor(); - void orphan(); - unsigned cursorPosition(); - bool keyPress(unsigned scancode, unsigned mask); - signed rows(); - signed rowsScrollable(); - void scroll(signed position); - void setCursorPosition(unsigned position); - void setScroll(); - void updateScroll(); -}; - -struct pHorizontalScroller : public pWidget { - HorizontalScroller& horizontalScroller; - - Size minimumSize(); - void setLength(unsigned length); - void setPosition(unsigned position); - - pHorizontalScroller(HorizontalScroller& horizontalScroller) : pWidget(horizontalScroller), horizontalScroller(horizontalScroller) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pHorizontalSlider : public pWidget { - HorizontalSlider& horizontalSlider; - - Size minimumSize(); - void setLength(unsigned length); - void setPosition(unsigned position); - - pHorizontalSlider(HorizontalSlider& horizontalSlider) : pWidget(horizontalSlider), horizontalSlider(horizontalSlider) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pLabel : public pWidget { - Label& label; - - Size minimumSize(); - void setText(string text); - - pLabel(Label& label) : pWidget(label), label(label) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pLineEdit : public pWidget { - LineEdit& lineEdit; - - Size minimumSize(); - void setBackgroundColor(Color color); - void setEditable(bool editable); - void setForegroundColor(Color color); - void setText(string text); - string text(); - - pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pListView : public pWidget { - ListView& listView; - GtkWidget* subWidget; - GtkListStore* store; - struct GtkColumn { - GtkTreeViewColumn* column; - GtkCellRenderer* checkbutton; - GtkCellRenderer* icon; - GtkCellRenderer* text; - GtkWidget *label; - }; - vector<GtkColumn> column; - - void append(const lstring& text); - void autoSizeColumns(); - bool focused(); - void remove(unsigned selection); - void reset(); - void setBackgroundColor(Color color); - void setCheckable(bool checkable); - void setChecked(unsigned selection, bool checked); - void setForegroundColor(Color color); - void setHeaderText(const lstring& text); - void setHeaderVisible(bool visible); - void setImage(unsigned selection, unsigned position, const image& image); - void setSelected(bool selected); - void setSelection(unsigned row); - void setText(unsigned selection, unsigned position, string text); - - pListView(ListView& listView) : pWidget(listView), listView(listView) {} - void constructor(); - void destructor(); - void orphan(); - void setFocused(); - void setFont(string font); -}; - -struct pProgressBar : public pWidget { - ProgressBar& progressBar; - - Size minimumSize(); - void setPosition(unsigned position); - - pProgressBar(ProgressBar& progressBar) : pWidget(progressBar), progressBar(progressBar) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pRadioButton : public pWidget { - RadioButton& radioButton; - - Size minimumSize(); - void setChecked(); - void setGroup(const group<RadioButton>& group); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {} - void constructor(); - void destructor(); - void orphan(); - void onActivate(); - pRadioButton& parent(); -}; - -struct pRadioLabel : public pWidget { - RadioLabel& radioLabel; - - Size minimumSize(); - void setChecked(); - void setGroup(const group<RadioLabel>& group); - void setText(string text); - - pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {} - void onActivate(); - pRadioLabel& parent(); - void constructor(); - void destructor(); - void orphan(); -}; - -struct pTabFrame : public pWidget { - TabFrame& tabFrame; - struct Tab { - GtkWidget* child; - GtkWidget* container; - GtkWidget* layout; - GtkWidget* image; - GtkWidget* title; - }; - vector<Tab> tabs; - - void append(string text, const image& image); - GtkWidget* container(Widget& widget); - Position displacement(); - void remove(unsigned selection); - void setEnabled(bool enabled); - void setGeometry(Geometry geometry); - void setImage(unsigned selection, const image& image); - void setSelection(unsigned selection); - void setText(unsigned selection, string text); - void setVisible(bool visible); - - pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {} - void constructor(); - void destructor(); - void orphan(); - void setFont(string font); - void synchronizeLayout(); -}; - -struct pTextEdit : public pWidget { - TextEdit& textEdit; - GtkWidget* subWidget; - GtkTextBuffer* textBuffer; - - bool focused(); - void setBackgroundColor(Color color); - void setCursorPosition(unsigned position); - void setEditable(bool editable); - void setForegroundColor(Color color); - void setText(string text); - void setWordWrap(bool wordWrap); - string text(); - - pTextEdit(TextEdit& textEdit) : pWidget(textEdit), textEdit(textEdit) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pVerticalScroller : public pWidget { - VerticalScroller& verticalScroller; - - Size minimumSize(); - void setLength(unsigned length); - void setPosition(unsigned position); - - pVerticalScroller(VerticalScroller& verticalScroller) : pWidget(verticalScroller), verticalScroller(verticalScroller) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pVerticalSlider : public pWidget { - VerticalSlider& verticalSlider; - - Size minimumSize(); - void setLength(unsigned length); - void setPosition(unsigned position); - - pVerticalSlider(VerticalSlider& verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {} - void constructor(); - void destructor(); - void orphan(); -}; - -struct pViewport : public pWidget { - Viewport& viewport; - - uintptr_t handle(); - void setDroppable(bool droppable); - - pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {} - void constructor(); - void destructor(); - void orphan(); -}; - -} diff --git a/phoenix/gtk/timer.cpp b/phoenix/gtk/timer.cpp deleted file mode 100644 index 3be9964f..00000000 --- a/phoenix/gtk/timer.cpp +++ /dev/null @@ -1,28 +0,0 @@ -namespace phoenix { - -static guint Timer_trigger(pTimer* self) { - //timer may have been disabled prior to triggering, so check state - if(self->timer.state.enabled) { - if(self->timer.onActivate) self->timer.onActivate(); - } - //callback may have disabled timer, so check state again - if(self->timer.state.enabled) { - g_timeout_add(self->timer.state.interval, (GSourceFunc)Timer_trigger, (gpointer)self); - } - //kill this timer instance (it is spawned above if needed again) - return false; -} - -void pTimer::setEnabled(bool enabled) { - if(enabled) { - g_timeout_add(timer.state.interval, (GSourceFunc)Timer_trigger, (gpointer)this); - } -} - -void pTimer::setInterval(unsigned interval) { -} - -void pTimer::constructor() { -} - -} diff --git a/phoenix/gtk/utility.cpp b/phoenix/gtk/utility.cpp deleted file mode 100644 index 1645ab76..00000000 --- a/phoenix/gtk/utility.cpp +++ /dev/null @@ -1,259 +0,0 @@ -namespace phoenix { - -static GdkColor CreateColor(uint8_t r, uint8_t g, uint8_t b) { - GdkColor color; - color.pixel = (r << 16) | (g << 8) | (b << 0); - color.red = (r << 8) | (r << 0); - color.green = (g << 8) | (g << 0); - color.blue = (b << 8) | (b << 0); - return color; -} - -static GdkPixbuf* CreatePixbuf(const nall::image& image, bool scale = false) { - nall::image gdkImage = image; - gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); - if(scale) gdkImage.scale(15, 15); - - GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height); - memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4); - - return pixbuf; -} - -static GtkImage* CreateImage(const nall::image& image, bool scale = false) { - GdkPixbuf* pixbuf = CreatePixbuf(image, scale); - GtkImage* gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf); - g_object_unref(pixbuf); - return gtkImage; -} - -static lstring DropPaths(GtkSelectionData* data) { - gchar** uris = gtk_selection_data_get_uris(data); - if(uris == nullptr) return {}; - - lstring paths; - for(unsigned n = 0; uris[n] != nullptr; n++) { - gchar* pathname = g_filename_from_uri(uris[n], nullptr, nullptr); - if(pathname == nullptr) continue; - - string path = pathname; - g_free(pathname); - if(directory::exists(path) && !path.endsWith("/")) path.append("/"); - paths.append(path); - } - - g_strfreev(uris); - return paths; -} - -static Position GetDisplacement(Sizable* sizable) { - Position position; - while(sizable->state.parent) { - Position displacement = sizable->state.parent->p.displacement(); - position.x += displacement.x; - position.y += displacement.y; - sizable = sizable->state.parent; - } - return position; -} - -static Layout* GetParentWidgetLayout(Sizable* sizable) { - while(sizable) { - if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Layout*)sizable; - sizable = sizable->state.parent; - } - return nullptr; -} - -static Widget* GetParentWidget(Sizable* sizable) { - while(sizable) { - if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Widget*)sizable->state.parent; - sizable = sizable->state.parent; - } - return nullptr; -} - -static Keyboard::Keycode Keysym(unsigned keysym) { - switch(keysym) { - case GDK_Escape: return Keyboard::Keycode::Escape; - case GDK_F1: return Keyboard::Keycode::F1; - case GDK_F2: return Keyboard::Keycode::F2; - case GDK_F3: return Keyboard::Keycode::F3; - case GDK_F4: return Keyboard::Keycode::F4; - case GDK_F5: return Keyboard::Keycode::F5; - case GDK_F6: return Keyboard::Keycode::F6; - case GDK_F7: return Keyboard::Keycode::F7; - case GDK_F8: return Keyboard::Keycode::F8; - case GDK_F9: return Keyboard::Keycode::F9; - case GDK_F10: return Keyboard::Keycode::F10; - case GDK_F11: return Keyboard::Keycode::F11; - case GDK_F12: return Keyboard::Keycode::F12; - - case GDK_Print: return Keyboard::Keycode::PrintScreen; - //Keyboard::Keycode::SysRq - case GDK_Scroll_Lock: return Keyboard::Keycode::ScrollLock; - case GDK_Pause: return Keyboard::Keycode::Pause; - //Keyboard::Keycode::Break - - case GDK_Insert: return Keyboard::Keycode::Insert; - case GDK_Delete: return Keyboard::Keycode::Delete; - case GDK_Home: return Keyboard::Keycode::Home; - case GDK_End: return Keyboard::Keycode::End; - case GDK_Prior: return Keyboard::Keycode::PageUp; - case GDK_Next: return Keyboard::Keycode::PageDown; - - case GDK_Up: return Keyboard::Keycode::Up; - case GDK_Down: return Keyboard::Keycode::Down; - case GDK_Left: return Keyboard::Keycode::Left; - case GDK_Right: return Keyboard::Keycode::Right; - - case GDK_grave: return Keyboard::Keycode::Grave; - case GDK_1: return Keyboard::Keycode::Number1; - case GDK_2: return Keyboard::Keycode::Number2; - case GDK_3: return Keyboard::Keycode::Number3; - case GDK_4: return Keyboard::Keycode::Number4; - case GDK_5: return Keyboard::Keycode::Number5; - case GDK_6: return Keyboard::Keycode::Number6; - case GDK_7: return Keyboard::Keycode::Number7; - case GDK_8: return Keyboard::Keycode::Number8; - case GDK_9: return Keyboard::Keycode::Number9; - case GDK_0: return Keyboard::Keycode::Number0; - case GDK_minus: return Keyboard::Keycode::Minus; - case GDK_equal: return Keyboard::Keycode::Equal; - case GDK_BackSpace: return Keyboard::Keycode::Backspace; - - case GDK_asciitilde: return Keyboard::Keycode::Tilde; - case GDK_exclam: return Keyboard::Keycode::Exclamation; - case GDK_at: return Keyboard::Keycode::At; - case GDK_numbersign: return Keyboard::Keycode::Pound; - case GDK_dollar: return Keyboard::Keycode::Dollar; - case GDK_percent: return Keyboard::Keycode::Percent; - case GDK_asciicircum: return Keyboard::Keycode::Power; - case GDK_ampersand: return Keyboard::Keycode::Ampersand; - case GDK_asterisk: return Keyboard::Keycode::Asterisk; - case GDK_parenleft: return Keyboard::Keycode::ParenthesisLeft; - case GDK_parenright: return Keyboard::Keycode::ParenthesisRight; - case GDK_underscore: return Keyboard::Keycode::Underscore; - case GDK_plus: return Keyboard::Keycode::Plus; - - case GDK_bracketleft: return Keyboard::Keycode::BracketLeft; - case GDK_bracketright: return Keyboard::Keycode::BracketRight; - case GDK_backslash: return Keyboard::Keycode::Backslash; - case GDK_semicolon: return Keyboard::Keycode::Semicolon; - case GDK_apostrophe: return Keyboard::Keycode::Apostrophe; - case GDK_comma: return Keyboard::Keycode::Comma; - case GDK_period: return Keyboard::Keycode::Period; - case GDK_slash: return Keyboard::Keycode::Slash; - - case GDK_braceleft: return Keyboard::Keycode::BraceLeft; - case GDK_braceright: return Keyboard::Keycode::BraceRight; - case GDK_bar: return Keyboard::Keycode::Pipe; - case GDK_colon: return Keyboard::Keycode::Colon; - case GDK_quotedbl: return Keyboard::Keycode::Quote; - case GDK_less: return Keyboard::Keycode::CaretLeft; - case GDK_greater: return Keyboard::Keycode::CaretRight; - case GDK_question: return Keyboard::Keycode::Question; - - case GDK_Tab: return Keyboard::Keycode::Tab; - case GDK_Caps_Lock: return Keyboard::Keycode::CapsLock; - case GDK_Return: return Keyboard::Keycode::Return; - case GDK_Shift_L: return Keyboard::Keycode::ShiftLeft; - case GDK_Shift_R: return Keyboard::Keycode::ShiftRight; - case GDK_Control_L: return Keyboard::Keycode::ControlLeft; - case GDK_Control_R: return Keyboard::Keycode::ControlRight; - case GDK_Super_L: return Keyboard::Keycode::SuperLeft; - case GDK_Super_R: return Keyboard::Keycode::SuperRight; - case GDK_Alt_L: return Keyboard::Keycode::AltLeft; - case GDK_Alt_R: return Keyboard::Keycode::AltRight; - case GDK_space: return Keyboard::Keycode::Space; - case GDK_Menu: return Keyboard::Keycode::Menu; - - case GDK_A: return Keyboard::Keycode::A; - case GDK_B: return Keyboard::Keycode::B; - case GDK_C: return Keyboard::Keycode::C; - case GDK_D: return Keyboard::Keycode::D; - case GDK_E: return Keyboard::Keycode::E; - case GDK_F: return Keyboard::Keycode::F; - case GDK_G: return Keyboard::Keycode::G; - case GDK_H: return Keyboard::Keycode::H; - case GDK_I: return Keyboard::Keycode::I; - case GDK_J: return Keyboard::Keycode::J; - case GDK_K: return Keyboard::Keycode::K; - case GDK_L: return Keyboard::Keycode::L; - case GDK_M: return Keyboard::Keycode::M; - case GDK_N: return Keyboard::Keycode::N; - case GDK_O: return Keyboard::Keycode::O; - case GDK_P: return Keyboard::Keycode::P; - case GDK_Q: return Keyboard::Keycode::Q; - case GDK_R: return Keyboard::Keycode::R; - case GDK_S: return Keyboard::Keycode::S; - case GDK_T: return Keyboard::Keycode::T; - case GDK_U: return Keyboard::Keycode::U; - case GDK_V: return Keyboard::Keycode::V; - case GDK_W: return Keyboard::Keycode::W; - case GDK_X: return Keyboard::Keycode::X; - case GDK_Y: return Keyboard::Keycode::Y; - case GDK_Z: return Keyboard::Keycode::Z; - - case GDK_a: return Keyboard::Keycode::a; - case GDK_b: return Keyboard::Keycode::b; - case GDK_c: return Keyboard::Keycode::c; - case GDK_d: return Keyboard::Keycode::d; - case GDK_e: return Keyboard::Keycode::e; - case GDK_f: return Keyboard::Keycode::f; - case GDK_g: return Keyboard::Keycode::g; - case GDK_h: return Keyboard::Keycode::h; - case GDK_i: return Keyboard::Keycode::i; - case GDK_j: return Keyboard::Keycode::j; - case GDK_k: return Keyboard::Keycode::k; - case GDK_l: return Keyboard::Keycode::l; - case GDK_m: return Keyboard::Keycode::m; - case GDK_n: return Keyboard::Keycode::n; - case GDK_o: return Keyboard::Keycode::o; - case GDK_p: return Keyboard::Keycode::p; - case GDK_q: return Keyboard::Keycode::q; - case GDK_r: return Keyboard::Keycode::r; - case GDK_s: return Keyboard::Keycode::s; - case GDK_t: return Keyboard::Keycode::t; - case GDK_u: return Keyboard::Keycode::u; - case GDK_v: return Keyboard::Keycode::v; - case GDK_w: return Keyboard::Keycode::w; - case GDK_x: return Keyboard::Keycode::x; - case GDK_y: return Keyboard::Keycode::y; - case GDK_z: return Keyboard::Keycode::z; - - case GDK_Num_Lock: return Keyboard::Keycode::NumLock; - case GDK_KP_Divide: return Keyboard::Keycode::Divide; - case GDK_KP_Multiply: return Keyboard::Keycode::Multiply; - case GDK_KP_Subtract: return Keyboard::Keycode::Subtract; - case GDK_KP_Add: return Keyboard::Keycode::Add; - case GDK_KP_Enter: return Keyboard::Keycode::Enter; - case GDK_KP_Decimal: return Keyboard::Keycode::Point; - - case GDK_KP_1: return Keyboard::Keycode::Keypad1; - case GDK_KP_2: return Keyboard::Keycode::Keypad2; - case GDK_KP_3: return Keyboard::Keycode::Keypad3; - case GDK_KP_4: return Keyboard::Keycode::Keypad4; - case GDK_KP_5: return Keyboard::Keycode::Keypad5; - case GDK_KP_6: return Keyboard::Keycode::Keypad6; - case GDK_KP_7: return Keyboard::Keycode::Keypad7; - case GDK_KP_8: return Keyboard::Keycode::Keypad8; - case GDK_KP_9: return Keyboard::Keycode::Keypad9; - case GDK_KP_0: return Keyboard::Keycode::Keypad0; - - case GDK_KP_Home: return Keyboard::Keycode::KeypadHome; - case GDK_KP_End: return Keyboard::Keycode::KeypadEnd; - case GDK_KP_Page_Up: return Keyboard::Keycode::KeypadPageUp; - case GDK_KP_Page_Down: return Keyboard::Keycode::KeypadPageDown; - case GDK_KP_Up: return Keyboard::Keycode::KeypadUp; - case GDK_KP_Down: return Keyboard::Keycode::KeypadDown; - case GDK_KP_Left: return Keyboard::Keycode::KeypadLeft; - case GDK_KP_Right: return Keyboard::Keycode::KeypadRight; - case GDK_KP_Begin: return Keyboard::Keycode::KeypadCenter; - case GDK_KP_Insert: return Keyboard::Keycode::KeypadInsert; - case GDK_KP_Delete: return Keyboard::Keycode::KeypadDelete; - } - return Keyboard::Keycode::None; -} - -} diff --git a/phoenix/gtk/widget/button.cpp b/phoenix/gtk/widget/button.cpp deleted file mode 100644 index 16e6bb37..00000000 --- a/phoenix/gtk/widget/button.cpp +++ /dev/null @@ -1,57 +0,0 @@ -namespace phoenix { - -static void Button_activate(Button* self) { - if(self->onActivate) self->onActivate(); -} - -Size pButton::minimumSize() { - Size size = pFont::size(widget.state.font, button.state.text); - - if(button.state.orientation == Orientation::Horizontal) { - size.width += button.state.image.width; - size.height = max(button.state.image.height, size.height); - } - - if(button.state.orientation == Orientation::Vertical) { - size.width = max(button.state.image.width, size.width); - size.height += button.state.image.height; - } - - return {size.width + 24, size.height + 12}; -} - -void pButton::setImage(const image& image, Orientation orientation) { - if(image.empty() == false) { - GtkImage* gtkImage = CreateImage(image); - gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage); - } else { - gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr); - } - switch(orientation) { - case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break; - case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break; - } -} - -void pButton::setText(string text) { - gtk_button_set_label(GTK_BUTTON(gtkWidget), text); - setFont(widget.state.font); -} - -void pButton::constructor() { - gtkWidget = gtk_button_new(); - g_signal_connect_swapped(G_OBJECT(gtkWidget), "clicked", G_CALLBACK(Button_activate), (gpointer)&button); - - setText(button.state.text); -} - -void pButton::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pButton::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/canvas.cpp b/phoenix/gtk/widget/canvas.cpp deleted file mode 100644 index 4fad9909..00000000 --- a/phoenix/gtk/widget/canvas.cpp +++ /dev/null @@ -1,177 +0,0 @@ -namespace phoenix { - -static void Canvas_drop(GtkWidget* widget, GdkDragContext* context, signed x, signed y, -GtkSelectionData* data, unsigned type, unsigned timestamp, Canvas* canvas) { - if(!canvas->state.droppable) return; - lstring paths = DropPaths(data); - if(paths.empty()) return; - if(canvas->onDrop) canvas->onDrop(paths); -} - -static signed Canvas_expose(GtkWidget* widget, GdkEventExpose* event, Canvas* self) { - self->p.onExpose(event); - return true; -} - -static signed Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, Canvas* self) { - if(self->onMouseLeave) self->onMouseLeave(); - return true; -} - -static signed Canvas_mouseMove(GtkWidget* widget, GdkEventButton* event, Canvas* self) { - if(self->onMouseMove) self->onMouseMove({(signed)event->x, (signed)event->y}); - return true; -} - -static signed Canvas_mousePress(GtkWidget* widget, GdkEventButton* event, Canvas* self) { - if(self->onMousePress) switch(event->button) { - case 1: self->onMousePress(Mouse::Button::Left); break; - case 2: self->onMousePress(Mouse::Button::Middle); break; - case 3: self->onMousePress(Mouse::Button::Right); break; - } - return true; -} - -static signed Canvas_mouseRelease(GtkWidget* widget, GdkEventButton* event, Canvas* self) { - if(self->onMouseRelease) switch(event->button) { - case 1: self->onMouseRelease(Mouse::Button::Left); break; - case 2: self->onMouseRelease(Mouse::Button::Middle); break; - case 3: self->onMouseRelease(Mouse::Button::Right); break; - } - return true; -} - -Size pCanvas::minimumSize() { - return {canvas.state.width, canvas.state.height}; -} - -void pCanvas::setDroppable(bool droppable) { - gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); - if(droppable) gtk_drag_dest_add_uri_targets(gtkWidget); -} - -void pCanvas::setGeometry(Geometry geometry) { - if(canvas.state.width == 0 || canvas.state.height == 0) rasterize(); - unsigned width = canvas.state.width; - unsigned height = canvas.state.height; - if(width == 0) width = widget.state.geometry.width; - if(height == 0) height = widget.state.geometry.height; - - if(width < geometry.width) { - geometry.x += (geometry.width - width) / 2; - geometry.width = width; - } - - if(height < geometry.height) { - geometry.y += (geometry.height - height) / 2; - geometry.height = height; - } - - pWidget::setGeometry(geometry); -} - -void pCanvas::setMode(Canvas::Mode mode) { - rasterize(), redraw(); -} - -void pCanvas::setSize(Size size) { - rasterize(), redraw(); -} - -void pCanvas::constructor() { - gtkWidget = gtk_drawing_area_new(); -//gtk_widget_set_double_buffered(gtkWidget, false); - gtk_widget_add_events(gtkWidget, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Canvas_mousePress), (gpointer)&canvas); - g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Canvas_mouseRelease), (gpointer)&canvas); - g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_drop), (gpointer)&canvas); - g_signal_connect(G_OBJECT(gtkWidget), "expose-event", G_CALLBACK(Canvas_expose), (gpointer)&canvas); - g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Canvas_mouseLeave), (gpointer)&canvas); - g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Canvas_mouseMove), (gpointer)&canvas); - - setDroppable(canvas.state.droppable); - rasterize(), redraw(); -} - -void pCanvas::destructor() { - release(); - gtk_widget_destroy(gtkWidget); -} - -void pCanvas::orphan() { - destructor(); - constructor(); -} - -void pCanvas::onExpose(GdkEventExpose* expose) { - if(surface) gdk_draw_pixbuf(gtk_widget_get_window(gtkWidget), nullptr, surface, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); -} - -void pCanvas::rasterize() { - unsigned width = canvas.state.width; - unsigned height = canvas.state.height; - if(width == 0) width = widget.state.geometry.width; - if(height == 0) height = widget.state.geometry.height; - - if(width != surfaceWidth || height != surfaceHeight) release(); - surfaceWidth = width; - surfaceHeight = height; - - if(width == 0 || height == 0) return; - - if(!surface) surface = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height); - uint32_t* buffer = (uint32_t*)gdk_pixbuf_get_pixels(surface); - - if(canvas.state.mode == Canvas::Mode::Color) { - uint32_t color = canvas.state.color.argb(); - for(unsigned n = 0; n < width * height; n++) buffer[n] = color; - } - - if(canvas.state.mode == Canvas::Mode::Gradient) { - nall::image image; - image.allocate(width, height); - image.gradient( - canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb() - ); - memcpy(buffer, image.data, image.size); - } - - if(canvas.state.mode == Canvas::Mode::Image) { - nall::image image = canvas.state.image; - image.scale(width, height); - image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); - memcpy(buffer, image.data, image.size); - } - - if(canvas.state.mode == Canvas::Mode::Data) { - if(width == canvas.state.width && height == canvas.state.height) { - memcpy(buffer, canvas.state.data, width * height * sizeof(uint32_t)); - } else { - memset(buffer, 0x00, width * height * sizeof(uint32_t)); - } - } - - //ARGB -> ABGR conversion - for(unsigned n = 0; n < width * height; n++) { - uint32_t color = *buffer; - color = (color & 0xff00ff00) | ((color & 0xff0000) >> 16) | ((color & 0x0000ff) << 16); - *buffer++ = color; - } -} - -void pCanvas::redraw() { - if(gtk_widget_get_realized(gtkWidget)) { - gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), nullptr, true); - } -} - -void pCanvas::release() { - if(surface == nullptr) return; - g_object_unref(surface); - surface = nullptr; - surfaceWidth = 0; - surfaceHeight = 0; -} - -} diff --git a/phoenix/gtk/widget/check-button.cpp b/phoenix/gtk/widget/check-button.cpp deleted file mode 100644 index d72d91ff..00000000 --- a/phoenix/gtk/widget/check-button.cpp +++ /dev/null @@ -1,70 +0,0 @@ -namespace phoenix { - -static void CheckButton_toggle(GtkToggleButton* toggleButton, CheckButton* self) { - self->p.onToggle(); -} - -Size pCheckButton::minimumSize() { - Size size = pFont::size(widget.state.font, checkButton.state.text); - - if(checkButton.state.orientation == Orientation::Horizontal) { - size.width += checkButton.state.image.width; - size.height = max(checkButton.state.image.height, size.height); - } - - if(checkButton.state.orientation == Orientation::Vertical) { - size.width = max(checkButton.state.image.width, size.width); - size.height += checkButton.state.image.height; - } - - return {size.width + 24, size.height + 12}; -} - -void pCheckButton::setChecked(bool checked) { - locked = true; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked); - locked = false; -} - -void pCheckButton::setImage(const image& image, Orientation orientation) { - if(image.empty() == false) { - GtkImage* gtkImage = CreateImage(image); - gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage); - } else { - gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr); - } - switch(orientation) { - case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break; - case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break; - } -} - -void pCheckButton::setText(string text) { - gtk_button_set_label(GTK_BUTTON(gtkWidget), text); - setFont(widget.state.font); -} - -void pCheckButton::constructor() { - gtkWidget = gtk_toggle_button_new(); - g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckButton_toggle), (gpointer)&checkButton); - - setChecked(checkButton.state.checked); - setText(checkButton.state.text); -} - -void pCheckButton::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pCheckButton::orphan() { - destructor(); - constructor(); -} - -void pCheckButton::onToggle() { - if(locked) return; - checkButton.state.checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget)); - if(checkButton.onToggle) checkButton.onToggle(); -} - -} diff --git a/phoenix/gtk/widget/check-label.cpp b/phoenix/gtk/widget/check-label.cpp deleted file mode 100644 index 6e59fbd6..00000000 --- a/phoenix/gtk/widget/check-label.cpp +++ /dev/null @@ -1,40 +0,0 @@ -namespace phoenix { - -static void CheckLabel_toggle(GtkToggleButton* toggleButton, CheckLabel* self) { - self->state.checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self->p.gtkWidget)); - if(!self->p.locked && self->onToggle) self->onToggle(); -} - -Size pCheckLabel::minimumSize() { - Size size = pFont::size(widget.state.font, checkLabel.state.text); - return {size.width + 28, size.height + 4}; -} - -void pCheckLabel::setChecked(bool checked) { - locked = true; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked); - locked = false; -} - -void pCheckLabel::setText(string text) { - gtk_button_set_label(GTK_BUTTON(gtkWidget), text); -} - -void pCheckLabel::constructor() { - gtkWidget = gtk_check_button_new_with_label(""); - g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckLabel_toggle), (gpointer)&checkLabel); - - setChecked(checkLabel.state.checked); - setText(checkLabel.state.text); -} - -void pCheckLabel::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pCheckLabel::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/combo-button.cpp b/phoenix/gtk/widget/combo-button.cpp deleted file mode 100644 index ed523f1a..00000000 --- a/phoenix/gtk/widget/combo-button.cpp +++ /dev/null @@ -1,74 +0,0 @@ -namespace phoenix { - -static void ComboButton_change(ComboButton* self) { - if(!self->p.locked) { - self->state.selection = gtk_combo_box_get_active(GTK_COMBO_BOX(self->p.gtkWidget)); - if(self->onChange) self->onChange(); - } -} - -void pComboButton::append(string text) { - gtk_combo_box_append_text(GTK_COMBO_BOX(gtkWidget), text); - if(itemCounter++ == 0) comboButton.setSelection(0); -} - -Size pComboButton::minimumSize() { - unsigned maximumWidth = 0; - for(auto& item : comboButton.state.text) maximumWidth = max(maximumWidth, pFont::size(widget.state.font, item).width); - - Size size = pFont::size(widget.state.font, " "); - return {maximumWidth + 44, size.height + 12}; -} - -void pComboButton::remove(unsigned selection) { - locked = true; - gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), selection); - itemCounter--; - locked = false; - - //when removing the actively selected item, reset the selection to the first entry - if(selection == comboButton.state.selection) comboButton.setSelection(0); -} - -void pComboButton::reset() { - locked = true; - gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(gtkWidget)))); - itemCounter = 0; - locked = false; -} - -void pComboButton::setSelection(unsigned selection) { - locked = true; - gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), selection); - locked = false; -} - -void pComboButton::setText(unsigned selection, string text) { - locked = true; - gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), selection); - gtk_combo_box_insert_text(GTK_COMBO_BOX(gtkWidget), selection, text); - gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), comboButton.state.selection); - locked = false; -} - -void pComboButton::constructor() { - itemCounter = 0; - gtkWidget = gtk_combo_box_new_text(); - g_signal_connect_swapped(G_OBJECT(gtkWidget), "changed", G_CALLBACK(ComboButton_change), (gpointer)&comboButton); - - locked = true; - for(auto& text : comboButton.state.text) append(text); - locked = false; - setSelection(comboButton.state.selection); -} - -void pComboButton::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pComboButton::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/frame.cpp b/phoenix/gtk/widget/frame.cpp deleted file mode 100644 index f41e1c3c..00000000 --- a/phoenix/gtk/widget/frame.cpp +++ /dev/null @@ -1,48 +0,0 @@ -namespace phoenix { - -GtkWidget* pFrame::container(Widget& widget) { - return gtk_widget_get_parent(gtkWidget); -} - -Position pFrame::containerOffset() { - return {0, 0}; -} - -void pFrame::setEnabled(bool enabled) { - if(frame.state.layout) frame.state.layout->setEnabled(frame.state.layout->enabled()); - pWidget::setEnabled(enabled); -} - -void pFrame::setGeometry(Geometry geometry) { - pWidget::setGeometry(geometry); - if(frame.state.layout == nullptr) return; - Size size = pFont::size(widget.state.font, frame.state.text); - if(frame.state.text.empty()) size.height = 8; - geometry.x += 2, geometry.width -= 5; - geometry.y += size.height - 1, geometry.height -= size.height + 2; - frame.state.layout->setGeometry(geometry); -} - -void pFrame::setText(string text) { - gtk_frame_set_label(GTK_FRAME(gtkWidget), text); -} - -void pFrame::setVisible(bool visible) { - if(frame.state.layout) frame.state.layout->setVisible(frame.state.layout->visible()); - pWidget::setVisible(visible); -} - -void pFrame::constructor() { - gtkWidget = gtk_frame_new(""); -} - -void pFrame::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pFrame::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/horizontal-scroller.cpp b/phoenix/gtk/widget/horizontal-scroller.cpp deleted file mode 100644 index 5a46879f..00000000 --- a/phoenix/gtk/widget/horizontal-scroller.cpp +++ /dev/null @@ -1,43 +0,0 @@ -namespace phoenix { - -static void HorizontalScroller_change(GtkRange* gtkRange, HorizontalScroller* self) { - unsigned position = (unsigned)gtk_range_get_value(gtkRange); - if(self->state.position == position) return; - self->state.position = position; - if(!self->p.locked && self->onChange) self->onChange(); -} - -Size pHorizontalScroller::minimumSize() { - return {0, 20}; -} - -void pHorizontalScroller::setLength(unsigned length) { - locked = true; - length += length == 0; - gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); - gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); - locked = false; -} - -void pHorizontalScroller::setPosition(unsigned position) { - gtk_range_set_value(GTK_RANGE(gtkWidget), position); -} - -void pHorizontalScroller::constructor() { - gtkWidget = gtk_hscrollbar_new(0); - g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScroller_change), (gpointer)&horizontalScroller); - - setLength(horizontalScroller.state.length); - setPosition(horizontalScroller.state.position); -} - -void pHorizontalScroller::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pHorizontalScroller::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/horizontal-slider.cpp b/phoenix/gtk/widget/horizontal-slider.cpp deleted file mode 100644 index 2ef80d93..00000000 --- a/phoenix/gtk/widget/horizontal-slider.cpp +++ /dev/null @@ -1,42 +0,0 @@ -namespace phoenix { - -static void HorizontalSlider_change(GtkRange* gtkRange, HorizontalSlider* self) { - unsigned position = (unsigned)gtk_range_get_value(gtkRange); - if(self->state.position == position) return; - self->state.position = position; - if(self->onChange) self->onChange(); -} - -Size pHorizontalSlider::minimumSize() { - return {0, 20}; -} - -void pHorizontalSlider::setLength(unsigned length) { - length += length == 0; - gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); - gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); -} - -void pHorizontalSlider::setPosition(unsigned position) { - gtk_range_set_value(GTK_RANGE(gtkWidget), position); -} - -void pHorizontalSlider::constructor() { - gtkWidget = gtk_hscale_new_with_range(0, 100, 1); - gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); - g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)&horizontalSlider); - - setLength(horizontalSlider.state.length); - setPosition(horizontalSlider.state.position); -} - -void pHorizontalSlider::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pHorizontalSlider::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/label.cpp b/phoenix/gtk/widget/label.cpp deleted file mode 100644 index c484587b..00000000 --- a/phoenix/gtk/widget/label.cpp +++ /dev/null @@ -1,28 +0,0 @@ -namespace phoenix { - -Size pLabel::minimumSize() { - Size size = pFont::size(widget.state.font, label.state.text); - return {size.width, size.height}; -} - -void pLabel::setText(string text) { - gtk_label_set_text(GTK_LABEL(gtkWidget), text); -} - -void pLabel::constructor() { - gtkWidget = gtk_label_new(""); - gtk_misc_set_alignment(GTK_MISC(gtkWidget), 0.0, 0.5); - - setText(label.state.text); -} - -void pLabel::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pLabel::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/line-edit.cpp b/phoenix/gtk/widget/line-edit.cpp deleted file mode 100644 index 642e6936..00000000 --- a/phoenix/gtk/widget/line-edit.cpp +++ /dev/null @@ -1,59 +0,0 @@ -namespace phoenix { - -static void LineEdit_activate(LineEdit* self) { - if(self->onActivate) self->onActivate(); -} - -static void LineEdit_change(LineEdit* self) { - self->state.text = self->text(); - if(self->p.locked == false && self->onChange) self->onChange(); -} - -Size pLineEdit::minimumSize() { - Size size = pFont::size(widget.state.font, lineEdit.state.text); - return {size.width + 10, size.height + 10}; -} - -void pLineEdit::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_base(gtkWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pLineEdit::setEditable(bool editable) { - gtk_editable_set_editable(GTK_EDITABLE(gtkWidget), editable); -} - -void pLineEdit::setForegroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_text(gtkWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pLineEdit::setText(string text) { - locked = true; - gtk_entry_set_text(GTK_ENTRY(gtkWidget), text); - locked = false; -} - -string pLineEdit::text() { - return gtk_entry_get_text(GTK_ENTRY(gtkWidget)); -} - -void pLineEdit::constructor() { - gtkWidget = gtk_entry_new(); - g_signal_connect_swapped(G_OBJECT(gtkWidget), "activate", G_CALLBACK(LineEdit_activate), (gpointer)&lineEdit); - g_signal_connect_swapped(G_OBJECT(gtkWidget), "changed", G_CALLBACK(LineEdit_change), (gpointer)&lineEdit); - - setEditable(lineEdit.state.editable); - setText(lineEdit.state.text); -} - -void pLineEdit::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pLineEdit::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/list-view.cpp b/phoenix/gtk/widget/list-view.cpp deleted file mode 100644 index 8fa77c6c..00000000 --- a/phoenix/gtk/widget/list-view.cpp +++ /dev/null @@ -1,216 +0,0 @@ -namespace phoenix { - -static void ListView_activate(GtkTreeView* treeView, GtkTreePath* path, GtkTreeViewColumn* column, ListView* self) { - char* pathname = gtk_tree_path_to_string(path); - unsigned selection = decimal(pathname); - g_free(pathname); - self->state.selection = selection; - if(self->onActivate) self->onActivate(); -} - -static void ListView_change(GtkTreeView* treeView, ListView* self) { - GtkTreeIter iter; - if(!gtk_tree_selection_get_selected(gtk_tree_view_get_selection(treeView), 0, &iter)) return; //should not be possible - char* path = gtk_tree_model_get_string_from_iter(gtk_tree_view_get_model(treeView), &iter); - unsigned selection = decimal(path); - g_free(path); - - if(!self->state.selected || self->state.selection != selection) { - self->state.selected = true; - self->state.selection = selection; - if(self->onChange) self->onChange(); - } -} - -static void ListView_toggle(GtkCellRendererToggle* cell, gchar* path, ListView* self) { - unsigned selection = decimal(path); - self->setChecked(selection, !self->checked(selection)); - if(self->onToggle) self->onToggle(selection); -} - -void pListView::append(const lstring& text) { - GtkTreeIter iter; - gtk_list_store_append(store, &iter); - for(unsigned n = 0; n < text.size(); n++) { - gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1); - } -} - -void pListView::autoSizeColumns() { - gtk_tree_view_columns_autosize(GTK_TREE_VIEW(subWidget)); -} - -bool pListView::focused() { - return GTK_WIDGET_HAS_FOCUS(subWidget); -} - -void pListView::remove(unsigned selection) { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreeIter iter; - gtk_tree_model_get_iter_from_string(model, &iter, string(selection)); - gtk_list_store_remove(store, &iter); -} - -void pListView::reset() { - listView.state.selected = false; - listView.state.selection = 0; - gtk_list_store_clear(GTK_LIST_STORE(store)); - gtk_tree_view_set_model(GTK_TREE_VIEW(subWidget), GTK_TREE_MODEL(store)); - //reset gtk_scrolled_window scrollbar position to 0,0 (top-left), as ListView is now empty - gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(gtkWidget), 0); - gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(gtkWidget), 0); -} - -void pListView::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pListView::setCheckable(bool checkable) { - gtk_cell_renderer_set_visible(column(0).checkbutton, checkable); -} - -void pListView::setChecked(unsigned selection, bool checked) { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreeIter iter; - gtk_tree_model_get_iter_from_string(model, &iter, string(selection)); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1); -} - -void pListView::setForegroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pListView::setHeaderText(const lstring& text) { - destructor(); - constructor(); -} - -void pListView::setHeaderVisible(bool visible) { - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(subWidget), visible); -} - -void pListView::setImage(unsigned selection, unsigned position, const image& image) { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreeIter iter; - gtk_tree_model_get_iter_from_string(model, &iter, string(selection)); - if(image.empty() == false) { - GdkPixbuf* pixbuf = CreatePixbuf(image, true); - gtk_list_store_set(store, &iter, 1 + position * 2, pixbuf, -1); - } else { - gtk_list_store_set(store, &iter, 1 + position * 2, nullptr, -1); - } -} - -void pListView::setSelected(bool selected) { - if(selected == false) { - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget)); - gtk_tree_selection_unselect_all(selection); - } else { - setSelection(listView.state.selection); - } -} - -void pListView::setSelection(unsigned selection) { - GtkTreeSelection* treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget)); - gtk_tree_selection_unselect_all(treeSelection); - GtkTreePath* path = gtk_tree_path_new_from_string(string{selection}); - gtk_tree_selection_select_path(treeSelection, path); - gtk_tree_view_set_cursor(GTK_TREE_VIEW(subWidget), path, nullptr, false); - gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(subWidget), path, nullptr, true, 0.5, 0.0); - gtk_tree_path_free(path); -} - -void pListView::setText(unsigned selection, unsigned position, string text) { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreeIter iter; - gtk_tree_model_get_iter_from_string(model, &iter, string(selection)); - gtk_list_store_set(store, &iter, 1 + position * 2 + 1, (const char*)text, -1); -} - -void pListView::constructor() { - gtkWidget = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); - - lstring headerText = listView.state.headerText; - if(headerText.size() == 0) headerText.append(""); //ListView must have at least one column - - column.reset(); - vector<GType> gtype; - for(auto& text : headerText) { - GtkColumn cell; - cell.label = gtk_label_new(text); - cell.column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_resizable(cell.column, true); - gtk_tree_view_column_set_title(cell.column, ""); - - if(column.size() == 0) { //first column checkbutton - cell.checkbutton = gtk_cell_renderer_toggle_new(); - gtk_tree_view_column_pack_start(cell.column, cell.checkbutton, false); - gtk_tree_view_column_set_attributes(cell.column, cell.checkbutton, "active", gtype.size(), nullptr); - gtype.append(G_TYPE_BOOLEAN); - g_signal_connect(cell.checkbutton, "toggled", G_CALLBACK(ListView_toggle), (gpointer)&listView); - } - - cell.icon = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(cell.column, cell.icon, false); - gtk_tree_view_column_set_attributes(cell.column, cell.icon, "pixbuf", gtype.size(), nullptr); - gtype.append(GDK_TYPE_PIXBUF); - - cell.text = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(cell.column, cell.text, false); - gtk_tree_view_column_set_attributes(cell.column, cell.text, "text", gtype.size(), nullptr); - gtype.append(G_TYPE_STRING); - - column.append(cell); - } - - store = gtk_list_store_newv(gtype.size(), gtype.data()); - subWidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); - g_object_unref(G_OBJECT(store)); - - for(auto& cell : column) { - gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(cell.column), cell.label); - gtk_tree_view_append_column(GTK_TREE_VIEW(subWidget), cell.column); - gtk_widget_show(cell.label); - } - - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(subWidget), headerText.size() >= 2); //two or more columns + checkbutton column - gtk_tree_view_set_search_column(GTK_TREE_VIEW(subWidget), 2); - - g_signal_connect(G_OBJECT(subWidget), "cursor-changed", G_CALLBACK(ListView_change), (gpointer)&listView); - g_signal_connect(G_OBJECT(subWidget), "row-activated", G_CALLBACK(ListView_activate), (gpointer)&listView); - - gtk_widget_show(subWidget); - - setHeaderVisible(listView.state.headerVisible); - setCheckable(listView.state.checkable); - for(auto& text : listView.state.text) append(text); - for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]); - if(listView.state.selected) setSelection(listView.state.selection); - autoSizeColumns(); -} - -void pListView::destructor() { - gtk_widget_destroy(subWidget); - gtk_widget_destroy(gtkWidget); -} - -void pListView::orphan() { - destructor(); - constructor(); -} - -void pListView::setFocused() { - gtk_widget_grab_focus(subWidget); -} - -void pListView::setFont(string font) { - pFont::setFont(gtkWidget, font); - for(auto& cell : column) pFont::setFont(cell.label, font); -} - -} diff --git a/phoenix/gtk/widget/progress-bar.cpp b/phoenix/gtk/widget/progress-bar.cpp deleted file mode 100644 index 7f4545a2..00000000 --- a/phoenix/gtk/widget/progress-bar.cpp +++ /dev/null @@ -1,27 +0,0 @@ -namespace phoenix { - -Size pProgressBar::minimumSize() { - return {0, 25}; -} - -void pProgressBar::setPosition(unsigned position) { - position = position <= 100 ? position : 0; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkWidget), (double)position / 100.0); -} - -void pProgressBar::constructor() { - gtkWidget = gtk_progress_bar_new(); - - setPosition(progressBar.state.position); -} - -void pProgressBar::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pProgressBar::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/radio-button.cpp b/phoenix/gtk/widget/radio-button.cpp deleted file mode 100644 index ca10fc36..00000000 --- a/phoenix/gtk/widget/radio-button.cpp +++ /dev/null @@ -1,89 +0,0 @@ -namespace phoenix { - -static void RadioButton_activate(GtkToggleButton* toggleButton, RadioButton* self) { - self->p.onActivate(); -} - -Size pRadioButton::minimumSize() { - Size size = pFont::size(widget.state.font, radioButton.state.text); - - if(radioButton.state.orientation == Orientation::Horizontal) { - size.width += radioButton.state.image.width; - size.height = max(radioButton.state.image.height, size.height); - } - - if(radioButton.state.orientation == Orientation::Vertical) { - size.width = max(radioButton.state.image.width, size.width); - size.height += radioButton.state.image.height; - } - - return {size.width + 24, size.height + 12}; -} - -void pRadioButton::setChecked() { - parent().locked = true; - for(auto& item : radioButton.state.group) { - bool checked = &item == &radioButton; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), item.state.checked = checked); - } - parent().locked = false; -} - -void pRadioButton::setGroup(const group<RadioButton>& group) { - parent().locked = true; - for(auto& item : radioButton.state.group) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), item.state.checked); - } - parent().locked = false; -} - -void pRadioButton::setImage(const image& image, Orientation orientation) { - if(image.empty() == false) { - GtkImage* gtkImage = CreateImage(image); - gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage); - } else { - gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr); - } - switch(orientation) { - case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break; - case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break; - } -} - -void pRadioButton::setText(string text) { - gtk_button_set_label(GTK_BUTTON(gtkWidget), text); - setFont(widget.state.font); -} - -void pRadioButton::constructor() { - gtkWidget = gtk_toggle_button_new(); - g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioButton_activate), (gpointer)&radioButton); - - setGroup(radioButton.state.group); - setText(radioButton.state.text); -} - -void pRadioButton::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pRadioButton::orphan() { - destructor(); - constructor(); -} - -void pRadioButton::onActivate() { - if(parent().locked) return; - bool wasChecked = radioButton.state.checked; - setChecked(); - if(!wasChecked) { - if(radioButton.onActivate) radioButton.onActivate(); - } -} - -pRadioButton& pRadioButton::parent() { - if(radioButton.state.group.size()) return radioButton.state.group.first().p; - return *this; -} - -} diff --git a/phoenix/gtk/widget/radio-label.cpp b/phoenix/gtk/widget/radio-label.cpp deleted file mode 100644 index 5e1b224d..00000000 --- a/phoenix/gtk/widget/radio-label.cpp +++ /dev/null @@ -1,69 +0,0 @@ -namespace phoenix { - -static void RadioLabel_activate(GtkToggleButton* toggleButton, RadioLabel* self) { - self->p.onActivate(); -} - -Size pRadioLabel::minimumSize() { - Size size = pFont::size(widget.state.font, radioLabel.state.text); - return {size.width + 28, size.height + 4}; -} - -void pRadioLabel::setChecked() { - parent().locked = true; - for(auto& item : radioLabel.state.group) item.state.checked = false; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), radioLabel.state.checked = true); - parent().locked = false; -} - -void pRadioLabel::setGroup(const group<RadioLabel>& group) { - if(&parent() == this) return; - parent().locked = true; - gtk_radio_button_set_group( - GTK_RADIO_BUTTON(gtkWidget), - gtk_radio_button_get_group(GTK_RADIO_BUTTON(parent().gtkWidget)) - ); - for(auto& item : radioLabel.state.group) { - if(item.state.checked) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), true); - break; - } - } - parent().locked = false; -} - -void pRadioLabel::setText(string text) { - gtk_button_set_label(GTK_BUTTON(gtkWidget), text); -} - -void pRadioLabel::constructor() { - gtkWidget = gtk_radio_button_new_with_label(nullptr, ""); - g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioLabel_activate), (gpointer)&radioLabel); - - setGroup(radioLabel.state.group); - setText(radioLabel.state.text); -} - -void pRadioLabel::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pRadioLabel::orphan() { - destructor(); - constructor(); -} - -void pRadioLabel::onActivate() { - if(parent().locked) return; - bool wasChecked = radioLabel.state.checked; - setChecked(); - if(wasChecked) return; - if(radioLabel.onActivate) radioLabel.onActivate(); -} - -pRadioLabel& pRadioLabel::parent() { - if(radioLabel.state.group.size()) return radioLabel.state.group.first().p; - return *this; -} - -} diff --git a/phoenix/gtk/widget/tab-frame.cpp b/phoenix/gtk/widget/tab-frame.cpp deleted file mode 100644 index a9a3c562..00000000 --- a/phoenix/gtk/widget/tab-frame.cpp +++ /dev/null @@ -1,126 +0,0 @@ -namespace phoenix { - -static void TabFrame_change(GtkNotebook* notebook, GtkWidget* page, unsigned selection, TabFrame* self) { - self->state.selection = selection; - self->p.synchronizeLayout(); - if(!self->p.locked && self->onChange) self->onChange(); -} - -void pTabFrame::append(string text, const image& image) { - unsigned selection = tabFrame.state.text.size() - 1; - - Tab tab; - tab.child = gtk_fixed_new(); - tab.container = gtk_hbox_new(false, 0); - tab.image = gtk_image_new(); - tab.title = gtk_label_new(text); - tabs.append(tab); - - gtk_widget_show(tab.child); - gtk_widget_show(tab.container); - gtk_widget_show(tab.image); - gtk_widget_show(tab.title); - gtk_box_pack_start(GTK_BOX(tab.container), tab.image, false, false, 0); - gtk_box_pack_start(GTK_BOX(tab.container), tab.title, false, false, 2); - - gtk_notebook_append_page(GTK_NOTEBOOK(gtkWidget), tab.child, tab.container); - setFont(widget.state.font); - if(!image.empty()) setImage(selection, image); -} - -GtkWidget* pTabFrame::container(Widget& widget) { - Layout* widgetLayout = GetParentWidgetLayout(&widget); - unsigned selection = 0; - for(auto& layout : tabFrame.state.layout) { - if(layout == widgetLayout) return tabs[selection].child; - selection++; - } - return nullptr; -} - -Position pTabFrame::displacement() { - return {6, 31}; -} - -void pTabFrame::remove(unsigned selection) { - tabs.remove(selection); - gtk_notebook_remove_page(GTK_NOTEBOOK(gtkWidget), selection); -} - -void pTabFrame::setEnabled(bool enabled) { - for(auto& layout : tabFrame.state.layout) { - if(layout) layout->setEnabled(layout->enabled()); - } - pWidget::setEnabled(enabled); -} - -void pTabFrame::setGeometry(Geometry geometry) { - pWidget::setGeometry(geometry); - geometry.x += 1, geometry.width -= 5; - geometry.y += 26, geometry.height -= 31; - for(auto& layout : tabFrame.state.layout) { - if(layout) layout->setGeometry(geometry); - } - synchronizeLayout(); -} - -void pTabFrame::setImage(unsigned selection, const image& image) { - if(image.empty() == false) { - nall::image copy = image; - unsigned size = pFont::size(widget.state.font, " ").height; - copy.scale(size, size); - GdkPixbuf* pixbuf = CreatePixbuf(copy); - gtk_image_set_from_pixbuf(GTK_IMAGE(tabs[selection].image), pixbuf); - } else { - gtk_image_clear(GTK_IMAGE(tabs[selection].image)); - } -} - -void pTabFrame::setSelection(unsigned selection) { - locked = true; - gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkWidget), selection); - locked = false; -} - -void pTabFrame::setText(unsigned selection, string text) { - gtk_label_set_text(GTK_LABEL(tabs[selection].title), text); -} - -void pTabFrame::setVisible(bool visible) { - for(auto& layout : tabFrame.state.layout) { - if(layout) layout->setVisible(layout->visible()); - } - pWidget::setVisible(visible); -} - -void pTabFrame::constructor() { - gtkWidget = gtk_notebook_new(); - gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkWidget), false); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), GTK_POS_TOP); - g_signal_connect(G_OBJECT(gtkWidget), "switch-page", G_CALLBACK(TabFrame_change), (gpointer)&tabFrame); - - setSelection(tabFrame.state.selection); -} - -void pTabFrame::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pTabFrame::orphan() { - destructor(); - constructor(); -} - -void pTabFrame::setFont(string font) { - for(auto& tab : tabs) pFont::setFont(tab.title, font); -} - -void pTabFrame::synchronizeLayout() { - unsigned selection = 0; - for(auto& layout : tabFrame.state.layout) { - if(layout) layout->setVisible(selection == tabFrame.state.selection); - selection++; - } -} - -} diff --git a/phoenix/gtk/widget/text-edit.cpp b/phoenix/gtk/widget/text-edit.cpp deleted file mode 100644 index 49ee4df7..00000000 --- a/phoenix/gtk/widget/text-edit.cpp +++ /dev/null @@ -1,88 +0,0 @@ -namespace phoenix { - -static void TextEdit_change(TextEdit* self) { - self->state.text = self->text(); - if(self->p.locked == false && self->onChange) self->onChange(); -} - -bool pTextEdit::focused() { - return GTK_WIDGET_HAS_FOCUS(subWidget); -} - -void pTextEdit::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pTextEdit::setCursorPosition(unsigned position) { - GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); - GtkTextIter iter; - gtk_text_buffer_get_end_iter(textBuffer, &iter); - gtk_text_iter_set_offset(&iter, min(position, gtk_text_iter_get_offset(&iter))); - gtk_text_buffer_place_cursor(textBuffer, &iter); - gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark); -} - -void pTextEdit::setEditable(bool editable) { - gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), editable); -} - -void pTextEdit::setForegroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &gdkColor); -} - -void pTextEdit::setText(string text) { - locked = true; - gtk_text_buffer_set_text(textBuffer, text, -1); - locked = false; -} - -void pTextEdit::setWordWrap(bool wordWrap) { - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), wordWrap ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), - wordWrap ? GTK_POLICY_NEVER : GTK_POLICY_ALWAYS, - GTK_POLICY_ALWAYS); -} - -string pTextEdit::text() { - GtkTextIter start, end; - gtk_text_buffer_get_start_iter(textBuffer, &start); - gtk_text_buffer_get_end_iter(textBuffer, &end); - char* temp = gtk_text_buffer_get_text(textBuffer, &start, &end, true); - string text = temp; - g_free(temp); - return text; -} - -void pTextEdit::constructor() { - gtkWidget = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN); - - subWidget = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_WORD_CHAR); - gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget); - - textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); - - g_signal_connect_swapped(G_OBJECT(textBuffer), "changed", G_CALLBACK(TextEdit_change), (gpointer)&textEdit); - - gtk_widget_show(subWidget); - - setEditable(textEdit.state.editable); - setText(textEdit.state.text); - setWordWrap(textEdit.state.wordWrap); -} - -void pTextEdit::destructor() { - gtk_widget_destroy(subWidget); - gtk_widget_destroy(gtkWidget); -} - -void pTextEdit::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/vertical-scroller.cpp b/phoenix/gtk/widget/vertical-scroller.cpp deleted file mode 100644 index 68928ce3..00000000 --- a/phoenix/gtk/widget/vertical-scroller.cpp +++ /dev/null @@ -1,43 +0,0 @@ -namespace phoenix { - -static void VerticalScroller_change(GtkRange* gtkRange, VerticalScroller* self) { - unsigned position = (unsigned)gtk_range_get_value(gtkRange); - if(self->state.position == position) return; - self->state.position = position; - if(!self->p.locked && self->onChange) self->onChange(); -} - -Size pVerticalScroller::minimumSize() { - return {20, 0}; -} - -void pVerticalScroller::setLength(unsigned length) { - locked = true; - length += length == 0; - gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); - gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); - locked = false; -} - -void pVerticalScroller::setPosition(unsigned position) { - gtk_range_set_value(GTK_RANGE(gtkWidget), position); -} - -void pVerticalScroller::constructor() { - gtkWidget = gtk_vscrollbar_new(0); - g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScroller_change), (gpointer)&verticalScroller); - - setLength(verticalScroller.state.length); - setPosition(verticalScroller.state.position); -} - -void pVerticalScroller::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pVerticalScroller::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/vertical-slider.cpp b/phoenix/gtk/widget/vertical-slider.cpp deleted file mode 100644 index 102b5c44..00000000 --- a/phoenix/gtk/widget/vertical-slider.cpp +++ /dev/null @@ -1,42 +0,0 @@ -namespace phoenix { - -static void VerticalSlider_change(GtkRange* gtkRange, VerticalSlider* self) { - unsigned position = (unsigned)gtk_range_get_value(gtkRange); - if(self->state.position == position) return; - self->state.position = position; - if(self->onChange) self->onChange(); -} - -Size pVerticalSlider::minimumSize() { - return {20, 0}; -} - -void pVerticalSlider::setLength(unsigned length) { - length += length == 0; - gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1)); - gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); -} - -void pVerticalSlider::setPosition(unsigned position) { - gtk_range_set_value(GTK_RANGE(gtkWidget), position); -} - -void pVerticalSlider::constructor() { - gtkWidget = gtk_vscale_new_with_range(0, 100, 1); - gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); - g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)&verticalSlider); - - setLength(verticalSlider.state.length); - setPosition(verticalSlider.state.position); -} - -void pVerticalSlider::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pVerticalSlider::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/viewport.cpp b/phoenix/gtk/widget/viewport.cpp deleted file mode 100644 index bc2474e6..00000000 --- a/phoenix/gtk/widget/viewport.cpp +++ /dev/null @@ -1,76 +0,0 @@ -namespace phoenix { - -static void Viewport_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y, -GtkSelectionData* data, guint type, guint timestamp, Viewport* viewport) { - if(viewport->state.droppable == false) return; - lstring paths = DropPaths(data); - if(paths.empty()) return; - if(viewport->onDrop) viewport->onDrop(paths); -} - -static gboolean Viewport_mouseLeave(GtkWidget* widget, GdkEventButton* event, pViewport* self) { - if(self->viewport.onMouseLeave) self->viewport.onMouseLeave(); - return true; -} - -static gboolean Viewport_mouseMove(GtkWidget* widget, GdkEventButton* event, pViewport* self) { - if(self->viewport.onMouseMove) self->viewport.onMouseMove({(signed)event->x, (signed)event->y}); - return true; -} - -static gboolean Viewport_mousePress(GtkWidget* widget, GdkEventButton* event, pViewport* self) { - if(self->viewport.onMousePress) switch(event->button) { - case 1: self->viewport.onMousePress(Mouse::Button::Left); break; - case 2: self->viewport.onMousePress(Mouse::Button::Middle); break; - case 3: self->viewport.onMousePress(Mouse::Button::Right); break; - } - return true; -} - -static gboolean Viewport_mouseRelease(GtkWidget* widget, GdkEventButton* event, pViewport* self) { - if(self->viewport.onMouseRelease) switch(event->button) { - case 1: self->viewport.onMouseRelease(Mouse::Button::Left); break; - case 2: self->viewport.onMouseRelease(Mouse::Button::Middle); break; - case 3: self->viewport.onMouseRelease(Mouse::Button::Right); break; - } - return true; -} - -uintptr_t pViewport::handle() { - return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget)); -} - -void pViewport::setDroppable(bool droppable) { - gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); - if(droppable) gtk_drag_dest_add_uri_targets(gtkWidget); -} - -void pViewport::constructor() { - gtkWidget = gtk_drawing_area_new(); -//gtk_widget_set_double_buffered(gtkWidget, false); - gtk_widget_add_events(gtkWidget, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Viewport_dropEvent), (gpointer)&viewport); - g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Viewport_mousePress), (gpointer)this); - g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this); - g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this); - g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Viewport_mouseMove), (gpointer)this); - - GdkColor color; - color.pixel = 0; - color.red = 0; - color.green = 0; - color.blue = 0; - gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color); -} - -void pViewport::destructor() { - gtk_widget_destroy(gtkWidget); -} - -void pViewport::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/widget/widget.cpp b/phoenix/gtk/widget/widget.cpp deleted file mode 100644 index 1b834d32..00000000 --- a/phoenix/gtk/widget/widget.cpp +++ /dev/null @@ -1,62 +0,0 @@ -namespace phoenix { - -GtkWidget* pWidget::container(Widget& widget) { - return nullptr; -} - -bool pWidget::focused() { - return GTK_WIDGET_HAS_FOCUS(gtkWidget); -} - -Size pWidget::minimumSize() { - return {0, 0}; -} - -void pWidget::setEnabled(bool enabled) { - if(!widget.parent()) enabled = false; - if(widget.state.abstract) enabled = false; - if(!widget.enabledToAll()) enabled = false; - gtk_widget_set_sensitive(gtkWidget, enabled); -} - -void pWidget::setFocused() { - gtk_widget_grab_focus(gtkWidget); -} - -void pWidget::setFont(string font) { - pFont::setFont(gtkWidget, font); -} - -void pWidget::setGeometry(Geometry geometry) { - Position displacement = GetDisplacement(&widget); - geometry.x -= displacement.x; - geometry.y -= displacement.y; - - if(gtkParent) gtk_fixed_move(GTK_FIXED(gtkParent), gtkWidget, geometry.x, geometry.y); - unsigned width = (signed)geometry.width <= 0 ? 1u : geometry.width; - unsigned height = (signed)geometry.height <= 0 ? 1u : geometry.height; - gtk_widget_set_size_request(gtkWidget, width, height); - if(widget.onSize) widget.onSize(); -} - -void pWidget::setVisible(bool visible) { - if(!widget.parent()) visible = false; - if(widget.state.abstract) visible = false; - if(!widget.visibleToAll()) visible = false; - gtk_widget_set_visible(gtkWidget, visible); -} - -void pWidget::constructor() { - if(widget.state.abstract) gtkWidget = gtk_fixed_new(); -} - -void pWidget::destructor() { - if(widget.state.abstract) gtk_widget_destroy(gtkWidget); -} - -void pWidget::orphan() { - destructor(); - constructor(); -} - -} diff --git a/phoenix/gtk/window.cpp b/phoenix/gtk/window.cpp deleted file mode 100644 index 573972be..00000000 --- a/phoenix/gtk/window.cpp +++ /dev/null @@ -1,402 +0,0 @@ -namespace phoenix { - -static gint Window_close(GtkWidget* widget, GdkEvent* event, Window* window) { - if(window->onClose) window->onClose(); - else window->setVisible(false); - if(window->state.modal && !window->visible()) window->setModal(false); - return true; -} - -static gboolean Window_expose(GtkWidget* widget, GdkEvent* event, Window* window) { - if(window->state.backgroundColorOverride == false) return false; - cairo_t* context = gdk_cairo_create(widget->window); - - Color color = window->backgroundColor(); - double red = (double)color.red / 255.0; - double green = (double)color.green / 255.0; - double blue = (double)color.blue / 255.0; - double alpha = (double)color.alpha / 255.0; - - if(gdk_screen_is_composited(gdk_screen_get_default()) - && gdk_screen_get_rgba_colormap(gdk_screen_get_default()) - ) { - cairo_set_source_rgba(context, red, green, blue, alpha); - } else { - cairo_set_source_rgb(context, red, green, blue); - } - - cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); - cairo_paint(context); - cairo_destroy(context); - - return false; -} - -static gboolean Window_configure(GtkWidget* widget, GdkEvent* event, Window* window) { - if(gtk_widget_get_realized(window->p.widget) == false) return false; - if(window->visible() == false) return false; - GdkWindow *gdkWindow = gtk_widget_get_window(widget); - - GdkRectangle border, client; - gdk_window_get_frame_extents(gdkWindow, &border); - gdk_window_get_geometry(gdkWindow, nullptr, nullptr, &client.width, &client.height, nullptr); - gdk_window_get_origin(gdkWindow, &client.x, &client.y); - - if(window->state.fullScreen == false) { - //update geometry settings - settings->geometry.frameX = client.x - border.x; - settings->geometry.frameY = client.y - border.y; - settings->geometry.frameWidth = border.width - client.width; - settings->geometry.frameHeight = border.height - client.height; - if(window->state.backgroundColorOverride == false) { - GdkColor color = widget->style->bg[GTK_STATE_NORMAL]; - settings->window.backgroundColor - = ((uint8_t)(color.red >> 8) << 16) - + ((uint8_t)(color.green >> 8) << 8) - + ((uint8_t)(color.blue >> 8) << 0); - } - settings->save(); - } - - Geometry geometry = { - client.x, - client.y + window->p.menuHeight(), - client.width, - client.height - window->p.menuHeight() - window->p.statusHeight() - }; - - //move - if(geometry.x != window->state.geometry.x || geometry.y != window->state.geometry.y) { - if(window->state.fullScreen == false) { - window->state.geometry.x = geometry.x; - window->state.geometry.y = geometry.y; - } - if(window->p.locked == false && window->onMove) window->onMove(); - } - - //size - if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) { - window->p.onSizePending = true; - } - - return false; -} - -static void Window_drop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, -GtkSelectionData* data, guint type, guint timestamp, Window* window) { - if(window->state.droppable == false) return; - lstring paths = DropPaths(data); - if(paths.empty()) return; - if(window->onDrop) window->onDrop(paths); -} - -static gboolean Window_keyPress(GtkWidget* widget, GdkEventKey* event, Window* window) { - Keyboard::Keycode key = Keysym(event->keyval); - if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key); - return false; -} - -static gboolean Window_keyRelease(GtkWidget* widget, GdkEventKey* event, Window* window) { - Keyboard::Keycode key = Keysym(event->keyval); - if(key != Keyboard::Keycode::None && window->onKeyRelease) window->onKeyRelease(key); - return false; -} - -static void Window_sizeAllocate(GtkWidget* widget, GtkAllocation* allocation, Window* window) { - //size-allocate sent from gtk_fixed_move(); detect if layout unchanged and return - if(allocation->width == window->p.lastAllocation.width - && allocation->height == window->p.lastAllocation.height) return; - - window->state.geometry.width = allocation->width; - window->state.geometry.height = allocation->height; - - for(auto& layout : window->state.layout) { - Geometry geometry = window->geometry(); - geometry.x = geometry.y = 0; - layout.setGeometry(geometry); - } - - if(window->p.onSizePending && window->p.locked == false && window->onSize) { - window->p.onSizePending = false; - window->onSize(); - } - - window->p.lastAllocation = *allocation; -} - -static void Window_sizeRequest(GtkWidget* widget, GtkRequisition* requisition, Window* window) { - requisition->width = window->state.geometry.width; - requisition->height = window->state.geometry.height; -} - -Window& pWindow::none() { - static Window* window = nullptr; - if(window == nullptr) window = new Window; - return *window; -} - -void pWindow::append(Layout& layout) { - Geometry geometry = this->geometry(); - geometry.x = geometry.y = 0; - layout.setGeometry(geometry); -} - -void pWindow::append(Menu& menu) { - if(window.state.menuFont) menu.p.setFont(window.state.menuFont); - else menu.p.setFont(Font::sans(8)); - gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), menu.p.widget); - gtk_widget_show(menu.p.widget); -} - -void pWindow::append(Widget& widget) { - if(widget.font().empty() && !window.state.widgetFont.empty()) { - widget.setFont(window.state.widgetFont); - } - - if(GetParentWidget(&widget)) { - widget.p.gtkParent = GetParentWidget(&widget)->p.container(widget); - } else { - widget.p.gtkParent = formContainer; - } - - gtk_fixed_put(GTK_FIXED(widget.p.gtkParent), widget.p.gtkWidget, 0, 0); - if(widget.state.font) widget.p.setFont(widget.state.font); - else if(window.state.widgetFont) widget.p.setFont(window.state.widgetFont); - else widget.p.setFont(Font::sans(8)); - widget.setVisible(widget.visible()); -} - -Geometry pWindow::frameMargin() { - if(window.state.fullScreen) return { - 0, - menuHeight(), - 0, - menuHeight() + statusHeight() - }; - - return { - settings->geometry.frameX, - settings->geometry.frameY + menuHeight(), - settings->geometry.frameWidth, - settings->geometry.frameHeight + menuHeight() + statusHeight() - }; -} - -bool pWindow::focused() { - return gtk_window_is_active(GTK_WINDOW(widget)); -} - -Geometry pWindow::geometry() { - if(window.state.fullScreen) { - int x, y, width, height; - gtk_window_get_position(GTK_WINDOW(widget), &x, &y); - gtk_window_get_size(GTK_WINDOW(widget), &width, &height); - return {x, y + menuHeight(), width, height - menuHeight() - statusHeight()}; - } - return window.state.geometry; -} - -void pWindow::remove(Layout& layout) { -} - -void pWindow::remove(Menu& menu) { - menu.p.orphan(); -} - -void pWindow::remove(Widget& widget) { - widget.p.orphan(); -} - -void pWindow::setBackgroundColor(Color color) { - GdkColor gdkColor = CreateColor(color.red, color.green, color.blue); - gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor); -} - -void pWindow::setDroppable(bool droppable) { - gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); - if(droppable) gtk_drag_dest_add_uri_targets(widget); -} - -void pWindow::setFocused() { - gtk_window_present(GTK_WINDOW(widget)); -} - -void pWindow::setFullScreen(bool fullScreen) { - if(fullScreen == false) { - gtk_window_unfullscreen(GTK_WINDOW(widget)); - } else { - gtk_window_fullscreen(GTK_WINDOW(widget)); - /*unsigned monitor = gdk_screen_get_monitor_at_window(gdk_screen_get_default(), gtk_widget_get_window(widget)); - GdkRectangle rectangle = {0}; - gdk_screen_get_monitor_geometry(gdk_screen_get_default(), monitor, &rectangle); - gtk_window_set_decorated(GTK_WINDOW(widget), false); - gtk_window_move(GTK_WINDOW(widget), rectangle.x, rectangle.y); - gtk_window_resize(GTK_WINDOW(widget), rectangle.width, rectangle.height); - gtk_widget_set_size_request(formContainer, rectangle.width, rectangle.height);*/ - } -} - -void pWindow::setGeometry(Geometry geometry) { - Geometry margin = frameMargin(); - gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y); - - GdkGeometry geom; - geom.min_width = window.state.resizable ? 1 : window.state.geometry.width; - geom.min_height = window.state.resizable ? 1 : window.state.geometry.height; - gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE); - -//gtk_window_set_policy(GTK_WINDOW(widget), true, true, false); - gtk_widget_set_size_request(formContainer, geometry.width, geometry.height); - gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight()); - - for(auto& layout : window.state.layout) { - Geometry layoutGeometry = geometry; - layoutGeometry.x = layoutGeometry.y = 0; - layout.setGeometry(layoutGeometry); - } -} - -void pWindow::setMenuFont(string font) { - for(auto& item : window.state.menu) item.p.setFont(font); -} - -void pWindow::setMenuVisible(bool visible) { - gtk_widget_set_visible(menu, visible); -} - -void pWindow::setModal(bool modal) { - if(modal == true) { - gtk_window_set_modal(GTK_WINDOW(widget), true); - while(window.state.modal) { - Application::processEvents(); - usleep(20 * 1000); - } - gtk_window_set_modal(GTK_WINDOW(widget), false); - } -} - -void pWindow::setResizable(bool resizable) { - gtk_window_set_resizable(GTK_WINDOW(widget), resizable); - gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(status), resizable); -} - -void pWindow::setStatusFont(string font) { - pFont::setFont(status, font); -} - -void pWindow::setStatusText(string text) { - gtk_statusbar_pop(GTK_STATUSBAR(status), 1); - gtk_statusbar_push(GTK_STATUSBAR(status), 1, text); -} - -void pWindow::setStatusVisible(bool visible) { - gtk_widget_set_visible(status, visible); -} - -void pWindow::setTitle(string text) { - gtk_window_set_title(GTK_WINDOW(widget), text); -} - -void pWindow::setVisible(bool visible) { - gtk_widget_set_visible(widget, visible); - if(visible) { - if(gtk_widget_get_visible(menu)) { - GtkAllocation allocation; - gtk_widget_get_allocation(menu, &allocation); - settings->geometry.menuHeight = allocation.height; - } - - if(gtk_widget_get_visible(status)) { - GtkAllocation allocation; - gtk_widget_get_allocation(status, &allocation); - settings->geometry.statusHeight = allocation.height; - } - } -} - -void pWindow::setWidgetFont(string font) { -} - -void pWindow::constructor() { - lastAllocation.width = 0; - lastAllocation.height = 0; - onSizePending = false; - - widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - //if program was given a name, try and set the window taskbar icon from one of the pixmaps folders - if(applicationState.name.empty() == false) { - string filename = {"/usr/share/pixmaps/", applicationState.name, ".png"}; - if(!file::exists(filename)) filename = {"/usr/local/share/pixmaps/", applicationState.name, ".png"}; - if(file::exists(filename)) { - //maximum image size supported by GTK+ is 256x256; so we must scale larger images ourselves - nall::image icon(filename); - icon.scale(min(256u, icon.width), min(256u, icon.height), true); - GdkPixbuf* pixbuf = CreatePixbuf(icon); - gtk_window_set_icon(GTK_WINDOW(widget), pixbuf); - g_object_unref(G_OBJECT(pixbuf)); - } - } - - GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default()); - if(!colormap) colormap = gdk_screen_get_rgb_colormap(gdk_screen_get_default()); - if(colormap) gtk_widget_set_colormap(widget, colormap); - - gtk_window_set_resizable(GTK_WINDOW(widget), true); - #if GTK_MAJOR_VERSION >= 3 - gtk_window_set_has_resize_grip(GTK_WINDOW(widget), false); - #endif - - gtk_widget_set_app_paintable(widget, true); - gtk_widget_add_events(widget, GDK_CONFIGURE); - - menuContainer = gtk_vbox_new(false, 0); - gtk_container_add(GTK_CONTAINER(widget), menuContainer); - gtk_widget_show(menuContainer); - - menu = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(menuContainer), menu, false, false, 0); - - formContainer = gtk_fixed_new(); - gtk_box_pack_start(GTK_BOX(menuContainer), formContainer, true, true, 0); - gtk_widget_show(formContainer); - - statusContainer = gtk_event_box_new(); - status = gtk_statusbar_new(); - gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(status), true); - gtk_container_add(GTK_CONTAINER(statusContainer), status); - gtk_box_pack_start(GTK_BOX(menuContainer), statusContainer, false, false, 0); - gtk_widget_show(statusContainer); - - setTitle(""); - setResizable(window.state.resizable); - setGeometry(window.state.geometry); - setMenuFont(Font::sans(8)); - setStatusFont(Font::sans(8)); - - g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window); - g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window); - g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window); - g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_drop), (gpointer)&window); - g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPress), (gpointer)&window); - g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPress), (gpointer)&window); - - g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)&window); - g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)&window); - - window.state.backgroundColor = Color( - (uint8_t)(settings->window.backgroundColor >> 16), - (uint8_t)(settings->window.backgroundColor >> 8), - (uint8_t)(settings->window.backgroundColor >> 0) - ); -} - -unsigned pWindow::menuHeight() { - return window.state.menuVisible ? settings->geometry.menuHeight : 0; -} - -unsigned pWindow::statusHeight() { - return window.state.statusVisible ? settings->geometry.statusHeight : 0; -} - -} diff --git a/phoenix/phoenix.cpp b/phoenix/phoenix.cpp deleted file mode 100644 index 63041289..00000000 --- a/phoenix/phoenix.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef PHOENIX_CPP -#define PHOENIX_CPP - -#include "core/core.cpp" - -#endif diff --git a/phoenix/phoenix.hpp b/phoenix/phoenix.hpp deleted file mode 100644 index 21e85af6..00000000 --- a/phoenix/phoenix.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef PHOENIX_HPP -#define PHOENIX_HPP - -#include "core/core.hpp" - -#endif diff --git a/phoenix/qt/keyboard.cpp b/phoenix/qt/keyboard.cpp deleted file mode 100644 index 17821076..00000000 --- a/phoenix/qt/keyboard.cpp +++ /dev/null @@ -1,149 +0,0 @@ -namespace phoenix { - -void pKeyboard::initialize() { - auto append = [](Keyboard::Scancode scancode, unsigned keysym) { - settings->keymap.insert(scancode, XKeysymToKeycode(pApplication::display, keysym)); - }; - - append(Keyboard::Scancode::Escape, XK_Escape); - append(Keyboard::Scancode::F1, XK_F1); - append(Keyboard::Scancode::F2, XK_F2); - append(Keyboard::Scancode::F3, XK_F3); - append(Keyboard::Scancode::F4, XK_F4); - append(Keyboard::Scancode::F5, XK_F5); - append(Keyboard::Scancode::F6, XK_F6); - append(Keyboard::Scancode::F7, XK_F7); - append(Keyboard::Scancode::F8, XK_F8); - append(Keyboard::Scancode::F9, XK_F9); - append(Keyboard::Scancode::F10, XK_F10); - append(Keyboard::Scancode::F11, XK_F11); - append(Keyboard::Scancode::F12, XK_F12); - - append(Keyboard::Scancode::PrintScreen, XK_Print); - append(Keyboard::Scancode::ScrollLock, XK_Scroll_Lock); - append(Keyboard::Scancode::Pause, XK_Pause); - - append(Keyboard::Scancode::Insert, XK_Insert); - append(Keyboard::Scancode::Delete, XK_Delete); - append(Keyboard::Scancode::Home, XK_Home); - append(Keyboard::Scancode::End, XK_End); - append(Keyboard::Scancode::PageUp, XK_Prior); - append(Keyboard::Scancode::PageDown, XK_Next); - - append(Keyboard::Scancode::Up, XK_Up); - append(Keyboard::Scancode::Down, XK_Down); - append(Keyboard::Scancode::Left, XK_Left); - append(Keyboard::Scancode::Right, XK_Right); - - append(Keyboard::Scancode::Grave, XK_asciitilde); - append(Keyboard::Scancode::Number1, XK_1); - append(Keyboard::Scancode::Number2, XK_2); - append(Keyboard::Scancode::Number3, XK_3); - append(Keyboard::Scancode::Number4, XK_4); - append(Keyboard::Scancode::Number5, XK_5); - append(Keyboard::Scancode::Number6, XK_6); - append(Keyboard::Scancode::Number7, XK_7); - append(Keyboard::Scancode::Number8, XK_8); - append(Keyboard::Scancode::Number9, XK_9); - append(Keyboard::Scancode::Number0, XK_0); - append(Keyboard::Scancode::Minus, XK_minus); - append(Keyboard::Scancode::Equal, XK_equal); - append(Keyboard::Scancode::Backspace, XK_BackSpace); - - append(Keyboard::Scancode::BracketLeft, XK_bracketleft); - append(Keyboard::Scancode::BracketRight, XK_bracketright); - append(Keyboard::Scancode::Backslash, XK_backslash); - append(Keyboard::Scancode::Semicolon, XK_semicolon); - append(Keyboard::Scancode::Apostrophe, XK_apostrophe); - append(Keyboard::Scancode::Comma, XK_comma); - append(Keyboard::Scancode::Period, XK_period); - append(Keyboard::Scancode::Slash, XK_slash); - - append(Keyboard::Scancode::Tab, XK_Tab); - append(Keyboard::Scancode::CapsLock, XK_Caps_Lock); - append(Keyboard::Scancode::Return, XK_Return); - append(Keyboard::Scancode::ShiftLeft, XK_Shift_L); - append(Keyboard::Scancode::ShiftRight, XK_Shift_R); - append(Keyboard::Scancode::ControlLeft, XK_Control_L); - append(Keyboard::Scancode::ControlRight, XK_Control_R); - append(Keyboard::Scancode::SuperLeft, XK_Super_L); - append(Keyboard::Scancode::SuperRight, XK_Super_R); - append(Keyboard::Scancode::AltLeft, XK_Alt_L); - append(Keyboard::Scancode::AltRight, XK_Alt_R); - append(Keyboard::Scancode::Space, XK_space); - append(Keyboard::Scancode::Menu, XK_Menu); - - append(Keyboard::Scancode::A, XK_A); - append(Keyboard::Scancode::B, XK_B); - append(Keyboard::Scancode::C, XK_C); - append(Keyboard::Scancode::D, XK_D); - append(Keyboard::Scancode::E, XK_E); - append(Keyboard::Scancode::F, XK_F); - append(Keyboard::Scancode::G, XK_G); - append(Keyboard::Scancode::H, XK_H); - append(Keyboard::Scancode::I, XK_I); - append(Keyboard::Scancode::J, XK_J); - append(Keyboard::Scancode::K, XK_K); - append(Keyboard::Scancode::L, XK_L); - append(Keyboard::Scancode::M, XK_M); - append(Keyboard::Scancode::N, XK_N); - append(Keyboard::Scancode::O, XK_O); - append(Keyboard::Scancode::P, XK_P); - append(Keyboard::Scancode::Q, XK_Q); - append(Keyboard::Scancode::R, XK_R); - append(Keyboard::Scancode::S, XK_S); - append(Keyboard::Scancode::T, XK_T); - append(Keyboard::Scancode::U, XK_U); - append(Keyboard::Scancode::V, XK_V); - append(Keyboard::Scancode::W, XK_W); - append(Keyboard::Scancode::X, XK_X); - append(Keyboard::Scancode::Y, XK_Y); - append(Keyboard::Scancode::Z, XK_Z); - - append(Keyboard::Scancode::NumLock, XK_Num_Lock); - append(Keyboard::Scancode::Divide, XK_KP_Divide); - append(Keyboard::Scancode::Multiply, XK_KP_Multiply); - append(Keyboard::Scancode::Subtract, XK_KP_Subtract); - append(Keyboard::Scancode::Add, XK_KP_Add); - append(Keyboard::Scancode::Enter, XK_KP_Enter); - append(Keyboard::Scancode::Point, XK_KP_Decimal); - - append(Keyboard::Scancode::Keypad1, XK_KP_1); - append(Keyboard::Scancode::Keypad2, XK_KP_2); - append(Keyboard::Scancode::Keypad3, XK_KP_3); - append(Keyboard::Scancode::Keypad4, XK_KP_4); - append(Keyboard::Scancode::Keypad5, XK_KP_5); - append(Keyboard::Scancode::Keypad6, XK_KP_6); - append(Keyboard::Scancode::Keypad7, XK_KP_7); - append(Keyboard::Scancode::Keypad8, XK_KP_8); - append(Keyboard::Scancode::Keypad9, XK_KP_9); - append(Keyboard::Scancode::Keypad0, XK_KP_0); -} - -bool pKeyboard::pressed(Keyboard::Scancode scancode) { - char state[256]; - XQueryKeymap(pApplication::display, state); - if(auto result = settings->keymap.find(scancode)) { - unsigned id = result(); - return state[id >> 3] & (1 << (id & 7)); - } - return false; -} - -vector<bool> pKeyboard::state() { - vector<bool> output; - output.resize((unsigned)Keyboard::Scancode::Limit); - for(auto& n : output) n = false; - - char state[256]; - XQueryKeymap(pApplication::display, state); - for(auto node : settings->keymap) { - if(state[node.value >> 3] & (1 << (node.value & 7))) { - output[(unsigned)node.key] = true; - } - } - - return output; -} - -} diff --git a/phoenix/qt/widget/list-view.cpp b/phoenix/qt/widget/list-view.cpp deleted file mode 100644 index 7d5fd5dc..00000000 --- a/phoenix/qt/widget/list-view.cpp +++ /dev/null @@ -1,156 +0,0 @@ -namespace phoenix { - -void pListView::append(const lstring& text) { - locked = true; - auto items = qtListView->findItems("", Qt::MatchContains); - QTreeWidgetItem* item = new QTreeWidgetItem(qtListView); - - item->setData(0, Qt::UserRole, (unsigned)items.size()); - if(listView.state.checkable) item->setCheckState(0, Qt::Unchecked); - for(unsigned position = 0; position < text.size(); position++) { - item->setText(position, QString::fromUtf8(text[position])); - } - locked = false; -} - -void pListView::autoSizeColumns() { - for(unsigned n = 0; n < listView.state.headerText.size(); n++) qtListView->resizeColumnToContents(n); -} - -void pListView::remove(unsigned selection) { - locked = true; - QTreeWidgetItem* item = qtListView->topLevelItem(selection); - if(item == nullptr) return; - delete item; - locked = false; -} - -void pListView::reset() { - qtListView->clear(); -} - -void pListView::setBackgroundColor(Color color) { -} - -void pListView::setCheckable(bool checkable) { - if(checkable) { - auto items = qtListView->findItems("", Qt::MatchContains); - for(unsigned n = 0; n < items.size(); n++) items[n]->setCheckState(0, Qt::Unchecked); - } -} - -void pListView::setChecked(unsigned selection, bool checked) { - locked = true; - QTreeWidgetItem* item = qtListView->topLevelItem(selection); - if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked); - locked = false; -} - -void pListView::setForegroundColor(Color color) { -} - -void pListView::setHeaderText(const lstring& text) { - QStringList labels; - for(auto& column : text) labels << QString::fromUtf8(column); - - qtListView->setColumnCount(text.size()); - qtListView->setAlternatingRowColors(text.size() >= 2); - qtListView->setHeaderLabels(labels); - autoSizeColumns(); -} - -void pListView::setHeaderVisible(bool visible) { - qtListView->setHeaderHidden(!visible); - autoSizeColumns(); -} - -void pListView::setImage(unsigned selection, unsigned position, const nall::image& image) { - QTreeWidgetItem* item = qtListView->topLevelItem(selection); - if(item) { - if(image.empty() == 0) item->setIcon(position, CreateIcon(image)); - if(image.empty() == 1) item->setIcon(position, QIcon()); - } -} - -void pListView::setSelected(bool selected) { - QTreeWidgetItem* item = qtListView->currentItem(); - if(item) item->setSelected(selected); -} - -void pListView::setSelection(unsigned selection) { - locked = true; - QTreeWidgetItem* item = qtListView->currentItem(); - if(item) item->setSelected(false); - item = qtListView->topLevelItem(selection); - if(item) qtListView->setCurrentItem(item); - locked = false; -} - -void pListView::setText(unsigned selection, unsigned position, string text) { - locked = true; - QTreeWidgetItem* item = qtListView->topLevelItem(selection); - if(item) item->setText(position, QString::fromUtf8(text)); - locked = false; -} - -void pListView::constructor() { - qtWidget = qtListView = new QTreeWidget; - qtListView->setAllColumnsShowFocus(true); - qtListView->setRootIsDecorated(false); - - connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate())); - connect(qtListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(onChange(QTreeWidgetItem*))); - connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onToggle(QTreeWidgetItem*))); - - pWidget::synchronizeState(); - setCheckable(listView.state.checkable); - setHeaderText(listView.state.headerText.size() ? listView.state.headerText : lstring{ " " }); - setHeaderVisible(listView.state.headerVisible); - for(auto& row : listView.state.text) append(row); - if(listView.state.checkable) { - for(unsigned n = 0; n < listView.state.checked.size(); n++) { - setChecked(n, listView.state.checked[n]); - } - } - setSelected(listView.state.selected); - if(listView.state.selected) setSelection(listView.state.selection); - autoSizeColumns(); -} - -void pListView::destructor() { - delete qtListView; - qtWidget = qtListView = nullptr; -} - -void pListView::orphan() { - destructor(); - constructor(); -} - -void pListView::onActivate() { - if(locked == false && listView.onActivate) listView.onActivate(); -} - -void pListView::onChange(QTreeWidgetItem* item) { - bool selected = listView.state.selected; - unsigned selection = listView.state.selection; - if(item) { - item->setSelected(true); //Qt bug workaround: clicking items with mouse does not mark items as selected - listView.state.selected = true; - listView.state.selection = item->data(0, Qt::UserRole).toUInt(); - } else { - listView.state.selected = false; - listView.state.selection = 0; - } - if(selected != listView.state.selected || selection != listView.state.selection) { - if(!locked && listView.onChange) listView.onChange(); - } -} - -void pListView::onToggle(QTreeWidgetItem* item) { - unsigned selection = item->data(0, Qt::UserRole).toUInt(); - listView.state.checked[selection] = (item->checkState(0) == Qt::Checked); - if(!locked && listView.onToggle) listView.onToggle(selection); -} - -} diff --git a/processor/Makefile b/processor/GNUmakefile similarity index 100% rename from processor/Makefile rename to processor/GNUmakefile diff --git a/processor/arm/disassembler.cpp b/processor/arm/disassembler.cpp index eaf9a368..03e90679 100644 --- a/processor/arm/disassembler.cpp +++ b/processor/arm/disassembler.cpp @@ -408,7 +408,7 @@ string ARM::disassemble_arm_instruction(uint32 pc) { output.append(load ? "ldm" : "stm", conditions[condition], indices[index], " "); output.append(registers[rn], writeback ? "!" : "", ",{"); for(unsigned n = 0; n < 16; n++) if(list & (1 << n)) output.append(registers[n], ","); - output.rtrim<1>(","); + output.rtrim(","); output.append("}", s ? "^" : ""); return output; @@ -681,7 +681,7 @@ string ARM::disassemble_thumb_instruction(uint32 pc) { if(list & (1 << l)) output.append(registers[l], ","); } if(branch) output.append(load == 0 ? "lr," : "pc,"); - output.rtrim<1>(","); + output.rtrim(","); output.append("}"); return output; @@ -698,7 +698,7 @@ string ARM::disassemble_thumb_instruction(uint32 pc) { for(unsigned l = 0; l < 8; l++) { if(list & (1 << l)) output.append(registers[l], ","); } - output.rtrim<1>(","); + output.rtrim(","); output.append("}"); return output; diff --git a/processor/lr35902/disassembler.cpp b/processor/lr35902/disassembler.cpp index 8929cf9a..9cf10036 100644 --- a/processor/lr35902/disassembler.cpp +++ b/processor/lr35902/disassembler.cpp @@ -12,9 +12,9 @@ string LR35902::disassemble(uint16 pc) { " SP:", hex<4>(r[SP]) }; - memcpy(output + 0, hex<4>(pc), 4); - memcpy(output + 6, opcode, opcode.length()); - memcpy(output + 23, registers, registers.length()); + memcpy(output + 0, hex<4>(pc).data(), 4); + memcpy(output + 6, opcode.data(), opcode.length()); + memcpy(output + 23, registers.data(), registers.length()); output[63] = 0; return output; } diff --git a/processor/r6502/disassembler.cpp b/processor/r6502/disassembler.cpp index 2537e063..40c7755e 100644 --- a/processor/r6502/disassembler.cpp +++ b/processor/r6502/disassembler.cpp @@ -182,7 +182,7 @@ string R6502::disassemble() { #undef op output.append(" "); - output[20] = 0; + output.resize(20); output.append( "A:", hex<2>(regs.a), " X:", hex<2>(regs.x), " Y:", hex<2>(regs.y), " S:", hex<2>(regs.s), " ", diff --git a/ruby/Makefile b/ruby/GNUmakefile similarity index 100% rename from ruby/Makefile rename to ruby/GNUmakefile diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp index bdf091c9..5e03ebfb 100644 --- a/ruby/ruby.cpp +++ b/ruby/ruby.cpp @@ -1,5 +1,6 @@ #include <ruby/ruby.hpp> +#undef deprecated #undef mkdir #undef usleep #include <ruby/implementation.cpp> diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index ab421564..692cfe5c 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -1,8 +1,11 @@ -/* - ruby - version: 0.11 (2013-12-19) - license: public domain -*/ +/* ruby + * author: byuu + * license: ISC + * version: 0.11 (2013-12-19) + * + * ruby is a cross-platform hardware abstraction layer + * it provides a common interface to video, audio and input devices + */ #ifndef RUBY_H #define RUBY_H diff --git a/ruby/video/opengl/main.hpp b/ruby/video/opengl/main.hpp index 829fda6a..8b90ceff 100644 --- a/ruby/video/opengl/main.hpp +++ b/ruby/video/opengl/main.hpp @@ -28,11 +28,11 @@ void OpenGL::shader(const char* pathname) { for(auto& node : document["output"]) { string text = node.text(); if(node.name == "width") { - if(text.endsWith("%")) relativeWidth = real(text.rtrim<1>("%")) / 100.0; + if(text.endsWith("%")) relativeWidth = real(text.rtrim("%")) / 100.0; else absoluteWidth = decimal(text); } if(node.name == "height") { - if(text.endsWith("%")) relativeHeight = real(text.rtrim<1>("%")) / 100.0; + if(text.endsWith("%")) relativeHeight = real(text.rtrim("%")) / 100.0; else absoluteHeight = decimal(text); } } diff --git a/ruby/video/opengl/program.hpp b/ruby/video/opengl/program.hpp index 21950846..de127ccb 100644 --- a/ruby/video/opengl/program.hpp +++ b/ruby/video/opengl/program.hpp @@ -4,9 +4,9 @@ void OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin modulo = glrModulo(node["modulo"].integer()); string w = node["width"].text(), h = node["height"].text(); - if(w.endsWith("%")) relativeWidth = real(w.rtrim<1>("%")) / 100.0; + if(w.endsWith("%")) relativeWidth = real(w.rtrim("%")) / 100.0; else absoluteWidth = decimal(w); - if(h.endsWith("%")) relativeHeight = real(h.rtrim<1>("%")) / 100.0; + if(h.endsWith("%")) relativeHeight = real(h.rtrim("%")) / 100.0; else absoluteHeight = decimal(h); format = glrFormat(node["format"].text()); @@ -78,7 +78,7 @@ void OpenGLProgram::parse(OpenGL* instance, string& source) { if(auto position = s.find("//")) s.resize(position()); //strip comments s.strip(); //remove extraneous whitespace if(s.match("#in ?*")) { - s.ltrim<1>("#in ").strip(); + s.ltrim("#in ").strip(); if(auto setting = instance->settings.find({s})) { line = {"#define ", setting().name, " ", setting().value}; } else { diff --git a/ruby/video/sdl.cpp b/ruby/video/sdl.cpp index 0079f87d..4c63d237 100644 --- a/ruby/video/sdl.cpp +++ b/ruby/video/sdl.cpp @@ -109,6 +109,7 @@ struct pVideoSDL { bool init() { display = XOpenDisplay(0); + //todo: this causes a segfault inside SDL_SetVideoMode on FreeBSD (works under Linux) char env[512]; sprintf(env, "SDL_WINDOWID=%ld", (long int)settings.handle); putenv(env); diff --git a/ruby/video/xshm.cpp b/ruby/video/xshm.cpp index ef1552a8..f1592218 100644 --- a/ruby/video/xshm.cpp +++ b/ruby/video/xshm.cpp @@ -1,3 +1,10 @@ +//XShm driver for Xorg + +//Note that on composited displays, the alpha bits will allow translucency underneath the active window +//As this is not a feature of ruby, this driver must always set the alpha bits on clear() and refresh() + +//Linear interpolation is only applied horizontally for performance reasons, although Nearest is still much faster + #include <sys/shm.h> #include <X11/extensions/XShm.h> @@ -18,30 +25,22 @@ struct pVideoXShm { } device; struct Settings { - uintptr_t handle; - unsigned depth = 24; + uintptr_t handle = 0; + unsigned filter = Video::FilterLinear; uint32_t* buffer = nullptr; unsigned width, height; } settings; - struct Color { - unsigned depth; - unsigned shift; - - unsigned idepth; - unsigned ishift; - } red, green, blue; - bool cap(const string& name) { if(name == Video::Handle) return true; - if(name == Video::Depth) return true; + if(name == Video::Filter) return true; return false; } any get(const string& name) { if(name == Video::Handle) return settings.handle; - if(name == Video::Depth) return settings.depth; + if(name == Video::Filter) return settings.filter; return false; } @@ -50,8 +49,9 @@ struct pVideoXShm { settings.handle = any_cast<uintptr_t>(value); return true; } - if(name == Video::Depth) { - return setDepth(any_cast<unsigned>(value)); + if(name == Video::Filter) { + settings.filter = any_cast<unsigned>(value); + return true; } return false; } @@ -60,7 +60,7 @@ struct pVideoXShm { if(settings.buffer == nullptr || settings.width != width || settings.height != height) { if(settings.buffer) delete[] settings.buffer; settings.width = width, settings.height = height; - settings.buffer = new uint32_t[width * height](); + settings.buffer = new uint32_t[width * height + 16]; //+16 is padding for linear interpolation } data = settings.buffer; @@ -73,7 +73,9 @@ struct pVideoXShm { void clear() { if(settings.buffer == nullptr) return; - memset(settings.buffer, 0, settings.width * settings.height * sizeof(uint32_t)); + uint32_t* dp = settings.buffer; + unsigned length = settings.width * settings.height; + while(length--) *dp++ = (255u << 24); refresh(); } @@ -81,23 +83,27 @@ struct pVideoXShm { if(settings.buffer == nullptr) return; size(); - float xRatio = (float)settings.width / (float)device.width; - float yRatio = (float)settings.height / (float)device.height; - float yStep = 0; + float xratio = (float)settings.width / (float)device.width; + float yratio = (float)settings.height / (float)device.height; + + #pragma omp parallel for for(unsigned y = 0; y < device.height; y++) { - uint32_t* sp = settings.buffer + (unsigned)yStep * settings.width; + float ystep = y * yratio; + float xstep = 0; + + uint32_t* sp = settings.buffer + (unsigned)ystep * settings.width; uint32_t* dp = device.buffer + y * device.width; - yStep += yRatio; - float xStep = 0; - for(unsigned x = 0; x < device.width; x++) { - uint32_t color = sp[(unsigned)xStep]; - xStep += xRatio; - unsigned r = (color >> red.ishift ) & ((1 << red.idepth ) - 1); - unsigned g = (color >> green.ishift) & ((1 << green.idepth) - 1); - unsigned b = (color >> blue.ishift ) & ((1 << blue.idepth ) - 1); - *dp++ = image::normalize(r, red.idepth, red.depth ) << red.shift - | image::normalize(g, green.idepth, green.depth) << green.shift - | image::normalize(b, blue.idepth, blue.depth ) << blue.shift; + + if(settings.filter == Video::FilterNearest) { + for(unsigned x = 0; x < device.width; x++) { + *dp++ = (255u << 24) | sp[(unsigned)xstep]; + xstep += xratio; + } + } else { //settings.filter == Video::FilterLinear + for(unsigned x = 0; x < device.width; x++) { + *dp++ = (255u << 24) | interpolate(xstep - (unsigned)xstep, sp[(unsigned)xstep], sp[(unsigned)xstep + 1]); + xstep += xratio; + } } } @@ -118,24 +124,12 @@ struct pVideoXShm { XGetWindowAttributes(device.display, (Window)settings.handle, &getAttributes); device.depth = getAttributes.depth; device.visual = getAttributes.visual; - unsigned visualID = XVisualIDFromVisual(device.visual); - - XVisualInfo visualTemplate = {0}; - visualTemplate.screen = device.screen; - visualTemplate.depth = device.depth; - int visualsMatched = 0; - XVisualInfo* visualList = XGetVisualInfo(device.display, VisualScreenMask | VisualDepthMask, &visualTemplate, &visualsMatched); - for(unsigned n = 0; n < visualsMatched; n++) { - auto& v = visualList[n]; - if(v.visualid == visualID) { - red.depth = bit::count(v.red_mask), red.shift = bit::first(v.red_mask); - green.depth = bit::count(v.green_mask), green.shift = bit::first(v.green_mask); - blue.depth = bit::count(v.blue_mask), blue.shift = bit::first(v.blue_mask); - break; - } + //driver only supports 32-bit pixels + //note that even on 15-bit and 16-bit displays, the window visual's depth should be 32 + if(device.depth < 24 || device.depth > 32) { + free(); + return false; } - XFree(visualList); - setDepth(settings.depth); XSetWindowAttributes setAttributes = {0}; setAttributes.border_pixel = 0; @@ -168,26 +162,6 @@ struct pVideoXShm { } //internal: - bool setDepth(unsigned depth) { - if(depth == 24) { - settings.depth = 24; - red.idepth = 8, red.ishift = 16; - green.idepth = 8, green.ishift = 8; - blue.idepth = 8, blue.ishift = 0; - return true; - } - - if(depth == 30) { - settings.depth = 30; - red.idepth = 10, red.ishift = 20; - green.idepth = 10, green.ishift = 10; - blue.idepth = 10, blue.ishift = 0; - return true; - } - - return false; - } - bool size() { XWindowAttributes windowAttributes; XGetWindowAttributes(device.display, settings.handle, &windowAttributes); @@ -197,7 +171,6 @@ struct pVideoXShm { XResizeWindow(device.display, device.window, device.width, device.height); free(); - //create device.shmInfo.shmid = shmget(IPC_PRIVATE, device.width * device.height * sizeof(uint32_t), IPC_CREAT | 0777); if(device.shmInfo.shmid < 0) return false; @@ -220,6 +193,15 @@ struct pVideoXShm { shmdt(device.shmInfo.shmaddr); shmctl(device.shmInfo.shmid, IPC_RMID, 0); } + + alwaysinline uint32_t interpolate(float mu, uint32_t a, uint32_t b) { + uint8_t ar = (a >> 16), ag = (a >> 8), ab = (a >> 0); + uint8_t br = (b >> 16), bg = (b >> 8), bb = (b >> 0); + uint8_t cr = ar * (1.0 - mu) + br * mu; + uint8_t cg = ag * (1.0 - mu) + bg * mu; + uint8_t cb = ab * (1.0 - mu) + bb * mu; + return (cr << 16) | (cg << 8) | (cb << 0); + } }; DeclareVideo(XShm) diff --git a/sfc/Makefile b/sfc/GNUmakefile similarity index 100% rename from sfc/Makefile rename to sfc/GNUmakefile diff --git a/sfc/cartridge/cartridge.cpp b/sfc/cartridge/cartridge.cpp index 4a599991..c9bd946e 100644 --- a/sfc/cartridge/cartridge.cpp +++ b/sfc/cartridge/cartridge.cpp @@ -66,56 +66,44 @@ void Cartridge::load() { //Super Game Boy if(cartridge.has_gb_slot()) { - sha256 = nall::sha256(GameBoy::cartridge.romdata, GameBoy::cartridge.romsize); + sha256 = Hash::SHA256(GameBoy::cartridge.romdata, GameBoy::cartridge.romsize).digest(); } //Broadcast Satellaview else if(cartridge.has_bs_cart() && cartridge.has_bs_slot()) { - sha256 = nall::sha256(satellaviewcartridge.memory.data(), satellaviewcartridge.memory.size()); + sha256 = Hash::SHA256(satellaviewcartridge.memory.data(), satellaviewcartridge.memory.size()).digest(); } //Sufami Turbo else if(cartridge.has_st_slots()) { - sha256_ctx sha; - uint8_t hash[32]; - sha256_init(&sha); - sha256_chunk(&sha, sufamiturboA.rom.data(), sufamiturboA.rom.size()); - sha256_chunk(&sha, sufamiturboB.rom.data(), sufamiturboB.rom.size()); - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto& byte : hash) result.append(hex<2>(byte)); - sha256 = result; + Hash::SHA256 sha; + sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size()); + sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size()); + sha256 = sha.digest(); } //Super Famicom else { - sha256_ctx sha; - uint8_t hash[32]; - vector<uint8_t> buffer; - sha256_init(&sha); + Hash::SHA256 sha; //hash each ROM image that exists; any with size() == 0 is ignored by sha256_chunk() - sha256_chunk(&sha, rom.data(), rom.size()); - sha256_chunk(&sha, bsxcartridge.rom.data(), bsxcartridge.rom.size()); - sha256_chunk(&sha, sa1.rom.data(), sa1.rom.size()); - sha256_chunk(&sha, superfx.rom.data(), superfx.rom.size()); - sha256_chunk(&sha, hitachidsp.rom.data(), hitachidsp.rom.size()); - sha256_chunk(&sha, spc7110.prom.data(), spc7110.prom.size()); - sha256_chunk(&sha, spc7110.drom.data(), spc7110.drom.size()); - sha256_chunk(&sha, sdd1.rom.data(), sdd1.rom.size()); + sha.data(rom.data(), rom.size()); + sha.data(bsxcartridge.rom.data(), bsxcartridge.rom.size()); + sha.data(sa1.rom.data(), sa1.rom.size()); + sha.data(superfx.rom.data(), superfx.rom.size()); + sha.data(hitachidsp.rom.data(), hitachidsp.rom.size()); + sha.data(spc7110.prom.data(), spc7110.prom.size()); + sha.data(spc7110.drom.data(), spc7110.drom.size()); + sha.data(sdd1.rom.data(), sdd1.rom.size()); //hash all firmware that exists + vector<uint8> buffer; buffer = armdsp.firmware(); - sha256_chunk(&sha, buffer.data(), buffer.size()); + sha.data(buffer.data(), buffer.size()); buffer = hitachidsp.firmware(); - sha256_chunk(&sha, buffer.data(), buffer.size()); + sha.data(buffer.data(), buffer.size()); buffer = necdsp.firmware(); - sha256_chunk(&sha, buffer.data(), buffer.size()); + sha.data(buffer.data(), buffer.size()); //finalize hash - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto& byte : hash) result.append(hex<2>(byte)); - sha256 = result; + sha256 = sha.digest(); } rom.write_protect(true); diff --git a/sfc/chip/event/event.cpp b/sfc/chip/event/event.cpp index b7276295..5ffae110 100644 --- a/sfc/chip/event/event.cpp +++ b/sfc/chip/event/event.cpp @@ -63,7 +63,7 @@ void Event::submitScore() { lstring side = interface->server().split<1>("@"); string username = side(0).split<1>(":")(0); string password = side(0).split<1>(":")(1); - side(1).ltrim<1>("http://"); + side(1).ltrim("http://"); string hostname = side(1).split<1>("/")(0); string hostpath = side(1).split<1>("/")(1); side = hostname.split<1>(":"); @@ -71,7 +71,7 @@ void Event::submitScore() { string hostport = side(1); if(hostport.empty()) hostport = "80"; - http server; +/*http server; if(server.connect(hostname, decimal(hostport))) { string content = { "username:", username, "\n", @@ -92,7 +92,7 @@ void Event::submitScore() { }; server.send(packet); server.disconnect(); - } + }*/ } void Event::init() { diff --git a/sfc/chip/hsu1/hsu1.cpp b/sfc/chip/hsu1/hsu1.cpp index 5feaebf3..6cf06d63 100644 --- a/sfc/chip/hsu1/hsu1.cpp +++ b/sfc/chip/hsu1/hsu1.cpp @@ -55,7 +55,7 @@ void HSU1::write(unsigned addr, uint8 data) { lstring side = interface->server().split<1>("@"); string username = side(0).split<1>(":")(0); string password = side(0).split<1>(":")(1); - side(1).ltrim<1>("http://"); + side(1).ltrim("http://"); string hostname = side(1).split<1>("/")(0); string hostpath = side(1).split<1>("/")(1); side = hostname.split<1>(":"); @@ -63,7 +63,7 @@ void HSU1::write(unsigned addr, uint8 data) { string hostport = side(1); if(hostport.empty()) hostport = "80"; - http server; + /*http server; if(server.connect(hostname, decimal(hostport))) { string header { "username:", username, "\n", @@ -97,7 +97,7 @@ void HSU1::write(unsigned addr, uint8 data) { free(data); server.disconnect(); - } + }*/ } txlatch = latch; } diff --git a/sfc/system/serialization.cpp b/sfc/system/serialization.cpp index a29a9eeb..3c68e902 100644 --- a/sfc/system/serialization.cpp +++ b/sfc/system/serialization.cpp @@ -8,7 +8,7 @@ serializer System::serialize() { memcpy(&hash, (const char*)cartridge.sha256(), 64); memset(&description, 0, sizeof description); memset(&profile, 0, sizeof profile); - strmcpy(profile, Emulator::Profile, sizeof profile); + strcpy(profile, Emulator::Profile); s.integer(signature); s.integer(version); diff --git a/target-higan/GNUmakefile b/target-higan/GNUmakefile new file mode 100644 index 00000000..2f741edc --- /dev/null +++ b/target-higan/GNUmakefile @@ -0,0 +1,53 @@ +name := higan + +processors := arm gsu hg51b lr35902 r6502 r65816 spc700 upd96050 +include processor/GNUmakefile +include fc/GNUmakefile +include sfc/GNUmakefile +include gb/GNUmakefile +include gba/GNUmakefile + +ui_objects := ui-higan +ui_objects += ruby hiro + +# platform +ifeq ($(platform),windows) +else ifeq ($(platform),macosx) +else ifeq ($(platform),linux) +else ifeq ($(platform),bsd) + ruby := video.glx video.xshm + ruby += audio.openal audio.oss + ruby += input.xlib +endif + +# ruby +include ruby/GNUmakefile +link += $(rubylink) + +# hiro +include hiro/GNUmakefile +link += $(hirolink) + +# rules +objects := $(ui_objects) $(objects) +objects := $(patsubst %,obj/%.o,$(objects)) + +obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/) + $(compiler) $(rubyflags) -c $< -o $@ + +obj/hiro.o: hiro/hiro.cpp $(call rwildcard,hiro/) + $(compiler) $(hiroflags) -c $< -o $@ + +obj/ui-higan.o: $(ui)/higan.cpp $(call rwildcard,$(ui)/) + +# build +build: $(objects) + $(strip $(compiler) -o out/$(name) $(objects) $(link)) + +install: + cp out/$(name) $(prefix)/bin/$(name) + cp data/higan.png $(prefix)/share/icons/higan.png + +uninstall: + if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi + if [ -f $(prefix)/share/icons/higan.png ]; then rm $(prefix)/share/icons/higan.png diff --git a/target-higan/Makefile b/target-higan/Makefile deleted file mode 100644 index 6e726ce5..00000000 --- a/target-higan/Makefile +++ /dev/null @@ -1,117 +0,0 @@ -name := higan - -processors := arm gsu hg51b lr35902 r6502 r65816 spc700 upd96050 -include processor/Makefile - -include fc/Makefile -include sfc/Makefile -include gb/Makefile -include gba/Makefile - -ui_objects := ui-higan ui-configuration ui-interface ui-utility -ui_objects += ui-input ui-window ui-general ui-settings ui-tools -ui_objects += phoenix ruby -ui_objects += $(if $(call streq,$(platform),windows),resource) - -# platform -ifeq ($(platform),windows) - ruby := video.direct3d video.wgl video.directdraw video.gdi - ruby += audio.directsound audio.xaudio2 - ruby += input.windows -else ifeq ($(platform),macosx) - ruby := video.cgl - ruby += audio.openal - ruby += input.carbon -else ifeq ($(platform),linux) - ruby := video.glx video.xv video.xshm video.sdl - ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao - ruby += input.udev input.sdl input.xlib -else ifeq ($(platform),bsd) - ruby := video.glx - ruby += audio.openal audio.oss - ruby += input.xlib -endif - -# phoenix -include phoenix/Makefile -link += $(phoenixlink) - -# ruby -include ruby/Makefile -link += $(rubylink) - -# rules -objects := $(ui_objects) $(objects) -objects := $(patsubst %,obj/%.o,$(objects)) - -obj/ui-higan.o: $(ui)/higan.cpp $(call rwildcard,$(ui)/) -obj/ui-configuration.o: $(ui)/configuration/configuration.cpp $(call rwildcard,$(ui)/) -obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/) -obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/) -obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/) -obj/ui-window.o: $(ui)/window/window.cpp $(call rwildcard,$(ui)/) -obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/) -obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/) -obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/) - -obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/) - $(compiler) $(rubyflags) -c $< -o $@ - -obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/) - $(compiler) $(phoenixflags) -c $< -o $@ - -obj/resource.o: $(ui)/resource.rc -ifeq ($(arch),win32) - windres --target=pe-i386 $(ui)/resource.rc obj/resource.o -else - windres $(ui)/resource.rc obj/resource.o -endif - -# targets -build: $(objects) -ifeq ($(platform),windows) - $(strip $(compiler) -shared -o out/phoenix.dll obj/phoenix.o $(phoenixlink)) - $(strip $(compiler) -o out/$(name) $(subst obj/phoenix.o,,$(objects)) $(link) -Lout -lphoenix) -else ifeq ($(platform),macosx) - if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi - mkdir out/$(name).app - mkdir out/$(name).app/Contents - mkdir out/$(name).app/Contents/MacOS - mkdir out/$(name).app/Contents/Resources - cp data/Info.plist out/$(name).app/Contents/Info.plist - sips -s format icns data/higan.png --out out/$(name).app/Contents/Resources/higan.icns - $(strip $(compiler) -o out/$(name).app/Contents/MacOS/$(name) $(objects) $(link)) -else - $(strip $(compiler) -o out/$(name) $(objects) $(link)) -endif - -resource: - sourcery $(ui)/resource/resource.bml $(ui)/resource/resource.cpp $(ui)/resource/resource.hpp - -install: -ifneq ($(shell id -un),root) - $(error "make install must be run as root") -else ifeq ($(platform),windows) -else ifeq ($(platform),macosx) - mkdir -p /Library/Application\ Support/$(name) - cp -R profile/* /Library/Application\ Support/$(name) - cp data/cheats.bml /Library/Application\ Support/$(name)/cheats.bml - chmod -R 777 /Library/Application\ Support/$(name) -else - cp out/$(name) $(prefix)/bin/$(name) - cp data/$(name).png $(prefix)/share/pixmaps/$(name).png - cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop - mkdir -p /usr/share/$(name) - cp -R profile/* /usr/share/$(name) - cp data/cheats.bml /usr/share/$(name)/cheats.bml - chmod -R 777 /usr/share/$(name) -endif - -uninstall: -ifneq ($(shell id -un),root) - $(error "make uninstall must be run as root") -else ifeq ($(platform),windows) -else ifeq ($(platform),macosx) -else - rm $(prefix)/bin/$(name) -endif diff --git a/target-higan/bootstrap.cpp b/target-higan/bootstrap.cpp deleted file mode 100644 index 5b14e25e..00000000 --- a/target-higan/bootstrap.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include <fc/interface/interface.hpp> -#include <sfc/interface/interface.hpp> -#include <gb/interface/interface.hpp> -#include <gba/interface/interface.hpp> - -void Program::bootstrap() { - interface = new Interface; - - emulator.append(new Famicom::Interface); - emulator.append(new SuperFamicom::Interface); - emulator.append(new GameBoy::Interface); - emulator.append(new GameBoyAdvance::Interface); - - for(auto& system : emulator) system->bind = interface; -} diff --git a/target-higan/configuration/configuration.cpp b/target-higan/configuration/configuration.cpp deleted file mode 100644 index 612f1bfc..00000000 --- a/target-higan/configuration/configuration.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "../higan.hpp" -ConfigurationSettings* config = nullptr; - -ConfigurationSettings::ConfigurationSettings() { - video.append(video.driver = ruby::video.optimalDriver(), "Driver"); - video.append(video.synchronize = false, "Synchronize"); - video.append(video.shader = "Blur", "Shader"); - video.append(video.scaleMode = 0, "ScaleMode"); - video.append(video.aspectCorrection = true, "AspectCorrection"); - video.append(video.colorEmulation = true, "ColorEmulation"); - video.maskOverscan.assign(video.maskOverscan.enable = false); - video.maskOverscan.append(video.maskOverscan.horizontal = 8, "Horizontal"); - video.maskOverscan.append(video.maskOverscan.vertical = 8, "Vertical"); - video.append(video.maskOverscan, "MaskOverscan"); - video.append(video.saturation = 100, "Saturation"); - video.append(video.gamma = 100, "Gamma"); - video.append(video.luminance = 100, "Luminance"); - video.append(video.startFullScreen = false, "StartFullScreen"); - append(video, "Video"); - - audio.append(audio.driver = ruby::audio.optimalDriver(), "Driver"); - audio.append(audio.synchronize = true, "Synchronize"); - audio.append(audio.frequency = 48000, "Frequency"); - audio.append(audio.latency = 60, "Latency"); - audio.append(audio.resampler = 2, "Resampler"); - audio.append(audio.volume = 100, "Volume"); - audio.append(audio.mute = false, "Mute"); - append(audio, "Audio"); - - input.append(input.driver = ruby::input.optimalDriver(), "Driver"); - input.focus.append(input.focus.pause = false, "Pause"); - input.focus.append(input.focus.allow = false, "AllowInput"); - input.append(input.focus, "Focus"); - append(input, "Input"); - - timing.append(timing.video = 60.0, "Video"); - timing.append(timing.audio = 48000.0, "Audio"); - append(timing, "Timing"); - - server.append(server.hostname = "", "Hostname"); - server.append(server.username = "", "Username"); - server.append(server.password = "", "Password"); - append(server, "Server"); - - library.append(library.selection = -1, "Selection"); - library.append(library.mediaMode = 0, "MediaMode"); - library.append(library.showOnStartup = true, "ShowOnStartup"); - append(library, "Library"); - - load(); -} - -void ConfigurationSettings::load() { - Configuration::Document::load(program->path("settings.bml")); - save(); //creates file if it does not exist -} - -void ConfigurationSettings::save() { - Configuration::Document::save(program->path("settings.bml")); -} diff --git a/target-higan/configuration/configuration.hpp b/target-higan/configuration/configuration.hpp deleted file mode 100644 index 9591669c..00000000 --- a/target-higan/configuration/configuration.hpp +++ /dev/null @@ -1,60 +0,0 @@ -struct ConfigurationSettings : Configuration::Document { - struct Video : Configuration::Node { - string driver; - bool synchronize; - string shader; - unsigned scaleMode; - bool aspectCorrection; - bool colorEmulation; - struct MaskOverscan : Configuration::Node { - bool enable; - unsigned horizontal; - unsigned vertical; - } maskOverscan; - unsigned saturation; - unsigned gamma; - unsigned luminance; - bool startFullScreen; - } video; - - struct Audio : Configuration::Node { - string driver; - bool synchronize; - unsigned frequency; - unsigned latency; - unsigned resampler; - unsigned volume; - bool mute; - } audio; - - struct Input : Configuration::Node { - string driver; - struct Focus : Configuration::Node { - bool pause; - bool allow; - } focus; - } input; - - struct Timing : Configuration::Node { - double video; - double audio; - } timing; - - struct Server : Configuration::Node { - string hostname; - string username; - string password; - } server; - - struct Library : Configuration::Node { - signed selection; - unsigned mediaMode; - bool showOnStartup; - } library; - - void load(); - void save(); - ConfigurationSettings(); -}; - -extern ConfigurationSettings* config; diff --git a/target-higan/general/dip-switches.cpp b/target-higan/general/dip-switches.cpp deleted file mode 100644 index 2734daaa..00000000 --- a/target-higan/general/dip-switches.cpp +++ /dev/null @@ -1,66 +0,0 @@ -DipSwitches* dipSwitches = nullptr; - -DipSwitch::DipSwitch() { - append(name, {100, 0}, 5); - append(value, {~0, 0}); -} - -DipSwitches::DipSwitches() { - setTitle("DIP Switches"); - layout.setMargin(5); - accept.setText("Accept"); - - append(layout); - for(auto& dipItem : dip) layout.append(dipItem, {~0, 0}, 5); - layout.append(controlLayout, {~0, 0}); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(accept, {80, 0}); - - setGeometry({128, 128, 250, layout.minimumSize().height}); - windowManager->append(this, "DipSwitches"); - - onClose = accept.onActivate = [&] { - setModal(false); - setVisible(false); - }; -} - -unsigned DipSwitches::run(const Markup::Node& node) { - for(auto& dipItem : dip) { - dipItem.name.setEnabled(false); - dipItem.name.setText("(empty)"); - dipItem.value.setEnabled(false); - dipItem.value.reset(); - dipItem.values.reset(); - } - - unsigned index = 0; - for(auto& setting : node) { - if(setting.name != "setting") continue; - dip[index].name.setEnabled(); - dip[index].name.setText(setting["name"].data); - dip[index].value.setEnabled(); - for(auto& option : setting) { - if(option.name != "option") continue; - if(auto result = Eval::integer(option["value"].data)) { - dip[index].value.append(option["name"].data); - dip[index].values.append(result()); - } - } - - if(++index >= Slots) break; - } - - setVisible(); - accept.setFocused(); - - audio.clear(); - setModal(); - - unsigned result = 0; - for(auto& dipItem : dip) { - if(dipItem.value.enabled() == false) continue; - result |= dipItem.values[dipItem.value.selection()]; - } - return result; -} diff --git a/target-higan/general/dip-switches.hpp b/target-higan/general/dip-switches.hpp deleted file mode 100644 index 0b25b73d..00000000 --- a/target-higan/general/dip-switches.hpp +++ /dev/null @@ -1,22 +0,0 @@ -struct DipSwitch : HorizontalLayout { - Label name; - ComboButton value; - vector<unsigned> values; - - DipSwitch(); -}; - -struct DipSwitches : Window { - enum : unsigned { Slots = 8 }; - - VerticalLayout layout; - DipSwitch dip[Slots]; - HorizontalLayout controlLayout; - Widget spacer; - Button accept; - - unsigned run(const Markup::Node& node); - DipSwitches(); -}; - -extern DipSwitches* dipSwitches; diff --git a/target-higan/general/general.cpp b/target-higan/general/general.cpp deleted file mode 100644 index fd34b8fa..00000000 --- a/target-higan/general/general.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "../higan.hpp" -#include "library.cpp" -#include "presentation.cpp" -#include "dip-switches.cpp" diff --git a/target-higan/general/general.hpp b/target-higan/general/general.hpp deleted file mode 100644 index 4e612af2..00000000 --- a/target-higan/general/general.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "library.hpp" -#include "presentation.hpp" -#include "dip-switches.hpp" diff --git a/target-higan/general/library.cpp b/target-higan/general/library.cpp deleted file mode 100644 index 3ce67235..00000000 --- a/target-higan/general/library.cpp +++ /dev/null @@ -1,298 +0,0 @@ -LibraryManager* libraryManager = nullptr; - -LibraryBrowser::LibraryBrowser(Emulator::Interface& emulator) : emulator(emulator) { - setMargin(5); - - informationType.setText({ - "Title:\n", - "Serial:" - }); - - for(auto& media : emulator.media) { - mediaMode.append(media.name); - } - - unsigned height = Font::size(program->normalFont, " ").height; - - append(folders, {~0, ~0}, 5); - append(informationLayout, {~0, 0}); - informationLayout.append(informationType, {0, height * 2}, 5); - informationLayout.append(information, {~0, height * 2}, 5); - informationLayout.append(mediaMode, {0, 0}); - - folders.onActivate = {&LibraryBrowser::onActivate, this}; - folders.onChange = {&LibraryBrowser::onChange, this}; - mediaMode.onChange = {&LibraryBrowser::setMode, this}; -} - -void LibraryBrowser::onActivate() { - if(folders.selected() == false) return; - if(libraryManager->loadButton.enabled() == false) return; - - unsigned selection = folders.selection(); - string pathname = {this->pathname, folders.text(selection, 0), typeSuffix}; - - libraryManager->loaded.append(folders.text(selection, 0)); - libraryManager->setInformation(false); - - if(libraryManager->slotLoad == false) { - utility->loadMedia(pathname); - } else { - libraryManager->loadPathname = pathname; - libraryManager->setModal(false); - } -} - -void LibraryBrowser::onChange() { - if(folders.selected() == false) return information.setText(""); - - string manifest = {pathname, folders.text(folders.selection(), 0), typeSuffix, "manifest.bml"}; - auto document = Markup::Document(file::read(manifest)); - - information.setText({ - document["information/title"].text(), "\n", - document["information/serial"].text() - }); -} - -void LibraryBrowser::refresh() { - folders.reset(); - lstring pathnames = directory::ifolders(pathname, typeMask); - unsigned selection = 0; - for(auto& pathname : pathnames) { - folders.append(string{pathname}.rtrim<1>(typeSuffix)); - folders.setImage(selection++, 0, {resource::game, sizeof resource::game}); - } - folders.setSelection(0); - onChange(); -} - -void LibraryBrowser::setMode() { - config->library.mediaMode = mediaMode.selection(); - auto& media = emulator.media[mediaMode.selection()]; - - pathname = {utility->libraryPath(), media.name, "/"}; - type = media.type; - typeMask = {"*.", type}; - typeSuffix = {".", type, "/"}; - - refresh(); - folders.setFocused(); - libraryManager->synchronize(); -} - -LibraryImport::LibraryImport() { - setMargin(5); - information.setText({ - "higan manages games in a library. To play a game, you must first import the game.\n" - "After doing so, the game will appear inside your library, and can then be loaded and played." - }); - importButton.setText("Import Game ..."); - append(information, {~0, 0}, 5); - append(importButton, {0, 0}); - - importButton.onActivate = {&LibraryImport::onImportActivate, this}; -} - -void LibraryImport::onImportActivate() { - if(program->ananke.open() == false) { - MessageWindow().setText("ananke must be installed to use this feature").warning(); - return; - } - function<string ()> browse = program->ananke.sym("ananke_browse"); - if(!browse) return; - audio.clear(); //ananke's browser is modal - string pathname = browse(); - pathname.rtrim<1>("/"); - if(pathname.empty()) return; - - //after importing game, take user to the relevant game list to show the newly imported title - string type = extension(pathname); - for(signed bootable = 1; bootable >= 0; bootable--) { - unsigned selection = 0; - for(auto& browser : libraryManager->browsers) { - unsigned mode = 0; - for(auto& media : browser->emulator.media) { - if(type == media.type && media.bootable == bootable) { - browser->mediaMode.setSelection(mode); - libraryManager->libraryFrame.setSelection(selection); - libraryManager->onChange(); - - //find game in list and select it - string name = notdir(nall::basename(pathname)); - for(unsigned n = 0; n < browser->folders.rows(); n++) { - if(browser->folders.text(n, 0) == name) { - browser->folders.setSelection(n); - browser->onChange(); - break; - } - } - - return; - } - mode++; - } - selection++; - } - } -} - -LibraryManager::LibraryManager() { - libraryManager = this; - - setTitle("Game Library"); - setGeometry({128, 128, 640, 680}); - windowManager->append(this, "LibraryManager"); - - layout.setMargin(5); - bootstrap(); - libraryFrame.append("Import"); - libraryFrame.setLayout(browsers.size(), libraryImport); - loadButton.setText("Load"); - - unsigned height = Font::size(program->normalFont, " ").height; - - append(layout); - layout.append(libraryFrame, {~0, ~0}, 5); - layout.append(informationLayout, {~0, 0}); - informationLayout.append(information, {~0, height * 3}, 5); - informationLayout.append(skipButton, {80, 0}, 5); - informationLayout.append(loadButton, {80, 0}); - - onClose = skipButton.onActivate = [&] { - setModal(false); - setVisible(false); - }; - - libraryFrame.onChange = {&LibraryManager::onChange, this}; - loadButton.onActivate = {&LibraryManager::onLoad, this}; - - //initial config value of -1 defaults to import tab on first launch of higan - if(config->library.selection < 0) config->library.selection = browsers.size(); - libraryFrame.setSelection(config->library.selection); - - if(libraryFrame.selection() < browsers.size()) { - browsers[libraryFrame.selection()]->mediaMode.setSelection(config->library.mediaMode); - browsers[libraryFrame.selection()]->setMode(); - } -} - -void LibraryManager::bootstrap() { - unsigned selection = 0; - for(auto& emulator : program->emulator) { - LibraryBrowser* browser = new LibraryBrowser(*emulator); - libraryFrame.append(emulator->information.name); - libraryFrame.setLayout(selection++, *browser); - browsers.append(browser); - } -} - -string LibraryManager::load(const string& type) { - requestedLoadType = type; - unsigned selection = 0; - for(auto& browser : browsers) { - unsigned mode = 0; - for(auto& media : browser->emulator.media) { - if(type == media.type && media.bootable == false) { - libraryFrame.setSelection(selection); - browser->mediaMode.setSelection(mode); - browser->setMode(); - - slotLoad = true; - loadPathname = ""; - show(); - setModal(); - slotLoad = false; - browser->mediaMode.setSelection(config->library.mediaMode = 0); - return loadPathname; - } - mode++; - } - selection++; - } - return ""; //should never occur -} - -void LibraryManager::onChange() { - unsigned selection = libraryFrame.selection(); - config->library.selection = selection; - if(selection < browsers.size()) { - browsers[selection]->setMode(); - } else { - loadButton.setEnabled(false); - } -} - -void LibraryManager::onLoad() { - unsigned selection = libraryFrame.selection(); - if(selection < browsers.size()) browsers[selection]->onActivate(); -} - -void LibraryManager::setInformation(bool load) { - string text; - if(loaded.size() == 0) { - text = {" \nPlease select a game to load ...\n "}; - } else if(loaded.size() == 1 && load == false) { - text = {" \n", loaded[0], "\n "}; - } else if(loaded.size() == 1 && load == true) { - text = {loaded[0], " \nPlease select a slot game to load ...\n "}; - } else if(loaded.size() == 2 && load == false) { - text = {loaded[0], "\n", loaded[1], "\n "}; - } else if(loaded.size() == 2 && load == true) { - text = {loaded[0], "\n", loaded[1], "\nPlease select a slot game to load ..."}; - } else if(loaded.size() == 3) { - text = {loaded[0], "\n", loaded[1], "\n", loaded[2]}; - } - information.setText(text); -} - -void LibraryManager::show() { - if(slotLoad == false) { - loaded.reset(); - requestedLoadType.reset(); - skipButton.setText("Cancel"); - } else { - skipButton.setText("Skip"); - } - - setInformation(true); - setVisible(); - setFocused(); - onChange(); -} - -//set library to show a specific media type, and then show the library -void LibraryManager::show(const string& type) { - unsigned selection = 0; - for(auto& browser : browsers) { - unsigned mode = 0; - for(auto& media : browser->emulator.media) { - if(media.bootable && media.type == type) { - libraryFrame.setSelection(selection); - browser->mediaMode.setSelection(mode); - browser->setMode(); - return show(); - } - mode++; - } - selection++; - } -} - -void LibraryManager::synchronize() { - if(libraryFrame.selection() < browsers.size()) { - auto& emulator = browsers[libraryFrame.selection()]->emulator; - auto& media = emulator.media[browsers[libraryFrame.selection()]->mediaMode.selection()]; - - if(requestedLoadType.empty()) { - loadButton.setEnabled(media.bootable); - } else { - bool enabled = (requestedLoadType == media.type); - //allow Super Game Boy to load Game Boy Color games - if(requestedLoadType == "gb" && loaded.size() == 1 && media.type == "gbc") enabled = true; - loadButton.setEnabled(enabled); - } - } else { - loadButton.setEnabled(false); - } -} diff --git a/target-higan/general/library.hpp b/target-higan/general/library.hpp deleted file mode 100644 index 7d93f4c9..00000000 --- a/target-higan/general/library.hpp +++ /dev/null @@ -1,55 +0,0 @@ -struct LibraryBrowser : VerticalLayout { - ListView folders; - HorizontalLayout informationLayout; - Label informationType; - Label information; - ComboButton mediaMode; - - LibraryBrowser(Emulator::Interface& emulator); - void onActivate(); - void onChange(); - void refresh(); - void setMode(); - - Emulator::Interface& emulator; - string pathname; - string type; - string typeMask; - string typeSuffix; -}; - -struct LibraryImport : VerticalLayout { - Label information; - Button importButton; - - LibraryImport(); - void onImportActivate(); -}; - -struct LibraryManager : Window { - VerticalLayout layout; - TabFrame libraryFrame; - vector<LibraryBrowser*> browsers; - LibraryImport libraryImport; - HorizontalLayout informationLayout; - Label information; - Button skipButton; - Button loadButton; - - LibraryManager(); - void bootstrap(); - string load(const string& type); - void onChange(); - void onLoad(); - void setInformation(bool load); - void show(); - void show(const string& type); - void synchronize(); - - lstring loaded; - string requestedLoadType; - bool slotLoad = false; - string loadPathname; -}; - -extern LibraryManager* libraryManager; diff --git a/target-higan/general/presentation.cpp b/target-higan/general/presentation.cpp deleted file mode 100644 index 651a11ac..00000000 --- a/target-higan/general/presentation.cpp +++ /dev/null @@ -1,257 +0,0 @@ -Presentation* presentation = nullptr; - -void Presentation::synchronize() { - for(auto& emulator : emulatorList) emulator->menu.setVisible(false); - for(auto& emulator : emulatorList) { - if(emulator->interface == program->active) { - active = emulator; - emulator->menu.setVisible(true); - } - } - - shaderNone.setChecked(); - if(config->video.shader == "None") shaderNone.setChecked(); - if(config->video.shader == "Blur") shaderBlur.setChecked(); - if(config->video.shader == "Display Emulation") shaderEmulation.setChecked(); - for(auto& shader : shaderList) { - string name = notdir(config->video.shader.split<1>(".shader/")(0)); - if(name == shader->text()) shader->setChecked(); - } - - switch(config->video.scaleMode) { - case 0: centerVideo.setChecked(); break; - case 1: scaleVideo.setChecked(); break; - case 2: stretchVideo.setChecked(); break; - } - aspectCorrection.setChecked(config->video.aspectCorrection); - maskOverscan.setChecked(config->video.maskOverscan.enable); - synchronizeVideo.setChecked(config->video.synchronize); - synchronizeAudio.setChecked(config->audio.synchronize); - muteAudio.setChecked(config->audio.mute); - - if(program->active == nullptr) { - toolsMenu.setVisible(false); - } else { - toolsMenu.setVisible(true); - saveStateMenu.setVisible(system().information.capability.states); - loadStateMenu.setVisible(system().information.capability.states); - stateMenuSeparator.setVisible(system().information.capability.states); - resizeWindow.setVisible(config->video.scaleMode != 2); - stateManager.setVisible(system().information.capability.states); - cheatEditor.setVisible(system().information.capability.cheats); - synchronizeTime.setVisible(system().rtc()); - } -} - -void Presentation::setSystemName(string name) { - if(active) active->menu.setText(systemName = name); -} - -Presentation::Presentation() { - bootstrap(); - loadShaders(); - setGeometry({256, 256, 720, 480}); - windowManager->append(this, "Presentation"); - - setTitle({::Emulator::Name, " v", ::Emulator::Version}); - setBackgroundColor({0, 0, 0}); - setMenuVisible(); - setStatusVisible(); - - setDroppable(); - viewport.setDroppable(); - - loadMenu.setText("Library"); - settingsMenu.setText("Settings"); - videoMenu.setText("Video"); - centerVideo.setText("Center"); - scaleVideo.setText("Scale"); - stretchVideo.setText("Stretch"); - RadioItem::group(centerVideo, scaleVideo, stretchVideo); - aspectCorrection.setText("Aspect Correction"); - maskOverscan.setText("Mask Overscan"); - shaderMenu.setText("Shader"); - shaderNone.setText("None"); - shaderBlur.setText("Blur"); - shaderEmulation.setText("Display Emulation"); - synchronizeVideo.setText("Synchronize Video"); - synchronizeAudio.setText("Synchronize Audio"); - muteAudio.setText("Mute Audio"); - configurationSettings.setText("Configuration ..."); - toolsMenu.setText("Tools"); - saveStateMenu.setText("Save State"); - for(unsigned n = 0; n < 5; n++) saveStateItem[n].setText({"Slot ", 1 + n}); - loadStateMenu.setText("Load State"); - for(unsigned n = 0; n < 5; n++) loadStateItem[n].setText({"Slot ", 1 + n}); - resizeWindow.setText("Resize Window"); - stateManager.setText("State Manager"); - cheatEditor.setText("Cheat Editor"); - synchronizeTime.setText("Synchronize Time"); - - append(loadMenu); - for(auto& item : loadBootableMedia) loadMenu.append(*item); - for(auto& systemItem : emulatorList) append(systemItem->menu); - append(settingsMenu); - settingsMenu.append(videoMenu); - videoMenu.append(centerVideo); - videoMenu.append(scaleVideo); - videoMenu.append(stretchVideo); - videoMenu.append(*new Separator); - videoMenu.append(aspectCorrection); - videoMenu.append(maskOverscan); - settingsMenu.append(shaderMenu); - shaderMenu.append(shaderNone); - shaderMenu.append(shaderBlur); - if(config->video.driver == "OpenGL") shaderMenu.append(shaderEmulation); - if(shaderList.size() > 0) { - shaderMenu.append(*new Separator); - for(auto& shader : shaderList) shaderMenu.append(*shader); - } - settingsMenu.append(*new Separator); - settingsMenu.append(synchronizeVideo); - settingsMenu.append(synchronizeAudio); - settingsMenu.append(muteAudio); - if(Intrinsics::platform() != Intrinsics::Platform::MacOSX) { - settingsMenu.append(*new Separator); - settingsMenu.append(configurationSettings); - } - append(toolsMenu); - toolsMenu.append(saveStateMenu); - for(unsigned n = 0; n < 5; n++) saveStateMenu.append(saveStateItem[n]); - toolsMenu.append(loadStateMenu); - for(unsigned n = 0; n < 5; n++) loadStateMenu.append(loadStateItem[n]); - toolsMenu.append(stateMenuSeparator); - toolsMenu.append(resizeWindow); - toolsMenu.append(stateManager); - toolsMenu.append(cheatEditor); - toolsMenu.append(synchronizeTime); - - append(layout); - layout.append(viewport, {0, 0, 1, 1}); - - onDrop = viewport.onDrop = [&](lstring paths) { - if(paths.size() && directory::exists(paths[0])) { - utility->loadMedia(paths[0]); - setFocused(); - } - }; - - onSize = [&] { - utility->resize(); - }; - - onClose = [&] { - setVisible(false); - if(Intrinsics::platform() == Intrinsics::Platform::MacOSX) { - utility->unload(); - } else { - Application::quit(); - } - }; - - shaderNone.onActivate = [&] { config->video.shader = "None"; utility->updateShader(); }; - shaderBlur.onActivate = [&] { config->video.shader = "Blur"; utility->updateShader(); }; - shaderEmulation.onActivate = [&] { config->video.shader = "Display Emulation"; utility->updateShader(); }; - centerVideo.onActivate = [&] { config->video.scaleMode = 0; utility->resize(); }; - scaleVideo.onActivate = [&] { config->video.scaleMode = 1; utility->resize(); }; - stretchVideo.onActivate = [&] { config->video.scaleMode = 2; utility->resize(); }; - aspectCorrection.onToggle = [&] { config->video.aspectCorrection = aspectCorrection.checked(); utility->resize(); }; - maskOverscan.onToggle = [&] { config->video.maskOverscan.enable = maskOverscan.checked(); }; - synchronizeVideo.onToggle = [&] { config->video.synchronize = synchronizeVideo.checked(); utility->synchronizeRuby(); }; - synchronizeAudio.onToggle = [&] { config->audio.synchronize = synchronizeAudio.checked(); utility->synchronizeRuby(); }; - muteAudio.onToggle = [&] { config->audio.mute = muteAudio.checked(); utility->synchronizeRuby(); }; - configurationSettings.onActivate = [&] { settings->setVisible(); }; - for(unsigned n = 0; n < 5; n++) saveStateItem[n].onActivate = [=] { utility->saveState(1 + n); }; - for(unsigned n = 0; n < 5; n++) loadStateItem[n].onActivate = [=] { utility->loadState(1 + n); }; - resizeWindow.onActivate = [&] { utility->resize(true); }; - stateManager.onActivate = [&] { tools->panels.setSelection(1); tools->setVisible(); }; - cheatEditor.onActivate = [&] { tools->panels.setSelection(0); tools->setVisible(); }; - synchronizeTime.onActivate = [&] { system().rtcsync(); }; - - synchronize(); -} - -void Presentation::bootstrap() { - for(auto& emulator : program->emulator) { - for(auto& media : emulator->media) { - if(media.bootable == false) continue; - Item* item = new Item; - item->setText({media.name, " ..."}); - item->onActivate = [=] { libraryManager->show(media.type); }; - loadBootableMedia.append(item); - } - } - - for(auto& emulator : program->emulator) { - auto iEmulator = new Emulator; - iEmulator->interface = emulator; - - iEmulator->menu.setText(emulator->information.name); - iEmulator->power.setText("Power"); - iEmulator->reset.setText("Reset"); - iEmulator->unload.setText("Unload"); - - for(auto& port : emulator->port) { - auto iPort = new Emulator::Port; - iPort->menu.setText(port.name); - iEmulator->port.append(iPort); - - for(auto& device : port.device) { - auto iDevice = new RadioItem; - iDevice->setText(device.name); - iDevice->onActivate = [=] { utility->connect(port.id, device.id); }; - iPort->group.append(*iDevice); - iPort->device.append(iDevice); - } - - RadioItem::group(iPort->group); - } - - iEmulator->menu.append(iEmulator->power); - if(emulator->information.resettable) - iEmulator->menu.append(iEmulator->reset); - iEmulator->menu.append(*new Separator); - unsigned visiblePorts = 0; - for(auto& iPort : iEmulator->port) { - iEmulator->menu.append(iPort->menu); - if(iPort->device.size() <= 1) iPort->menu.setVisible(false); - else visiblePorts++; - for(auto& iDevice : iPort->device) { - iPort->menu.append(*iDevice); - } - } - iEmulator->menu.append(iEmulator->controllerSeparator); - if(visiblePorts == 0) iEmulator->controllerSeparator.setVisible(false); - iEmulator->menu.append(iEmulator->unload); - - iEmulator->power.onActivate = {&Utility::power, utility}; - iEmulator->reset.onActivate = {&Utility::reset, utility}; - iEmulator->unload.onActivate = {&Utility::unload, utility}; - - emulatorList.append(iEmulator); - } -} - -void Presentation::loadShaders() { - //only the OpenGL driver has video shader support - if(config->video.driver == "OpenGL") { - string pathname = program->path("Video Shaders/"); - lstring shaders = directory::folders(pathname, "*.shader"); - for(auto& name : shaders) { - auto shader = new RadioItem; - shader->setText(name.split<1>(".shader/")(0)); - shader->onActivate = [=] { - config->video.shader = {pathname, name}; - utility->updateShader(); - }; - shaderList.append(shader); - } - } - - nall::group<RadioItem> group; - group.append(shaderNone); - group.append(shaderBlur); - group.append(shaderEmulation); - for(auto& shader : shaderList) group.append(*shader); - RadioItem::group(group); -} diff --git a/target-higan/general/presentation.hpp b/target-higan/general/presentation.hpp deleted file mode 100644 index 7bc83326..00000000 --- a/target-higan/general/presentation.hpp +++ /dev/null @@ -1,63 +0,0 @@ -struct Presentation : Window { - FixedLayout layout; - Viewport viewport; - - struct Emulator { - ::Emulator::Interface* interface; - - Menu menu; - Item power; - Item reset; - Item unload; - Separator controllerSeparator; - struct Port { - Menu menu; - nall::group<RadioItem> group; - vector<RadioItem*> device; - }; - vector<Port*> port; - function<void (string)> callback; - }; - vector<Emulator*> emulatorList; - Emulator* active = nullptr; - - Menu loadMenu; - vector<Item*> loadBootableMedia; - Menu settingsMenu; - Menu videoMenu; - RadioItem centerVideo; - RadioItem scaleVideo; - RadioItem stretchVideo; - CheckItem aspectCorrection; - CheckItem maskOverscan; - Menu shaderMenu; - RadioItem shaderNone; - RadioItem shaderBlur; - RadioItem shaderEmulation; - vector<RadioItem*> shaderList; - CheckItem synchronizeVideo; - CheckItem synchronizeAudio; - CheckItem muteAudio; - Item configurationSettings; - Menu toolsMenu; - Menu saveStateMenu; - Item saveStateItem[5]; - Menu loadStateMenu; - Item loadStateItem[5]; - Separator stateMenuSeparator; - Item resizeWindow; - Item stateManager; - Item cheatEditor; - Item synchronizeTime; - - void synchronize(); - void setSystemName(string name); - void loadShaders(); - void bootstrap(); - Presentation(); - -//internal: - string systemName; -}; - -extern Presentation* presentation; diff --git a/target-higan/higan.cpp b/target-higan/higan.cpp index 0d8fce73..ee967a88 100644 --- a/target-higan/higan.cpp +++ b/target-higan/higan.cpp @@ -1,164 +1,25 @@ #include "higan.hpp" -#include "bootstrap.cpp" -#include "resource/resource.cpp" -Program* program = nullptr; -DSP dspaudio; +struct Presentation : Window { + MenuBar menuBar{this}; + Menu menuSystem{&menuBar}; + StatusBar statusBar{this}; -Emulator::Interface& system() { - if(program->active == nullptr) throw; - return *program->active; -} + Presentation() { + menuSystem.setText("System"); + onClose(&Application::quit); -bool Program::focused() { - return config->input.focus.allow || presentation->focused(); -} - -string Program::path(string name) { - string path = {basepath, name}; - if(file::exists(path) || directory::exists(path)) return path; - path = {userpath, name}; - if(file::exists(path) || directory::exists(path)) return path; - path = {sharedpath, name}; - if(file::exists(path) || directory::exists(path)) return path; - return {userpath, name}; -} - -void Program::main() { - inputManager->poll(); - utility->updateStatus(); - autopause = config->input.focus.pause && presentation->focused() == false; - - if(active == nullptr || system().loaded() == false || pause || autopause) { - audio.clear(); - usleep(20 * 1000); - return; + setBackgroundColor({0, 0, 0}); + setTitle({Emulator::Name, " v", Emulator::Version}); + setSize({640, 480}); + setCentered(); + setVisible(); } +}; - system().run(); -} - -Program::Program(int argc, char** argv) { - ananke.open("ananke"); - - program = this; - pause = false; - autopause = false; - - basepath = nall::programpath(); - userpath = {nall::configpath(), "higan/"}; - sharedpath = {nall::sharedpath(), "higan/"}; - directory::create(userpath); - - bootstrap(); - active = nullptr; - - normalFont = Font::sans(8); - boldFont = Font::sans(8, "Bold"); - titleFont = Font::sans(16, "Bold"); - monospaceFont = Font::monospace(8); - - config = new ConfigurationSettings; - video.driver(config->video.driver); - audio.driver(config->audio.driver); - input.driver(config->input.driver); - - utility = new Utility; - inputManager = new InputManager; - windowManager = new WindowManager; - libraryManager = new LibraryManager; - presentation = new Presentation; - dipSwitches = new DipSwitches; - videoSettings = new VideoSettings; - audioSettings = new AudioSettings; - inputSettings = new InputSettings; - hotkeySettings = new HotkeySettings; - timingSettings = new TimingSettings; - serverSettings = new ServerSettings; - advancedSettings = new AdvancedSettings; - settings = new Settings; - cheatDatabase = new CheatDatabase; - cheatEditor = new CheatEditor; - stateManager = new StateManager; - tools = new Tools; - windowManager->loadGeometry(); - presentation->setVisible(); - utility->resize(); - - if(argc == 1 && config->library.showOnStartup) libraryManager->show(); - - video.set(Video::Handle, presentation->viewport.handle()); - if(!video.cap(Video::Depth) || !video.set(Video::Depth, depth = 30u)) { - video.set(Video::Depth, depth = 24u); - } - if(video.init() == false) { video.driver("None"); video.init(); } - - audio.set(Audio::Handle, presentation->viewport.handle()); - if(audio.init() == false) { audio.driver("None"); audio.init(); } - - input.set(Input::Handle, presentation->viewport.handle()); - if(input.init() == false) { input.driver("None"); input.init(); } - - dspaudio.setPrecision(16); - dspaudio.setBalance(0.0); - dspaudio.setFrequency(96000); - - utility->synchronizeRuby(); - utility->updateShader(); - - if(config->video.startFullScreen && argc >= 2) utility->toggleFullScreen(); - Application::processEvents(); - - if(argc >= 2) utility->loadMedia(argv[1]); - - Application::main = {&Program::main, this}; - Application::run(); - - utility->unload(); - config->save(); - inputManager->saveConfiguration(); - windowManager->saveGeometry(); - - ananke.close(); -} - -int main(int argc, char** argv) { - #if defined(PLATFORM_WINDOWS) - utf8_args(argc, argv); - #endif - +#include <nall/main.hpp> +auto nall::main(lstring args) -> void { Application::setName("higan"); - - Application::Windows::onModalBegin = [&] { - audio.clear(); - }; - - Application::Cocoa::onActivate = [&] { - presentation->setVisible(); - }; - - Application::Cocoa::onAbout = [&] { - MessageWindow() - .setTitle({"About ", Emulator::Name}) - .setText({ - Emulator::Name, " v", Emulator::Version, "\n", - Emulator::Profile, " Profile\n", - "Author: ", Emulator::Author, "\n", - "License: ", Emulator::License, "\n", - "Website: ", Emulator::Website - }) - .information(); - }; - - Application::Cocoa::onPreferences = [&] { - settings->setVisible(); - }; - - Application::Cocoa::onQuit = [&] { - Application::quit(); - }; - - new Program(argc, argv); - delete program; - return 0; + new Presentation; + Application::run(); } diff --git a/target-higan/higan.hpp b/target-higan/higan.hpp index b9b9a22d..97b63a1f 100644 --- a/target-higan/higan.hpp +++ b/target-higan/higan.hpp @@ -1,59 +1,8 @@ #include <emulator/emulator.hpp> -#include <nall/platform.hpp> -#include <nall/config.hpp> -#include <nall/directory.hpp> -#include <nall/dsp.hpp> -#include <nall/invoke.hpp> -#include <nall/map.hpp> -#include <nall/stream/file.hpp> -#include <nall/stream/memory.hpp> -#include <nall/stream/mmap.hpp> -#include <nall/stream/vector.hpp> -using namespace nall; - -#include <phoenix/phoenix.hpp> -using namespace phoenix; - +#include <nall/nall.hpp> #include <ruby/ruby.hpp> +#include <hiro/hiro.hpp> +using namespace nall; using namespace ruby; - -#include "configuration/configuration.hpp" -#include "interface/interface.hpp" -#include "utility/utility.hpp" -#include "input/input.hpp" -#include "window/window.hpp" -#include "general/general.hpp" -#include "settings/settings.hpp" -#include "tools/tools.hpp" -#include "resource/resource.hpp" - -Emulator::Interface& system(); - -struct Program { - vector<Emulator::Interface*> emulator; - Emulator::Interface* active = nullptr; - library ananke; - - bool pause; - bool autopause; - unsigned depth; //color depth; 24(bpp) or 30(bpp) - - string basepath; - string userpath; - string sharedpath; - - string normalFont; - string boldFont; - string titleFont; - string monospaceFont; - - bool focused(); - string path(string filename); - void main(); - void bootstrap(); - Program(int argc, char** argv); -}; - -extern Program* program; -extern DSP dspaudio; +using namespace hiro; diff --git a/target-higan/input/hotkeys.cpp b/target-higan/input/hotkeys.cpp deleted file mode 100644 index 0df72552..00000000 --- a/target-higan/input/hotkeys.cpp +++ /dev/null @@ -1,146 +0,0 @@ -void InputManager::appendHotkeys() { - { - auto hotkey = new HotkeyInput; - hotkey->name = "Toggle Fullscreen Mode"; - hotkey->mapping = "1/Button/F11"; - - hotkey->press = [] { - utility->toggleFullScreen(); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Toggle Mouse Capture"; - hotkey->mapping = "1/Button/F12"; - - hotkey->press = [] { - input.acquired() ? input.unacquire() : input.acquire(); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Show Library"; - hotkey->mapping = "1/Button/L"; - - hotkey->press = [] { - libraryManager->show(); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Pause Emulation"; - hotkey->mapping = "1/Button/P"; - - hotkey->press = [] { - program->pause = !program->pause; - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Fast Forward"; - hotkey->mapping = "1/Button/Tilde"; - - hotkey->press = [] { - video.set(Video::Synchronize, false); - audio.set(Audio::Synchronize, false); - }; - - hotkey->release = [] { - video.set(Video::Synchronize, ::config->video.synchronize); - audio.set(Audio::Synchronize, ::config->audio.synchronize); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Power Cycle"; - hotkey->mapping = "None"; - - hotkey->press = [] { - utility->power(); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Soft Reset"; - hotkey->mapping = "None"; - - hotkey->press = [] { - utility->reset(); - }; - } - - static unsigned activeSlot = 1; - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Save State"; - hotkey->mapping = "1/Button/F5"; - - hotkey->press = [&] { - utility->saveState(activeSlot); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Load State"; - hotkey->mapping = "1/Button/F7"; - - hotkey->press = [&] { - utility->loadState(activeSlot); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Decrement Slot"; - hotkey->mapping = "1/Button/F6"; - - hotkey->press = [&] { - if(--activeSlot == 0) activeSlot = 5; - utility->showMessage({"Selected slot ", activeSlot}); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Increment Slot"; - hotkey->mapping = "1/Button/F8"; - - hotkey->press = [&] { - if(++activeSlot == 6) activeSlot = 1; - utility->showMessage({"Selected slot ", activeSlot}); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Close Emulator"; - hotkey->mapping = "None"; - - hotkey->press = [] { - Application::quit(); - }; - } - - Configuration::Node node; - for(auto& hotkey : hotkeyMap) { - node.append(hotkey->mapping, string{hotkey->name}.replace(" ", "")); - } - config.append(node, "Hotkey"); -} - -void InputManager::pollHotkeys() { - for(auto& hotkey : hotkeyMap) { - bool state = hotkey->poll(); - if(hotkey->state == 0 && state == 1) if(hotkey->press) hotkey->press(); - if(hotkey->state == 1 && state == 0) if(hotkey->release) hotkey->release(); - hotkey->state = state; - } -} diff --git a/target-higan/input/input.cpp b/target-higan/input/input.cpp deleted file mode 100644 index bc0083c1..00000000 --- a/target-higan/input/input.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include "../higan.hpp" -#include "hotkeys.cpp" -InputManager* inputManager = nullptr; -HID::Null hidNull; - -void AbstractInput::bind() { - inputList.reset(); - lstring list = mapping.split(","); - - for(auto& mapping : list) { - lstring values = mapping.split("/"); - if(values.size() == 1) continue; //skip "None" mapping - - uint64_t id = hex(values[0]); - string group = values(1, ""); - string input = values(2, ""); - string qualifier = values(3, ""); - - Input item; - for(auto device : inputManager->devices) { - if(id != device->id) continue; - if(group == "Rumble") { - item.device = device; - item.id = id; - item.group = 0; - item.input = 0; - break; - } - if(auto groupID = device->find(group)) { - if(auto inputID = device->group[groupID()].find(input)) { - item.device = device; - item.id = id; - item.group = groupID(); - item.input = inputID(); - item.qualifier = Input::Qualifier::None; - if(qualifier == "Lo") item.qualifier = Input::Qualifier::Lo; - if(qualifier == "Hi") item.qualifier = Input::Qualifier::Hi; - break; - } - } - } - if(item.device == nullptr) continue; - - inputList.append(item); - } -} - -bool AbstractInput::append(string encode) { - lstring mappings = mapping.split(","); - if(mappings.find(encode)) return true; //mapping already bound - if(mapping.empty() || mapping == "None") mapping = encode; //remove "None" - else mapping.append(",", encode); //add to existing mapping list - bind(); - return true; -} - -// - -bool DigitalInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) { - inputList.reset(); - mapping = "None"; - return true; - } - - string encode = {hex(device.id), "/", device.group[group].name, "/", device.group[group].input[input].name}; - - if((device.isKeyboard() && group == HID::Keyboard::GroupID::Button) - || (device.isMouse() && group == HID::Mouse::GroupID::Button) - || (device.isJoypad() && group == HID::Joypad::GroupID::Button) - ) { - if(newValue != 0) return append(encode); - } - - if((device.isJoypad() && group == HID::Joypad::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Hat) - ) { - if(newValue < -16384) return append({encode, "/Lo"}); - if(newValue > +16384) return append({encode, "/Hi"}); - } - - return false; -} - -int16_t DigitalInput::poll() { - if(program->focused() == false) return 0; - if(inputList.size() == 0) return 0; - bool result = logic; - - for(auto& item : inputList) { - HID::Device& device = *(item.device); - int16_t value = device.group[item.group].input[item.input].value; - bool output = logic; - if((device.isKeyboard() && item.group == HID::Keyboard::GroupID::Button) - || (device.isMouse() && item.group == HID::Mouse::GroupID::Button) - || (device.isJoypad() && item.group == HID::Joypad::GroupID::Button) - ) { - output = value; - } - if((device.isJoypad() && item.group == HID::Joypad::GroupID::Axis) - || (device.isJoypad() && item.group == HID::Joypad::GroupID::Hat) - ) { - if(item.qualifier == Input::Qualifier::Lo) output = value < -16384; - if(item.qualifier == Input::Qualifier::Hi) output = value > +16384; - } - if(logic == 0) result |= output; - if(logic == 1) result &= output; - } - - return result; -} - -// - -bool RelativeInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) { - inputList.reset(); - mapping = "None"; - return true; - } - - string encode = {hex(device.id), "/", device.group[group].name, "/", device.group[group].input[input].name}; - - if((device.isMouse() && group == HID::Mouse::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Hat) - ) { - if(newValue < -16384) return append(encode); - if(newValue > +16384) return append(encode); - } - - return false; -} - -int16_t RelativeInput::poll() { - if(program->focused() == false) return 0; - if(inputList.size() == 0) return 0; - int16_t result = 0; - - for(auto& item : inputList) { - HID::Device& device = *(item.device); - int16_t value = device.group[item.group].input[item.input].value; - if(device.isJoypad() && item.group == HID::Joypad::GroupID::Axis) value >>= 8; - if(device.isJoypad() && item.group == HID::Joypad::GroupID::Hat) value = (value < 0 ? -1 : value > 0 ? + 1 : 0); - if(device.isMouse() && input.acquired() == false) value = 0; - result += value; - } - - return result; -} - -// - -bool RumbleInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) { - inputList.reset(); - mapping = "None"; - return true; - } - - string encode = {hex(device.id), "/Rumble"}; - - if(device.isJoypad() && group == HID::Joypad::GroupID::Button) { - if(newValue != 0) return append(encode); - } - - return false; -} - -void RumbleInput::rumble(bool enable) { - if(program->focused() == false) return; - if(inputList.size() == 0) return; - - for(auto& item : inputList) { - input.rumble(item.id, enable); - } -} - -// - -HotkeyInput::HotkeyInput() { - logic = 1; //AND - inputManager->hotkeyMap.append(this); -} - -// - -//convert an input mapping string to a more human-readable form for the UI -string InputManager::sanitize(string mapping, string concatenate) const { - lstring values = mapping.split(","); - for(auto& value : values) { - lstring part = value.split("/"); - if(part.size() < 2) continue; //skip "None" mapping - if(part[0] == "1") part[0] = "Keyboard"; - else if(part[0] == "2") part[0] = "Mouse"; - else part[0] = {"Joypad(", part[0].slice(0, 3), ")"}; - value = part.merge("."); - } - return values.merge(concatenate); -} - -void InputManager::onChange(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(settings->focused()) { - inputSettings->inputEvent(device, group, input, oldValue, newValue); - hotkeySettings->inputEvent(device, group, input, oldValue, newValue); - } -} - -HID::Device* InputManager::findMouse() { - for(auto device : devices) { - if(device->isMouse()) return device; - } - return nullptr; -} - -void InputManager::bind() { - for(auto& input : inputMap) input->bind(); - for(auto& input : hotkeyMap) input->bind(); -} - -void InputManager::poll() { - auto devices = input.poll(); - bool changed = devices.size() != this->devices.size(); - if(changed == false) { - for(unsigned n = 0; n < devices.size(); n++) { - changed = devices[n] != this->devices[n]; - if(changed) break; - } - } - if(changed == true) { - this->devices = devices; - bind(); - } - - if(presentation->focused()) pollHotkeys(); -} - -void InputManager::saveConfiguration() { - config.save(program->path("input.bml")); -} - -InputManager::InputManager() { - inputManager = this; - bootstrap(); - - input.onChange = {&InputManager::onChange, this}; -} - -void InputManager::bootstrap() { - unsigned guid = 0; - for(auto& emulator : program->emulator) { - Configuration::Node emulatorNode; - - for(auto& port : emulator->port) { - Configuration::Node portNode; - - for(auto& device : port.device) { - Configuration::Node deviceNode; - - for(auto& number : device.order) { - auto& input = device.input[number]; - - AbstractInput* abstract = nullptr; - if(input.type == 0) abstract = new DigitalInput; - if(input.type == 1) abstract = new RelativeInput; - if(input.type == 2) abstract = new RumbleInput; - if(abstract == nullptr) continue; - - abstract->name = string{input.name}.replace(" ", ""); - abstract->mapping = "None"; - abstract->logic = 0; //OR - - input.guid = guid++; - inputMap.append(abstract); - - deviceNode.append(abstract->mapping, abstract->name); - } - - portNode.append(deviceNode, string{device.name}.replace(" ", "")); - } - - emulatorNode.append(portNode, string{port.name}.replace(" ", "")); - } - - config.append(emulatorNode, string{emulator->information.name}.replace(" ", "")); - } - - appendHotkeys(); - - config.load(program->path("input.bml")); - config.save(program->path("input.bml")); - - bind(); -} diff --git a/target-higan/input/input.hpp b/target-higan/input/input.hpp deleted file mode 100644 index 7466b5a2..00000000 --- a/target-higan/input/input.hpp +++ /dev/null @@ -1,71 +0,0 @@ -extern HID::Null hidNull; - -struct AbstractInput { - string name; - string mapping; - bool logic = 0; //0 = OR, 1 = AND - bool state = 0; - - struct Input { - HID::Device* device = nullptr; - uint64_t id = 0; - unsigned group = 0; - unsigned input = 0; - enum class Qualifier : unsigned { None, Lo, Hi } qualifier; - }; - vector<Input> inputList; - - void bind(); - bool append(string mapping); - virtual bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { return false; } - virtual int16_t poll() { return 0; } - virtual void rumble(bool enable) {} -}; - -struct DigitalInput : AbstractInput { - using AbstractInput::bind; - bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - int16_t poll(); -}; - -struct RelativeInput : AbstractInput { - using AbstractInput::bind; - bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - int16_t poll(); -}; - -struct RumbleInput : AbstractInput { - using AbstractInput::bind; - bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - void rumble(bool enable); -}; - -struct HotkeyInput : DigitalInput { - function<void ()> press; - function<void ()> release; - HotkeyInput(); -}; - -struct InputManager { - vector<HID::Device*> devices; - vector<AbstractInput*> inputMap; - vector<HotkeyInput*> hotkeyMap; - - string sanitize(string mapping, string concatenate) const; - void onChange(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - HID::Device* findMouse(); - void bind(); - void poll(); - void saveConfiguration(); - void bootstrap(); - InputManager(); - - //hotkeys.cpp - void appendHotkeys(); - void pollHotkeys(); - -private: - Configuration::Document config; -}; - -extern InputManager* inputManager; diff --git a/target-higan/interface/interface.cpp b/target-higan/interface/interface.cpp deleted file mode 100644 index c48e7f96..00000000 --- a/target-higan/interface/interface.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "../higan.hpp" -Interface* interface = nullptr; - -void Interface::loadRequest(unsigned id, string name, string type) { - return utility->loadRequest(id, name, type); -} - -void Interface::loadRequest(unsigned id, string path) { - return utility->loadRequest(id, path); -} - -void Interface::saveRequest(unsigned id, string path) { - return utility->saveRequest(id, path); -} - -uint32_t Interface::videoColor(unsigned source, uint16_t a, uint16_t r, uint16_t g, uint16_t b) { - if(config->video.shader != "Display Emulation") { - if(config->video.saturation != 100) { - uint16_t grayscale = uclamp<16>((r + g + b) / 3); - double saturation = config->video.saturation * 0.01; - double inverse = max(0.0, 1.0 - saturation); - r = uclamp<16>(r * saturation + grayscale * inverse); - g = uclamp<16>(g * saturation + grayscale * inverse); - b = uclamp<16>(b * saturation + grayscale * inverse); - } - - if(config->video.gamma != 100) { - double exponent = config->video.gamma * 0.01; - double reciprocal = 1.0 / 32767.0; - r = r > 32767 ? r : 32767 * pow(r * reciprocal, exponent); - g = g > 32767 ? g : 32767 * pow(g * reciprocal, exponent); - b = b > 32767 ? b : 32767 * pow(b * reciprocal, exponent); - } - - if(config->video.luminance != 100) { - double luminance = config->video.luminance * 0.01; - r = r * luminance; - g = g * luminance; - b = b * luminance; - } - } - - if(program->depth == 30) { - a >>= 14, r >>= 6, g >>= 6, b >>= 6; - return a << 30 | r << 20 | g << 10 | b << 0; - } - - if(program->depth == 24) { - a >>= 8, r >>= 8, g >>= 8, b >>= 8; - return a << 24 | r << 16 | g << 8 | b << 0; - } - - return 0u; -} - -void Interface::videoRefresh(const uint32_t* palette, const uint32_t* data, unsigned pitch, unsigned width, unsigned height) { - uint32_t* output; - unsigned outputPitch; - - if(video.lock(output, outputPitch, width, height)) { - pitch >>= 2, outputPitch >>= 2; - - for(unsigned y = 0; y < height; y++) { - const uint32_t* sp = data + y * pitch; - uint32_t* dp = output + y * outputPitch; - for(unsigned x = 0; x < width; x++) { - *dp++ = palette[*sp++]; - } - } - - if(system().information.overscan && config->video.maskOverscan.enable) { - unsigned h = config->video.maskOverscan.horizontal; - unsigned v = config->video.maskOverscan.vertical; - - if(h) for(unsigned y = 0; y < height; y++) { - memset(output + y * outputPitch, 0, 4 * h); - memset(output + y * outputPitch + (width - h), 0, 4 * h); - } - - if(v) for(unsigned y = 0; y < v; y++) { - memset(output + y * outputPitch, 0, 4 * width); - memset(output + (height - 1 - y) * outputPitch, 0, 4 * width); - } - } - - video.unlock(); - video.refresh(); - } - - static unsigned frameCounter = 0; - static time_t previous, current; - frameCounter++; - - time(¤t); - if(current != previous) { - previous = current; - utility->setStatusText({"FPS: ", frameCounter}); - frameCounter = 0; - } -} - -void Interface::audioSample(int16_t lsample, int16_t rsample) { - signed samples[] = {lsample, rsample}; - dspaudio.sample(samples); - while(dspaudio.pending()) { - dspaudio.read(samples); - audio.sample(samples[0], samples[1]); - } -} - -int16_t Interface::inputPoll(unsigned port, unsigned device, unsigned input) { - unsigned guid = system().port[port].device[device].input[input].guid; - return inputManager->inputMap[guid]->poll(); -} - -void Interface::inputRumble(unsigned port, unsigned device, unsigned input, bool enable) { - unsigned guid = system().port[port].device[device].input[input].guid; - return inputManager->inputMap[guid]->rumble(enable); -} - -unsigned Interface::dipSettings(const Markup::Node& node) { - return dipSwitches->run(node); -} - -string Interface::path(unsigned group) { - return utility->path(group); -} - -string Interface::server() { - return { - config->server.username, ":", - config->server.password, "@", - config->server.hostname - }; -} - -void Interface::notify(string text) { - MessageWindow().setParent(*presentation).setText(text).information(); -} diff --git a/target-higan/interface/interface.hpp b/target-higan/interface/interface.hpp deleted file mode 100644 index 485c831f..00000000 --- a/target-higan/interface/interface.hpp +++ /dev/null @@ -1,16 +0,0 @@ -struct Interface : Emulator::Interface::Bind { - void loadRequest(unsigned id, string name, string type); - void loadRequest(unsigned id, string path); - void saveRequest(unsigned id, string path); - uint32_t videoColor(unsigned source, uint16_t alpha, uint16_t red, uint16_t green, uint16_t blue); - void videoRefresh(const uint32_t* palette, const uint32_t* data, unsigned pitch, unsigned width, unsigned height); - void audioSample(int16_t lsample, int16_t rsample); - int16_t inputPoll(unsigned port, unsigned device, unsigned input); - void inputRumble(unsigned port, unsigned device, unsigned input, bool enable); - unsigned dipSettings(const Markup::Node& node); - string path(unsigned group); - string server(); - void notify(string text); -}; - -extern Interface* interface; diff --git a/target-higan/resource.rc b/target-higan/resource.rc deleted file mode 100644 index 49441758..00000000 --- a/target-higan/resource.rc +++ /dev/null @@ -1,2 +0,0 @@ -1 24 "../data/higan.Manifest" -2 ICON DISCARDABLE "../data/higan.ico" diff --git a/target-higan/resource/cheat-editor.png b/target-higan/resource/cheat-editor.png deleted file mode 100644 index c8d899cf..00000000 Binary files a/target-higan/resource/cheat-editor.png and /dev/null differ diff --git a/target-higan/resource/folder.png b/target-higan/resource/folder.png deleted file mode 100644 index 472484f1..00000000 Binary files a/target-higan/resource/folder.png and /dev/null differ diff --git a/target-higan/resource/game.png b/target-higan/resource/game.png deleted file mode 100644 index 1990dbb8..00000000 Binary files a/target-higan/resource/game.png and /dev/null differ diff --git a/target-higan/resource/resource.bml b/target-higan/resource/resource.bml deleted file mode 100644 index e9a78611..00000000 --- a/target-higan/resource/resource.bml +++ /dev/null @@ -1,15 +0,0 @@ -resource name=resource - binary id=advanced name=advanced.png - binary id=audio name=audio.png - binary id=cheatEditor name=cheat-editor.png - binary id=folder name=folder.png - binary id=game name=game.png - binary id=home name=home.png - binary id=hotkeys name=hotkeys.png - binary id=input name=input.png - binary id=server name=server.png - binary id=stateManager name=state-manager.png - binary id=timing name=timing.png - binary id=unverified name=unverified.png - binary id=up name=up.png - binary id=video name=video.png diff --git a/target-higan/resource/resource.cpp b/target-higan/resource/resource.cpp deleted file mode 100644 index 1f84fc61..00000000 --- a/target-higan/resource/resource.cpp +++ /dev/null @@ -1,411 +0,0 @@ -namespace resource { - -const uint8_t advanced[611] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, - 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,9,26,12,19,57,139,99,194,72,0,0,1,240,73, - 68,65,84,56,203,165,146,75,104,19,97,20,133,191,153,248,76,138,77,20,10,130,74,176,204,198,133,182,221,69,172,46, - 52,20,98,102,235,66,112,33,84,164,168,181,45,18,82,2,21,3,67,66,160,107,65,116,101,64,138,226,194,137,141,208, - 98,87,130,210,54,137,73,23,21,130,85,105,211,151,134,32,68,68,58,51,110,102,134,49,29,235,194,179,251,185,231,156, - 123,239,185,63,252,39,4,231,35,157,81,162,128,10,200,241,88,34,247,23,77,52,157,81,108,142,216,82,84,251,175,246, - 3,168,166,153,171,248,250,181,1,205,108,180,29,233,140,98,52,26,117,35,157,81,12,247,90,195,170,69,1,196,116,70, - 137,90,100,171,171,215,219,230,102,28,5,120,240,240,62,241,88,66,6,114,0,34,160,14,222,28,50,158,62,155,48,0, - 245,246,173,17,54,215,215,144,58,37,234,245,175,247,90,179,137,221,25,21,44,49,128,96,21,111,12,12,26,154,182,37, - 232,186,110,232,186,70,97,126,78,40,188,47,2,200,59,5,43,180,116,176,17,233,187,72,185,82,97,185,246,5,32,25, - 143,37,238,254,243,140,78,188,202,191,52,74,149,18,221,39,123,40,150,11,152,19,76,2,186,171,65,48,146,58,12,212, - 172,247,149,144,78,215,9,137,163,71,142,209,108,54,121,55,247,22,183,53,60,78,241,248,112,152,190,80,39,29,1,47, - 217,153,77,142,183,127,75,46,125,94,58,215,125,170,135,128,63,192,74,109,249,242,133,240,249,249,233,169,215,85,192,0, - 16,131,145,84,23,80,123,52,38,51,91,94,100,182,188,72,199,65,31,0,230,222,114,46,255,2,73,146,56,123,186,215, - 250,100,118,30,34,80,28,31,14,51,245,166,196,150,166,35,238,243,179,81,111,218,35,154,35,203,217,39,143,57,208,238, - 231,76,168,23,96,204,105,0,192,238,93,30,246,248,14,241,243,199,47,178,249,5,128,112,171,73,46,175,82,253,88,253, - 35,108,17,96,101,227,59,251,125,1,218,246,122,120,62,243,1,32,252,105,114,116,218,73,52,77,146,107,235,171,11,64, - 210,190,66,48,146,186,4,76,56,184,219,196,59,225,55,55,226,213,246,234,188,84,188,0,0,0,0,73,69,78,68,174, - 66,96,130, -}; - -const uint8_t audio[592] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, - 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,1,226,73,68,65,84,56,141, - 165,147,191,79,83,81,20,199,63,231,246,245,165,68,168,3,193,201,63,64,99,66,4,139,128,113,100,241,71,88,40,88, - 162,46,36,242,106,58,233,0,127,132,49,93,173,12,13,137,160,169,105,2,196,133,196,168,131,131,137,16,23,69,172,147, - 58,176,184,152,247,76,244,93,222,61,14,198,218,22,140,65,191,227,57,159,156,123,190,223,123,175,168,42,255,35,243,167, - 70,126,58,159,11,130,32,253,79,3,10,133,137,193,20,242,56,142,227,212,129,7,20,10,19,131,105,63,243,84,85,179, - 173,245,161,224,94,112,122,118,121,172,147,247,46,77,79,134,64,198,243,188,175,168,222,73,251,153,235,51,51,51,217,202, - 221,74,210,10,58,167,239,141,104,53,23,60,236,223,168,76,126,105,110,32,72,166,124,187,236,205,207,205,31,86,152,43, - 149,74,217,209,145,51,120,158,7,64,110,118,169,56,114,109,233,232,230,194,213,39,10,235,104,124,179,205,130,162,244,245, - 29,225,248,177,19,168,170,12,156,60,69,38,211,133,136,0,32,66,111,34,148,1,68,101,69,144,209,61,25,188,217,122, - 205,187,198,91,0,26,141,109,182,183,183,176,214,2,144,114,44,2,99,34,136,26,247,10,116,72,4,105,102,0,16,134, - 97,115,101,187,107,81,126,191,141,93,163,137,168,164,0,172,209,196,79,164,45,120,3,16,70,33,97,20,162,170,216,216, - 98,99,219,4,4,83,64,244,153,42,234,37,169,1,96,83,91,78,48,0,81,20,177,179,179,3,192,135,79,31,137,109, - 220,26,191,167,164,111,252,132,245,130,194,139,182,107,84,85,173,215,235,137,136,88,35,102,113,117,117,229,242,248,197,241, - 238,95,192,203,133,43,183,0,134,139,247,71,129,60,98,250,59,45,244,168,106,183,115,174,123,121,233,65,209,126,79,206, - 173,61,90,139,156,115,109,94,93,226,134,65,139,27,149,233,207,173,117,217,239,51,77,77,77,157,197,184,245,67,93,61, - 189,213,106,245,219,30,160,51,196,78,213,106,181,231,56,115,222,247,253,100,191,254,95,55,56,136,126,0,228,148,200,42, - 201,231,90,24,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t cheatEditor[937] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0, - 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,28,23,56,34,56,174,182,224,0,0,3,54,73, - 68,65,84,56,203,93,147,75,76,92,117,20,198,191,255,99,230,222,121,128,115,65,96,102,128,162,19,4,154,73,83,19, - 23,197,87,221,24,74,210,141,169,85,27,31,171,54,193,84,107,213,210,102,72,67,26,98,162,13,148,88,155,52,172,76, - 136,143,133,27,92,17,18,187,168,166,52,93,24,181,117,12,29,168,52,242,152,41,101,24,198,14,51,112,231,206,253,255, - 143,27,192,73,191,213,57,223,201,247,203,73,78,14,195,182,70,70,47,246,2,248,206,52,205,135,167,62,248,56,142,42, - 141,140,94,28,147,82,190,245,201,233,254,186,106,127,122,28,239,241,157,70,8,49,241,225,201,211,150,109,219,139,87,199, - 174,12,238,248,151,191,26,205,28,234,233,237,3,112,231,177,240,203,0,190,222,5,40,165,204,123,243,179,252,196,241,190, - 30,165,212,126,0,24,190,244,197,43,209,230,104,164,88,218,96,90,235,238,170,112,59,227,98,146,49,225,217,5,112,206, - 75,11,11,255,192,52,12,86,46,151,227,87,199,174,12,74,41,175,197,98,49,172,60,88,209,90,235,249,237,176,197,133, - 184,222,209,253,105,80,120,106,84,245,6,61,169,84,10,203,233,37,118,226,120,95,167,109,219,239,119,117,117,121,24,56, - 230,239,207,3,192,15,211,227,240,112,33,166,90,227,71,155,234,90,14,49,0,216,5,156,235,31,184,197,57,95,156,155, - 155,133,105,152,204,10,89,81,210,64,118,109,85,3,152,60,123,38,241,25,23,98,188,190,249,192,254,104,199,155,30,80, - 9,68,244,63,0,0,180,214,71,102,238,206,208,234,234,10,92,229,98,99,163,128,100,50,233,0,24,186,249,13,63,239, - 15,181,189,22,123,238,148,233,22,39,161,221,13,0,143,1,206,158,73,252,198,57,255,118,118,46,165,67,161,16,50,15, - 50,68,68,227,207,215,39,158,242,120,107,207,119,118,15,248,221,210,52,42,91,139,208,202,6,136,192,170,1,19,225,240, - 168,75,116,210,205,231,77,184,46,158,14,55,33,77,122,51,120,208,246,190,112,105,64,74,190,134,98,238,6,12,211,132, - 55,244,6,110,255,148,80,2,0,38,34,145,193,35,149,202,245,78,203,234,14,9,33,149,114,169,236,58,168,11,212,176, - 70,211,240,24,203,38,255,117,120,10,158,198,28,178,91,119,17,106,108,2,247,182,99,245,254,207,196,127,140,70,223,117, - 114,185,161,206,112,88,207,44,45,93,43,108,109,58,249,194,6,247,29,214,45,66,50,252,107,151,80,136,153,104,111,168, - 71,50,49,135,252,148,68,197,113,160,221,50,8,4,238,58,206,240,190,214,86,74,45,47,95,56,166,84,111,173,233,83, - 194,231,83,141,175,243,239,255,206,172,32,24,12,32,254,101,3,242,47,173,185,123,163,17,42,222,240,66,85,42,112,221, - 77,128,8,28,229,114,189,227,56,234,152,82,159,79,6,2,151,61,82,154,194,66,193,111,181,31,8,61,187,7,126,146, - 184,55,244,23,204,87,183,36,24,49,93,208,112,29,7,170,178,9,128,32,225,245,102,130,126,255,158,219,109,109,101,173, - 181,156,89,75,23,155,47,60,225,111,217,123,212,8,156,251,5,201,143,254,64,199,157,48,42,191,215,64,107,130,172,149, - 80,218,221,6,0,226,109,203,202,165,215,215,95,92,119,28,153,103,196,194,253,90,60,115,248,29,131,115,15,140,134,39, - 97,68,235,144,94,200,34,155,45,224,145,87,33,62,114,16,190,72,12,68,12,143,30,254,73,172,234,65,246,1,184,197, - 152,52,133,244,59,0,1,68,219,83,218,61,53,237,212,68,80,202,246,253,7,17,166,115,66,199,238,239,170,0,0,0, - 0,73,69,78,68,174,66,96,130, -}; - -const uint8_t folder[1176] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122, - 244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, - 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, - 97,112,101,46,111,114,103,155,238,60,26,0,0,4,21,73,68,65,84,88,133,237,151,61,111,28,69,24,199,127,51,187, - 119,123,175,246,57,145,48,9,5,86,148,194,31,0,9,5,33,83,110,149,130,26,137,2,90,58,62,64,36,62,64,74, - 132,68,133,104,161,67,72,167,64,23,201,138,2,138,210,69,194,198,196,40,22,198,247,186,119,222,151,153,157,25,138,123, - 201,58,119,142,19,114,82,40,248,75,143,118,118,118,247,121,126,243,60,51,179,187,34,12,67,94,167,228,107,141,254,95, - 0,240,1,110,220,184,225,43,165,126,54,198,188,119,209,3,66,136,220,90,251,249,195,135,15,191,92,25,64,154,166,91, - 149,74,229,157,155,55,111,250,73,146,224,156,3,192,90,11,48,63,159,182,253,59,119,238,220,222,222,222,254,254,209,163, - 71,199,43,1,80,74,101,213,106,213,29,29,29,209,233,116,112,206,45,53,0,33,4,155,155,155,249,193,193,193,71,192, - 237,149,0,104,173,211,44,203,196,165,75,27,24,99,176,214,158,9,92,204,132,16,130,106,181,90,63,60,60,252,98,123, - 123,251,214,172,127,153,156,115,218,90,251,241,222,222,222,143,207,5,0,178,44,203,188,78,167,75,167,211,153,3,204,142, - 179,32,197,64,91,91,91,245,70,163,65,179,217,68,8,129,16,2,0,41,229,188,29,69,17,247,238,221,187,5,60,31, - 224,242,229,203,105,191,223,247,54,54,90,104,173,23,0,150,149,98,166,56,142,1,230,16,69,139,227,24,99,76,237,188, - 224,115,128,221,221,93,117,237,218,53,217,235,245,230,25,0,150,130,204,178,81,212,108,196,197,224,82,202,25,64,229,66, - 0,0,99,140,109,54,215,100,154,102,220,63,180,220,221,63,27,228,188,58,63,171,25,204,228,153,22,206,93,185,206,219, - 31,232,226,61,158,39,190,93,255,253,155,79,206,0,56,231,116,183,219,245,187,221,46,143,59,13,62,253,240,93,174,191, - 181,81,112,54,61,62,47,250,18,200,105,207,60,206,147,206,152,175,190,187,255,254,236,188,152,1,221,104,212,171,90,107, - 212,31,146,102,181,204,254,223,99,162,56,159,140,108,233,104,207,35,17,11,77,1,52,42,62,42,211,8,65,103,118,121, - 190,21,27,99,116,191,63,160,219,237,18,103,150,122,181,132,53,147,27,228,212,193,179,134,59,207,220,83,179,19,179,214, - 145,100,134,52,203,193,137,249,6,86,44,65,86,169,4,180,90,45,50,35,168,5,37,172,83,120,114,53,175,139,113,154, - 83,111,250,140,134,57,214,186,39,11,0,121,158,171,40,26,209,239,15,208,230,13,170,129,143,115,14,79,158,155,231,23, - 147,131,81,170,209,185,37,240,37,113,170,173,49,249,209,2,128,49,38,43,151,75,84,155,27,172,213,202,56,64,10,177, - 188,248,47,40,227,28,163,84,147,91,135,231,9,130,178,199,105,146,41,33,196,201,2,128,181,54,27,141,198,28,15,20, - 235,245,75,232,220,190,210,232,51,109,137,51,3,78,224,79,253,148,61,201,232,84,229,130,167,147,176,152,129,212,247,125, - 188,32,160,73,153,76,217,11,131,76,230,152,195,186,201,62,97,236,196,84,110,151,173,72,156,131,193,40,181,185,115,139, - 0,214,218,100,60,30,211,25,248,84,90,101,162,68,147,233,233,75,8,200,141,69,27,135,206,45,185,153,110,203,47,153, - 149,68,25,134,227,196,19,210,91,90,130,84,8,129,12,26,148,74,62,163,68,19,37,154,84,25,148,182,47,29,108,153, - 226,44,231,52,209,62,231,148,32,142,227,83,122,81,133,74,13,30,159,196,12,99,189,212,209,191,145,0,134,177,66,25, - 83,250,245,234,94,47,124,252,12,128,181,54,6,129,245,107,100,185,37,138,53,74,95,60,15,94,84,82,10,78,134,9, - 82,200,56,220,221,157,59,62,51,7,146,36,33,74,12,87,175,4,84,3,143,160,188,186,111,86,41,4,105,170,144,82, - 12,139,253,197,18,36,0,154,18,235,85,143,122,105,21,85,127,42,231,28,253,36,65,88,59,88,0,104,183,219,98,103, - 103,199,68,177,98,112,234,248,243,100,136,236,190,226,14,184,68,199,199,67,155,36,195,7,187,237,118,45,12,195,120,14, - 0,120,81,20,253,244,203,161,248,76,173,227,255,182,255,202,31,187,103,228,192,2,88,157,30,28,63,248,225,235,226,53, - 49,251,53,107,183,219,205,96,109,237,205,90,208,218,116,56,41,133,92,201,18,200,141,49,42,75,107,185,16,121,62,58, - 233,1,127,133,97,216,91,0,152,66,72,32,96,146,153,124,21,0,83,5,64,10,168,48,12,207,44,45,241,255,207,233, - 235,6,248,7,188,50,165,151,203,8,55,43,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t game[1490] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122, - 244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,5,137,73,68,65,84,88,133,237,150,91,108,20, - 231,21,199,127,231,155,155,151,181,124,89,3,181,113,193,183,13,16,81,82,21,225,52,50,1,132,91,53,20,212,132,155, - 212,84,149,18,161,40,82,213,151,72,68,81,108,212,74,121,168,122,81,165,190,24,171,125,141,218,226,66,171,66,91,37, - 65,145,82,225,2,9,6,148,132,40,73,9,55,219,4,112,146,58,49,23,239,125,102,190,62,204,236,120,236,176,182,1, - 169,79,29,233,232,236,203,156,255,239,252,207,249,190,29,248,255,115,31,79,182,135,157,153,94,116,102,47,91,239,181,134, - 186,31,113,173,216,159,173,249,10,90,243,215,76,47,91,254,103,0,217,30,118,106,225,143,183,219,215,219,250,225,103,201, - 180,173,179,53,28,186,23,136,187,6,8,58,151,253,147,233,13,142,151,106,97,226,76,63,238,194,54,50,237,143,222,19, - 132,220,173,56,134,57,144,95,243,3,43,111,8,147,31,253,3,180,7,98,80,189,226,123,152,159,95,102,193,197,227,69, - 129,237,201,95,240,234,124,106,206,219,129,108,47,59,48,204,1,111,211,139,150,145,254,22,217,11,175,160,68,163,148,66, - 137,38,123,225,21,252,133,105,114,233,245,129,19,123,249,238,124,234,206,203,129,108,47,59,180,48,224,111,124,193,150,150, - 46,138,19,23,64,107,4,184,253,225,1,220,155,163,160,65,139,34,153,222,140,57,62,76,213,197,227,69,17,182,37,127, - 206,107,179,213,158,211,129,64,92,6,178,15,108,180,189,134,86,74,19,23,17,64,68,16,17,204,68,93,224,130,161,80, - 2,185,203,175,227,54,180,145,79,175,179,181,230,240,92,78,204,234,64,36,158,126,212,246,83,203,64,187,56,141,107,65, - 160,52,126,142,252,245,147,248,185,207,167,94,208,58,72,8,137,214,110,140,241,17,170,46,189,57,171,19,21,29,200,246, - 176,93,139,12,228,210,235,108,63,245,85,242,163,255,68,187,249,168,115,63,51,6,133,137,160,251,40,12,68,41,148,8, - 249,43,71,241,26,150,145,111,127,196,22,164,226,78,220,17,32,219,195,118,95,228,79,217,116,151,237,213,53,147,191,50, - 136,8,129,128,8,34,10,17,65,41,99,70,168,169,12,20,174,30,195,91,216,66,182,173,211,169,4,241,37,128,178,120, - 174,227,17,219,175,91,66,225,234,49,20,160,68,161,172,5,80,158,125,205,82,204,228,226,105,226,18,101,21,65,20,175, - 158,192,75,45,37,219,182,214,17,228,208,100,15,155,43,2,100,122,217,22,136,63,108,251,117,77,20,174,190,137,8,72, - 185,168,83,27,117,111,47,92,73,242,107,79,97,47,94,61,189,243,16,72,194,113,136,64,113,108,8,175,174,153,108,235, - 26,71,41,57,28,135,136,0,244,75,40,224,80,177,190,209,102,201,215,41,140,157,14,108,151,169,249,154,53,205,136,72, - 232,66,0,34,165,201,169,217,71,89,97,88,85,88,245,29,40,195,10,156,248,236,29,212,3,143,81,168,89,236,136,76, - 45,100,4,32,47,225,227,179,205,158,248,164,40,215,222,193,105,90,19,21,20,81,24,201,69,40,59,137,136,160,115,227, - 228,222,221,71,238,221,126,252,204,245,72,220,176,18,209,8,140,154,165,44,88,190,29,179,182,5,49,76,18,45,221,56, - 185,12,206,237,255,20,181,158,218,133,105,35,72,254,138,191,9,250,251,137,225,51,69,243,198,117,236,198,111,32,202,68, - 148,194,94,180,122,234,4,220,188,140,200,116,203,205,234,38,18,15,61,131,149,90,142,89,221,136,149,90,142,8,36,58, - 182,80,219,245,83,18,84,33,39,250,139,190,231,63,81,253,75,142,68,141,223,233,20,100,122,217,134,200,129,98,251,90, - 219,79,53,225,223,184,68,98,245,110,148,225,128,8,197,243,127,70,231,198,131,113,68,173,88,56,171,118,163,37,236,73, - 107,52,160,18,13,232,145,33,244,241,254,146,246,220,199,227,226,21,1,166,65,164,59,109,107,197,86,84,162,1,9,174, - 64,40,78,226,126,252,6,160,49,106,59,240,198,223,195,88,210,133,170,237,8,133,53,104,144,170,122,244,232,16,254,177, - 59,139,207,10,80,134,208,168,131,170,251,121,75,45,93,131,206,127,17,118,45,248,55,47,66,225,38,102,227,90,180,214, - 81,169,224,183,6,39,20,255,215,190,138,226,115,2,64,120,47,24,230,65,99,211,30,83,39,171,241,174,31,199,168,107, - 71,223,56,15,94,1,107,229,15,65,153,83,215,176,214,96,215,161,71,79,226,205,33,62,47,128,50,132,54,140,3,254, - 242,78,75,234,27,17,237,66,241,22,214,146,46,164,174,131,80,25,173,65,236,26,252,209,33,188,193,190,146,214,238,19, - 115,253,27,206,247,131,196,248,108,15,59,146,85,242,7,86,126,211,182,59,127,140,246,242,168,240,78,40,3,96,85,227, - 141,156,194,27,236,43,77,228,220,93,205,191,225,53,192,3,252,138,133,103,17,85,128,13,84,1,206,175,223,98,244,201, - 85,92,72,101,174,109,241,201,24,102,115,39,248,110,112,52,145,72,188,52,216,231,190,255,169,251,244,131,253,28,5,204, - 80,163,124,220,191,4,82,9,192,2,156,153,241,219,51,92,249,118,27,151,155,115,195,223,145,69,29,134,170,95,134,248, - 46,88,73,252,145,33,74,131,125,238,209,97,247,71,221,47,115,44,38,94,6,80,4,142,135,91,90,25,192,8,1,236, - 88,68,16,47,159,229,90,103,147,30,110,187,117,170,91,26,90,149,212,183,226,143,156,164,56,216,231,30,254,183,187,103, - 215,65,222,10,197,227,162,241,81,107,130,177,204,10,96,134,16,102,8,80,6,114,0,231,192,7,140,173,72,249,87,86, - 76,158,218,160,111,127,170,74,111,255,197,251,253,89,247,39,207,252,157,211,49,209,184,160,31,134,23,203,21,1,252,24, - 189,17,203,101,48,3,176,14,159,99,172,165,198,191,182,218,26,89,255,187,51,254,207,158,59,194,233,25,66,238,140,40, - 197,34,26,193,108,167,160,188,7,118,44,199,195,138,1,150,187,44,11,20,103,68,33,150,167,45,226,124,142,97,121,28, - 54,211,71,83,22,143,47,150,23,235,62,14,51,173,235,187,5,184,211,59,113,241,114,141,153,179,158,215,243,95,119,198, - 63,107,9,247,71,127,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t home[606] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, - 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,10,14,20,37,19,83,42,210,59,0,0,1,235,73, - 68,65,84,56,203,149,147,191,107,83,81,20,128,191,123,251,222,75,211,64,242,36,160,85,135,100,81,123,19,104,85,172, - 17,92,28,140,66,19,167,135,212,74,39,145,162,163,24,92,58,180,110,193,169,254,24,234,212,37,139,245,199,96,19,240, - 15,240,63,16,121,91,92,196,90,219,240,98,81,137,33,121,215,33,246,217,151,80,33,103,186,92,206,247,221,115,14,231, - 194,1,225,41,85,172,128,174,128,246,148,122,200,48,177,7,123,74,105,79,169,61,73,113,104,120,177,56,163,203,55,111, - 252,87,34,250,225,154,235,110,20,148,98,253,220,89,182,39,78,113,228,240,56,39,188,38,83,107,107,212,92,151,130,82, - 215,14,185,110,117,64,176,31,126,83,156,97,247,248,49,148,202,50,22,141,210,106,181,24,219,252,74,182,92,30,144,136, - 126,184,122,251,22,157,100,146,116,42,77,42,149,2,64,107,104,183,219,236,214,235,156,44,149,66,18,177,31,126,247,160, - 68,199,48,201,229,46,96,219,118,208,154,214,26,0,223,247,249,185,181,69,114,110,46,144,136,10,232,130,82,188,127,84, - 198,107,54,57,63,157,35,30,143,35,132,8,9,124,223,15,206,134,16,140,230,243,212,92,23,3,184,3,172,78,157,62, - 195,253,210,61,54,170,111,3,240,201,202,51,86,30,63,69,139,17,116,167,133,48,70,209,221,223,44,47,45,209,238,165, - 204,202,121,120,190,48,153,33,17,79,0,160,212,4,153,140,34,155,205,244,94,20,146,145,244,149,222,196,83,121,144,22, - 90,107,22,38,51,204,195,186,236,239,211,178,44,76,211,196,48,140,224,254,75,227,7,0,31,234,59,116,187,126,144,11, - 48,32,144,82,34,165,196,146,159,1,232,96,241,241,83,3,128,111,222,47,58,34,18,90,36,99,96,179,254,14,207,231, - 40,0,151,46,78,115,53,26,67,234,113,46,75,147,237,77,66,21,24,253,21,252,155,126,239,165,239,222,14,162,217,56, - 112,245,3,65,36,18,193,182,109,18,137,4,2,137,16,16,139,197,112,28,103,0,178,44,43,252,23,174,207,58,175,0, - 135,225,98,245,229,139,215,119,255,0,86,248,213,163,133,187,128,26,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t hotkeys[587] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, - 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, - 97,112,101,46,111,114,103,155,238,60,26,0,0,1,200,73,68,65,84,56,141,181,146,177,107,83,81,20,198,127,247,222, - 115,95,95,8,73,159,136,180,209,38,177,21,7,165,21,26,16,204,228,34,102,8,8,34,212,168,127,72,193,191,160,131, - 45,174,29,178,184,180,116,17,212,12,25,4,23,137,32,168,56,85,227,146,162,85,112,145,212,190,151,52,125,185,14,109, - 53,29,164,193,226,7,151,115,46,231,124,223,189,231,240,169,82,169,196,113,160,15,146,122,189,174,142,37,48,191,48,159, - 30,134,80,169,84,252,193,187,58,24,161,88,156,157,242,60,223,3,239,187,136,216,100,210,88,99,196,199,152,139,190,245, - 175,2,87,28,76,3,30,74,189,72,38,82,229,106,181,26,203,31,45,127,195,57,123,201,250,186,108,69,143,59,103,50, - 32,99,86,108,216,239,179,174,148,187,15,242,174,213,106,253,204,159,157,104,110,111,255,40,0,175,127,11,52,26,141,93, - 224,205,254,249,219,247,131,252,228,196,50,142,157,173,173,206,251,67,59,56,10,115,119,230,174,163,226,183,202,169,200,104, - 175,80,171,213,186,0,114,20,113,239,229,91,151,193,61,82,112,111,101,101,237,249,96,77,45,173,45,37,78,118,131,166, - 159,24,57,163,181,70,27,141,86,123,209,104,131,214,10,173,13,206,57,0,246,123,94,61,88,120,88,4,144,157,86,120, - 45,83,184,112,106,102,122,6,107,61,68,4,43,22,99,4,173,13,56,71,223,245,137,162,136,48,10,49,90,211,104,188, - 156,173,84,110,158,95,93,125,220,20,17,239,118,144,62,225,133,97,135,205,175,159,72,37,211,160,0,20,74,41,218,237, - 54,249,92,142,56,142,249,178,249,153,108,54,79,106,52,144,245,15,31,111,0,139,98,180,46,7,65,0,206,145,61,157, - 99,183,31,31,154,127,52,157,166,215,235,1,138,169,201,115,116,186,93,50,99,227,102,196,179,119,129,69,137,227,120,227, - 233,179,39,90,169,225,157,236,156,3,199,55,24,112,226,191,98,104,31,252,55,129,95,252,113,137,228,164,151,154,151,0, - 0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t input[812] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,172,0,77,0,0,52,214,215,123,0,0,0,9,112,72,89,115,0,0,11,19,0, - 0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,4,7,15,10,39,178,201,163,153,0,0,0,140,116, - 69,88,116,67,111,109,109,101,110,116,0,77,101,110,117,45,115,105,122,101,100,32,105,99,111,110,10,61,61,61,61,61, - 61,61,61,61,61,10,10,40,99,41,32,50,48,48,51,32,74,97,107,117,98,32,39,106,105,109,109,97,99,39,32,83, - 116,101,105,110,101,114,44,32,10,104,116,116,112,58,47,47,106,105,109,109,97,99,46,109,117,115,105,99,104,97,108,108, - 46,99,122,10,10,99,114,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,71,73,77,80,44,10,104,116,116,112, - 58,47,47,119,119,119,46,103,105,109,112,46,111,114,103,103,138,199,71,0,0,2,33,73,68,65,84,56,203,149,146,203, - 107,83,65,20,198,127,147,220,228,38,214,210,164,177,54,245,209,135,160,184,73,176,20,255,130,130,123,17,138,136,130,168, - 32,88,8,193,133,173,15,180,221,136,46,68,10,10,130,72,22,93,213,186,19,68,208,133,187,34,84,179,19,68,20,42, - 21,53,53,183,105,244,230,117,111,230,184,184,105,154,66,178,232,129,3,195,240,205,55,191,249,230,40,58,212,199,179,132, - 255,170,221,51,97,41,95,2,124,235,42,178,96,80,191,58,62,95,40,181,234,84,167,195,117,124,223,250,14,237,141,27, - 225,16,162,53,142,93,102,237,251,186,181,161,122,6,79,204,231,237,77,173,175,157,129,70,165,99,67,177,184,175,43,140, - 235,247,99,21,107,216,174,143,129,35,253,189,192,253,86,173,175,195,11,82,129,93,97,252,166,137,17,12,16,12,26,252, - 94,181,136,14,198,137,200,198,153,86,161,145,74,79,206,0,119,90,55,203,86,6,167,84,193,202,217,116,71,187,40,230, - 255,225,214,28,220,170,67,69,153,209,84,250,178,52,164,179,42,149,158,148,185,135,143,182,93,255,235,229,61,170,203,115, - 88,185,34,249,181,18,162,96,223,240,30,162,177,46,234,135,47,112,240,212,109,108,219,230,198,173,41,12,0,173,53,133, - 66,97,11,235,248,57,114,111,30,211,63,212,199,200,104,15,134,25,160,248,243,15,185,85,135,3,231,47,98,89,22,65, - 51,184,149,129,104,241,90,188,86,129,16,3,215,151,88,212,167,249,186,244,133,207,239,62,241,170,52,206,254,155,239,81, - 129,16,34,2,141,71,120,4,162,209,34,32,226,125,172,0,134,137,27,234,101,228,193,42,43,43,43,228,223,190,134,128, - 137,214,26,192,51,105,18,136,96,189,184,198,143,233,97,214,23,167,26,68,26,183,238,182,36,35,72,93,35,186,209,13, - 3,163,153,252,242,2,82,43,81,90,94,160,251,228,93,0,142,37,71,121,250,236,73,115,93,23,221,68,111,230,181,25, - 98,104,108,130,202,135,231,132,198,38,208,90,163,68,72,36,146,36,18,73,68,20,74,137,135,223,48,216,70,96,154,38, - 71,175,100,128,76,219,169,178,109,111,114,203,229,50,0,149,74,101,59,65,54,155,197,117,93,118,82,74,169,45,131,72, - 36,210,68,2,168,86,171,0,212,106,181,142,6,142,227,120,70,237,70,121,7,53,251,31,168,192,0,159,97,230,172,204, - 0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t server[408] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,11,18,0, - 0,11,18,1,210,221,126,252,0,0,0,7,116,73,77,69,7,214,2,16,22,3,20,11,54,9,17,0,0,1,37,73, - 68,65,84,56,203,157,146,61,75,195,80,20,134,159,155,92,242,63,164,46,221,2,226,238,32,226,38,82,255,131,17,10, - 34,56,74,196,42,232,228,80,63,210,95,32,4,99,5,255,134,131,110,46,130,56,152,22,170,129,214,170,225,82,18,7, - 13,26,242,97,240,29,207,121,207,203,121,206,189,130,2,181,246,182,61,160,65,185,58,178,164,217,88,152,95,164,86,55, - 115,155,131,167,7,188,174,107,149,5,80,171,155,44,55,47,48,140,180,77,169,9,87,206,10,0,165,1,66,8,12,67, - 98,206,78,3,49,32,0,184,189,190,39,138,190,60,178,140,245,180,189,207,220,20,168,151,30,143,98,134,247,15,197,235, - 56,76,121,100,69,86,122,207,111,223,21,29,128,56,142,127,16,170,176,70,163,97,170,254,123,131,74,172,238,225,82,102, - 179,204,17,117,93,163,63,24,231,178,58,71,7,121,132,118,42,224,230,174,15,177,200,101,93,91,109,166,38,53,77,227, - 196,105,183,100,98,82,106,130,49,28,101,110,144,40,8,130,220,35,203,132,231,242,184,81,248,10,0,238,249,89,97,64, - 199,235,186,214,31,127,222,182,183,118,118,139,2,172,141,245,77,194,48,204,157,76,88,129,194,0,124,223,231,191,146,101, - 124,85,244,9,241,192,132,130,214,14,135,66,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t stateManager[378] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, - 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,6,16,18,41,48,44,67,93,90,0,0,1,7,73, - 68,65,84,56,203,189,146,189,74,3,65,28,196,127,251,145,69,177,176,73,44,124,128,128,207,225,19,8,130,136,31,129, - 136,104,37,34,104,173,32,10,130,181,165,112,6,242,20,190,78,138,120,8,90,104,178,183,123,107,17,15,205,37,94,238, - 82,56,229,252,255,59,179,179,179,226,168,221,4,216,19,130,136,10,8,129,125,224,73,103,135,175,78,46,73,146,1,225, - 123,90,4,33,36,215,15,183,81,8,32,142,15,154,225,188,125,138,148,211,151,245,48,198,153,250,4,175,134,49,55,157, - 14,58,35,30,163,59,250,214,148,186,254,138,177,180,118,47,70,6,25,217,183,134,237,213,151,82,2,221,94,131,193,231, - 59,90,215,144,204,9,169,70,222,114,150,83,183,215,40,20,210,191,115,253,181,156,231,151,148,35,245,14,231,146,31,129, - 245,250,219,92,81,52,128,181,31,60,199,203,149,90,216,202,71,168,218,130,79,253,236,71,44,213,6,64,234,221,255,182, - 48,33,96,236,43,155,27,135,99,131,212,123,164,82,164,222,231,62,208,56,39,90,59,107,247,139,11,254,76,235,218,84, - 7,231,146,194,8,95,134,90,101,183,231,143,210,134,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t timing[897] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0, - 0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,9,15,8,58,5,128,132,46,85,0,0,3,14,73, - 68,65,84,56,203,101,146,75,76,92,101,28,197,127,223,119,239,188,152,185,119,96,34,8,210,202,35,88,29,108,48,150, - 190,226,162,177,59,220,152,138,193,186,32,26,54,38,68,87,181,53,38,44,77,99,26,31,137,198,68,77,172,53,177,139, - 62,240,17,77,76,163,46,176,5,77,85,40,5,58,88,43,218,17,233,76,167,204,12,195,204,189,195,12,119,190,207,141, - 109,40,158,228,236,206,57,255,71,142,96,19,142,28,24,25,210,146,23,5,226,97,148,14,8,67,122,90,138,27,85,181, - 126,230,157,207,94,127,101,179,94,108,48,246,104,248,116,247,190,71,123,182,247,198,9,71,194,8,1,90,67,113,181,196, - 204,84,130,75,151,230,211,131,195,231,142,245,60,146,10,34,117,146,80,242,180,185,193,124,97,112,120,192,46,27,138,85, - 159,131,40,190,118,103,138,221,113,140,120,224,65,26,59,83,205,141,205,149,55,61,189,115,213,208,191,172,8,183,93,73, - 0,141,62,62,56,60,96,223,88,43,208,254,80,136,104,245,237,187,214,180,235,45,182,110,107,161,119,111,142,104,195,46, - 131,192,187,13,200,167,163,192,14,121,228,192,200,208,238,125,59,118,150,180,71,91,87,35,45,91,226,155,207,68,74,137, - 16,2,51,16,67,178,68,165,116,2,167,52,19,4,253,131,4,6,182,247,198,89,46,103,105,109,109,166,144,255,135,248, - 227,167,72,103,125,119,63,75,8,42,94,31,158,232,39,149,172,114,242,195,7,170,120,242,156,169,209,123,194,145,48,150, - 23,66,41,133,207,103,81,118,139,132,234,44,70,94,218,134,223,222,203,115,109,57,108,219,66,200,24,210,127,16,195,187, - 201,194,212,199,209,161,23,250,131,18,168,23,2,154,154,26,200,23,242,40,165,168,41,141,227,20,57,250,222,239,68,98, - 221,76,76,76,160,148,66,107,133,97,26,152,134,4,165,5,208,101,2,43,90,19,43,187,85,58,58,218,169,84,214,80, - 74,81,44,22,233,238,238,230,229,195,175,114,237,218,85,106,181,26,82,74,180,82,104,13,72,52,176,32,5,226,162,83, - 114,88,252,59,141,82,10,207,243,240,60,143,67,135,14,147,72,36,200,100,210,88,150,69,173,86,195,178,108,202,110,25, - 167,228,128,207,112,63,57,253,150,35,129,179,115,147,243,216,134,133,83,114,241,249,252,140,141,141,49,58,58,74,42,181, - 116,39,48,28,142,160,53,44,95,207,50,55,57,79,133,218,12,128,124,227,203,163,39,126,62,63,53,217,24,182,25,255, - 254,87,180,214,244,245,61,65,58,157,98,173,82,65,107,77,32,16,192,52,77,242,153,28,238,178,203,197,31,167,171,95, - 77,156,121,6,192,0,232,188,183,107,110,97,54,249,236,254,253,143,249,255,252,99,145,92,33,207,253,109,91,8,6,130, - 4,131,33,252,190,0,55,255,202,144,191,190,194,201,15,206,234,217,165,217,247,167,230,127,154,3,178,6,192,76,114,58, - 239,55,253,87,150,174,102,246,52,53,196,162,109,45,173,120,69,143,74,126,141,114,182,204,173,228,45,46,143,207,242,245, - 231,223,174,143,255,118,225,248,249,233,239,190,1,210,64,78,108,232,74,61,208,249,228,174,254,231,239,187,103,235,83,117, - 254,186,22,41,164,169,209,202,93,119,139,233,66,58,241,197,248,169,143,128,20,112,5,88,4,180,224,255,136,252,23,118, - 155,26,40,3,171,64,22,40,0,234,182,248,95,201,36,100,6,22,194,54,223,0,0,0,0,73,69,78,68,174,66,96, - 130, -}; - -const uint8_t unverified[1675] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122, - 244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,6,66,73,68,65,84,88,133,229,151,217,115,84, - 85,30,199,191,231,119,238,146,78,210,183,59,107,147,116,167,151,132,152,72,132,208,128,27,13,9,104,160,28,202,146,161, - 3,79,83,214,164,242,52,207,62,251,224,195,252,13,62,88,53,37,102,134,69,12,250,162,165,14,58,162,65,81,17,179, - 66,7,59,91,111,233,108,244,96,210,33,73,247,237,123,231,161,23,110,98,2,1,103,158,230,86,253,234,156,170,123,239, - 249,124,206,249,253,234,87,117,128,255,247,135,253,158,159,143,118,116,119,106,76,239,37,157,94,253,234,139,191,125,242,36, - 107,208,239,129,103,152,126,94,177,213,32,67,218,135,109,199,186,78,60,201,58,252,73,225,26,99,231,188,190,131,242,169, - 147,29,88,211,56,159,137,70,207,184,234,247,254,28,154,24,8,254,79,5,142,118,116,119,106,132,243,222,67,62,217,225, - 170,195,59,189,223,224,224,179,45,40,85,20,30,143,68,30,91,226,177,4,142,118,116,119,130,211,133,87,94,123,69,42, - 171,182,225,131,43,55,161,105,192,157,169,89,28,122,174,5,102,197,194,167,195,225,199,146,216,182,64,91,71,151,159,56, - 191,248,122,215,105,241,233,150,167,240,246,197,175,0,157,65,32,2,17,67,48,52,7,223,129,93,48,91,44,60,22,10, - 159,113,55,236,187,25,26,239,31,251,175,8,180,117,116,249,193,232,194,159,94,247,75,45,45,77,24,15,207,195,251,180, - 19,7,118,185,112,247,94,18,43,171,105,16,99,24,11,207,227,57,111,19,20,139,149,71,67,83,219,146,120,164,64,91, - 71,151,159,49,186,112,224,240,33,105,207,158,102,68,226,255,6,24,64,44,187,243,249,68,18,139,75,171,16,56,129,24, - 195,100,100,1,251,91,159,202,74,132,31,45,241,80,129,60,124,223,33,159,84,235,172,67,96,124,6,85,21,102,16,17, - 194,211,119,241,237,207,227,152,187,187,4,129,19,4,226,16,136,192,115,239,188,187,119,66,177,150,241,72,40,116,198,221, - 224,221,82,98,203,62,208,126,172,251,20,35,186,224,245,249,164,29,14,59,62,191,54,130,180,154,1,39,2,103,12,137, - 123,247,113,127,37,5,81,224,16,57,135,40,80,97,78,68,184,118,115,12,110,143,27,190,246,118,137,129,125,212,126,188, - 251,15,219,22,104,63,214,125,10,76,191,232,61,152,133,255,235,251,81,112,70,133,99,38,202,206,69,158,135,103,71,129, - 19,132,220,156,51,194,15,131,147,112,215,123,224,59,210,38,211,22,18,191,73,65,30,190,247,69,159,84,227,112,224,155, - 159,126,1,129,65,224,4,119,109,5,170,203,205,32,98,208,52,29,43,43,41,168,25,173,112,244,198,84,8,156,192,25, - 97,110,97,17,187,154,60,80,172,86,33,58,21,58,237,118,183,254,52,53,57,48,182,169,192,145,227,93,127,4,195,251, - 173,47,100,119,254,93,255,120,1,46,16,161,209,85,13,171,82,12,98,12,101,74,49,26,221,54,164,83,42,150,150,215, - 10,223,100,225,188,48,231,68,88,72,36,209,220,232,130,181,204,42,132,67,225,51,70,137,7,41,120,235,45,210,117,246, - 81,149,221,37,181,182,54,227,198,208,36,56,123,144,87,145,115,216,42,20,112,198,178,117,64,12,196,24,86,83,234,186, - 111,178,115,130,73,22,81,91,109,133,44,8,224,140,16,28,159,197,97,223,126,212,185,93,178,78,236,211,223,158,192,213, - 171,122,125,189,119,96,121,121,209,207,4,19,111,110,116,98,62,177,84,200,125,185,165,4,205,245,59,64,68,88,76,174, - 224,202,181,0,198,166,230,145,74,169,133,221,154,100,17,12,217,230,100,171,84,240,236,30,55,146,203,107,72,165,51,216, - 183,219,133,196,92,28,125,125,215,83,200,104,175,230,79,96,93,10,166,38,6,238,120,26,90,71,102,98,81,191,217,98, - 229,77,13,78,220,189,151,4,39,194,174,134,26,84,150,149,130,17,67,40,150,192,226,210,202,131,156,115,66,133,181,4, - 109,207,55,98,109,85,133,36,114,212,213,150,67,49,155,80,93,105,198,254,221,78,68,67,97,156,59,255,97,42,147,86, - 79,94,253,242,236,103,91,22,225,212,248,192,168,167,161,117,36,30,139,250,45,214,50,190,211,227,192,210,242,26,246,63, - 227,130,32,16,136,17,130,147,179,80,85,173,80,108,2,113,232,58,208,224,172,66,173,205,10,103,109,5,44,102,19,136, - 8,149,229,165,24,25,30,197,63,206,93,78,111,132,111,42,96,148,152,142,70,252,86,107,57,63,122,112,55,100,89,0, - 67,182,251,217,42,21,36,147,107,40,41,150,80,95,87,133,213,149,20,158,105,178,67,49,155,10,29,146,136,80,102,41, - 198,224,208,109,244,252,253,114,58,147,86,95,219,8,223,82,96,189,68,180,179,185,201,195,157,142,26,164,83,42,136,8, - 178,40,64,18,57,100,81,64,131,179,26,110,71,37,148,210,34,16,35,176,28,220,170,152,48,56,20,64,79,207,229,116, - 38,157,222,20,254,80,129,188,132,171,222,59,50,60,28,232,116,56,106,72,42,50,97,240,86,12,153,140,134,88,252,30, - 150,146,171,112,218,203,193,11,13,42,11,87,204,121,120,239,67,225,143,20,0,128,208,68,255,168,211,179,119,100,104,232, - 182,159,139,197,188,178,170,28,247,151,83,80,211,26,154,118,238,128,82,106,2,203,117,71,34,6,115,105,81,246,216,123, - 122,211,170,150,57,249,245,23,239,110,9,223,150,64,78,34,104,119,182,4,98,145,200,201,138,138,42,254,114,219,30,216, - 119,88,97,46,41,42,180,102,34,134,210,146,34,12,15,7,240,94,79,111,122,117,109,229,116,223,151,239,253,51,183,132, - 254,36,2,4,64,2,80,4,64,14,79,14,133,170,108,158,224,108,60,126,130,139,37,188,169,209,9,77,211,11,69,87, - 82,44,99,104,56,128,119,123,46,169,139,191,46,252,249,135,190,75,87,1,8,57,70,190,225,105,219,21,16,1,200,27, - 99,58,18,8,91,202,107,39,98,177,217,227,110,151,157,219,107,170,161,105,58,138,77,89,248,217,158,75,234,194,124,244, - 47,253,63,126,220,103,128,231,5,8,217,107,128,110,60,145,205,4,120,78,64,50,68,65,98,102,58,24,43,85,42,38, - 127,25,139,190,228,114,216,169,206,97,195,224,208,109,156,237,185,164,198,167,39,222,24,233,191,114,61,7,55,66,141,247, - 15,29,64,230,81,2,66,78,66,200,9,228,133,100,0,242,220,204,68,188,200,100,14,7,39,166,219,18,137,69,250,248, - 211,43,153,104,248,206,155,163,195,95,223,48,64,141,64,45,23,25,195,184,165,128,102,176,231,134,49,47,198,1,136,11, - 115,161,184,44,149,196,18,191,174,30,142,132,110,253,53,24,184,126,99,3,72,221,16,105,67,20,82,240,176,171,89,190, - 14,36,195,104,12,209,32,152,223,101,30,144,218,16,107,134,113,93,33,110,231,110,152,79,135,132,245,169,201,195,141,133, - 149,49,236,222,40,179,110,215,143,43,176,217,63,70,120,126,141,141,185,222,214,243,31,50,77,124,34,176,20,164,223,0, - 0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t up[652] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114, - 101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,30,73,68,65,84,56,141, - 149,147,79,104,19,65,20,198,191,55,187,51,217,141,133,122,104,76,255,209,130,4,237,193,64,42,168,208,213,138,104,68, - 98,69,45,20,114,107,74,201,73,144,98,22,193,171,199,82,145,160,23,15,69,79,30,165,66,241,226,77,42,94,68,80, - 208,67,41,180,42,149,148,52,137,166,154,38,217,217,25,15,81,172,33,169,246,29,223,251,230,199,124,223,155,33,173,53, - 218,213,201,155,124,30,0,150,102,189,233,118,26,214,110,224,184,60,221,223,21,73,246,117,29,76,58,46,79,239,9,224, - 184,60,26,16,251,178,87,206,76,6,199,70,147,193,128,8,102,29,151,71,255,11,224,184,188,3,132,197,137,115,211,214, - 150,151,199,150,183,137,248,200,37,11,132,69,199,229,29,255,4,16,225,209,232,112,162,167,55,52,72,159,75,31,240,177, - 244,30,157,157,157,20,27,58,209,13,194,195,93,1,142,203,211,253,7,34,137,179,71,199,249,74,254,13,12,198,97,50, - 142,87,107,11,136,13,29,23,161,253,61,137,230,60,216,142,195,81,193,237,108,42,225,218,235,229,101,104,242,32,132,137, - 58,125,199,54,21,241,46,255,28,23,78,95,13,154,166,248,43,15,182,211,247,212,88,198,82,228,161,34,75,16,1,1, - 30,224,40,203,117,8,219,64,65,174,162,168,86,113,254,212,69,139,216,159,60,216,111,223,241,99,227,221,135,250,98,148, - 175,172,193,228,6,56,55,80,81,5,84,141,175,16,54,131,176,25,150,191,189,64,184,55,68,71,14,15,135,137,53,242, - 160,145,140,153,30,232,142,100,111,76,220,177,5,15,64,65,194,135,135,215,185,5,188,45,60,131,100,21,16,35,36,6, - 50,208,90,67,41,160,94,175,225,241,211,249,74,177,180,57,99,18,67,234,83,110,197,158,185,119,185,225,137,163,122,247, - 250,19,171,44,115,240,141,109,112,193,192,76,130,193,9,115,15,110,87,101,77,91,191,236,7,137,33,101,46,205,122,78, - 211,38,180,214,10,165,250,23,48,131,96,112,6,30,104,64,100,77,91,47,231,60,218,245,29,0,128,210,62,126,212,139, - 141,43,251,26,178,174,160,85,235,63,99,182,106,250,74,162,90,219,134,50,53,160,21,124,73,240,189,61,0,164,47,17, - 31,188,6,98,0,49,2,17,246,0,32,108,220,186,63,25,110,37,38,194,70,115,239,39,48,247,197,219,182,208,154,34, - 0,0,0,0,73,69,78,68,174,66,96,130, -}; - -const uint8_t video[662] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255, - 97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13, - 215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99, - 97,112,101,46,111,114,103,155,238,60,26,0,0,2,19,73,68,65,84,56,141,165,147,203,106,20,65,20,134,191,83,85, - 115,109,72,50,32,6,98,18,35,38,11,183,222,54,186,112,99,6,29,240,25,124,4,55,130,184,81,80,4,241,49,124, - 131,108,92,8,9,17,34,226,222,96,188,129,38,16,131,97,72,156,233,234,233,158,238,58,46,58,17,19,3,65,60,155, - 42,170,234,255,207,119,206,161,164,221,110,243,63,225,58,157,206,29,17,121,168,170,181,127,17,138,136,87,213,187,78,85, - 31,183,111,92,143,154,141,38,121,174,199,103,116,130,181,134,110,183,91,95,90,124,245,196,169,106,109,116,116,132,249,155, - 207,73,233,3,160,122,132,209,222,81,77,34,94,190,184,205,200,232,40,64,195,237,223,167,161,207,133,171,99,136,200,30, - 34,128,148,171,0,90,238,223,44,111,179,250,238,61,83,83,147,37,81,154,166,128,160,226,136,211,80,10,20,68,228,128, - 73,54,204,217,238,254,4,28,103,103,103,49,18,74,3,239,61,33,20,24,99,24,228,82,102,43,155,4,148,194,205,31, - 59,196,62,5,160,97,90,124,88,91,99,122,122,146,36,73,112,73,146,80,20,1,140,35,201,203,108,138,32,64,156,164, - 236,244,18,84,29,149,250,94,181,137,101,122,230,52,21,103,240,222,227,226,56,70,131,98,76,133,65,112,251,0,36,233, - 144,108,104,112,181,232,224,248,172,229,243,199,79,204,205,205,210,239,247,75,2,69,17,107,73,131,3,5,69,81,107,169, - 216,35,134,97,135,76,156,154,192,24,202,18,188,247,0,24,227,176,213,232,111,197,161,24,154,62,69,81,160,8,113,28, - 227,66,40,187,217,106,56,178,205,193,177,6,81,213,33,70,49,34,37,129,115,174,183,254,109,163,245,236,209,249,99,197, - 191,41,210,156,245,245,13,128,29,233,116,58,183,106,181,218,3,17,141,64,12,48,83,169,56,87,169,86,197,26,3,64, - 17,2,89,150,105,62,204,135,192,87,208,160,202,174,247,201,125,151,231,249,66,158,231,11,0,170,26,181,78,140,189,157, - 111,183,207,93,186,120,153,241,147,227,168,42,91,91,223,89,121,189,162,75,203,75,171,73,111,112,37,203,50,191,79,35, - 135,191,179,49,102,164,222,172,63,109,70,205,107,214,154,51,128,22,161,248,50,240,131,197,222,110,255,158,136,196,127,190, - 255,5,119,143,242,70,185,147,13,30,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -}; diff --git a/target-higan/resource/resource.hpp b/target-higan/resource/resource.hpp deleted file mode 100644 index 8a518946..00000000 --- a/target-higan/resource/resource.hpp +++ /dev/null @@ -1,16 +0,0 @@ -namespace resource { - extern const uint8_t advanced[611]; - extern const uint8_t audio[592]; - extern const uint8_t cheatEditor[937]; - extern const uint8_t folder[1176]; - extern const uint8_t game[1490]; - extern const uint8_t home[606]; - extern const uint8_t hotkeys[587]; - extern const uint8_t input[812]; - extern const uint8_t server[408]; - extern const uint8_t stateManager[378]; - extern const uint8_t timing[897]; - extern const uint8_t unverified[1675]; - extern const uint8_t up[652]; - extern const uint8_t video[662]; -}; diff --git a/target-higan/resource/unverified.png b/target-higan/resource/unverified.png deleted file mode 100644 index 8a150b84..00000000 Binary files a/target-higan/resource/unverified.png and /dev/null differ diff --git a/target-higan/settings/advanced.cpp b/target-higan/settings/advanced.cpp deleted file mode 100644 index 508c11a9..00000000 --- a/target-higan/settings/advanced.cpp +++ /dev/null @@ -1,81 +0,0 @@ -AdvancedSettings* advancedSettings = nullptr; - -AdvancedSettings::AdvancedSettings() { - driverTitle.setFont(program->boldFont); - driverTitle.setText("Driver Selection:"); - videoLabel.setText("Video:"); - audioLabel.setText("Audio:"); - inputLabel.setText("Input:"); - libraryTitle.setFont(program->boldFont); - libraryTitle.setText("Game Library:"); - libraryLabel.setText("Path:"); - libraryPath.setEditable(false); - libraryPath.setText(utility->libraryPath()); - libraryBrowse.setText("Browse ..."); - libraryShowOnStartup.setChecked(config->library.showOnStartup); - libraryShowOnStartup.setText("Show game library on program start"); - information.setText("Note: changing advanced settings requires program restart to take effect."); - infoLabel.setFont(program->boldFont); - infoLabel.setText({ - Emulator::Name, " v", Emulator::Version, "\n", - " ", Emulator::Profile, " Profile\n", - " Author: ", Emulator::Author, "\n", - " License: ", Emulator::License, "\n", - " Website: ", Emulator::Website - }); - - lstring list; - - list.split(";", video.availableDrivers()); - for(unsigned n = 0; n < list.size(); n++) { - videoDriver.append(list[n]); - if(list[n] == config->video.driver) videoDriver.setSelection(n); - } - - list.split(";", audio.availableDrivers()); - for(unsigned n = 0; n < list.size(); n++) { - audioDriver.append(list[n]); - if(list[n] == config->audio.driver) audioDriver.setSelection(n); - } - - list.split(";", input.availableDrivers()); - for(unsigned n = 0; n < list.size(); n++) { - inputDriver.append(list[n]); - if(list[n] == config->input.driver) inputDriver.setSelection(n); - } - - append(driverTitle, {~0, 0}); - append(driverLayout, {~0, 0}, 15); - driverLayout.append(videoLabel, {0, 0}, 5); - driverLayout.append(videoDriver, {~0, 0}, 5); - driverLayout.append(audioLabel, {0, 0}, 5); - driverLayout.append(audioDriver, {~0, 0}, 5); - driverLayout.append(inputLabel, {0, 0}, 5); - driverLayout.append(inputDriver, {~0, 0}); - append(libraryTitle, {~0, 0}); - append(libraryLayout, {~0, 0}); - libraryLayout.append(libraryLabel, {0, 0}, 5); - libraryLayout.append(libraryPath, {~0, 0}, 5); - libraryLayout.append(libraryBrowse, {80, 0}); - append(libraryShowOnStartup, {~0, 0}, 15); - append(information, {~0, 0}, 15); - if(Intrinsics::platform() != Intrinsics::Platform::MacOSX) { - append(spacer, {~0, ~0}); - append(infoLabel, {~0, 0}); - } - - videoDriver.onChange = [&] { config->video.driver = videoDriver.text(); }; - audioDriver.onChange = [&] { config->audio.driver = audioDriver.text(); }; - inputDriver.onChange = [&] { config->input.driver = inputDriver.text(); }; - - libraryBrowse.onActivate = [&] { - string path = BrowserWindow().setParent(*settings).setPath(userpath()).directory(); - if(path.empty()) return; - file::write({configpath(), "higan/library.bml"}, {"Path: ", path, "\n"}); - libraryPath.setText(path); - }; - - libraryShowOnStartup.onToggle = [&] { - config->library.showOnStartup = libraryShowOnStartup.checked(); - }; -} diff --git a/target-higan/settings/advanced.hpp b/target-higan/settings/advanced.hpp deleted file mode 100644 index eaf0041a..00000000 --- a/target-higan/settings/advanced.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct AdvancedSettings : SettingsLayout { - Label driverTitle; - HorizontalLayout driverLayout; - Label videoLabel; - ComboButton videoDriver; - Label audioLabel; - ComboButton audioDriver; - Label inputLabel; - ComboButton inputDriver; - - Label libraryTitle; - HorizontalLayout libraryLayout; - Label libraryLabel; - LineEdit libraryPath; - Button libraryBrowse; - CheckLabel libraryShowOnStartup; - - Label information; - - Widget spacer; - Label infoLabel; - - AdvancedSettings(); -}; - -extern AdvancedSettings* advancedSettings; diff --git a/target-higan/settings/audio.cpp b/target-higan/settings/audio.cpp deleted file mode 100644 index 6059576c..00000000 --- a/target-higan/settings/audio.cpp +++ /dev/null @@ -1,79 +0,0 @@ -AudioSettings* audioSettings = nullptr; - -AudioSlider::AudioSlider() { - append(name, {75, 0}); - append(value, {75, 0}); - append(slider, {~0, 0}); -} - -AudioSettings::AudioSettings() { - frequencyLabel.setText("Frequency:"); - frequency.append("32000hz"); - frequency.append("44100hz"); - frequency.append("48000hz"); - frequency.append("96000hz"); - latencyLabel.setText("Latency:"); - latency.append("20ms"); - latency.append("40ms"); - latency.append("60ms"); - latency.append("80ms"); - latency.append("100ms"); - resamplerLabel.setText("Resampler:"); - resampler.append("Linear"); - resampler.append("Hermite"); - resampler.append("Sinc"); - volume.name.setText("Volume:"); - volume.slider.setLength(201); - - append(controlLayout, {~0, 0}, 5); - controlLayout.append(frequencyLabel, {0, 0}, 5); - controlLayout.append(frequency, {~0, 0}, 5); - controlLayout.append(latencyLabel, {0, 0}, 5); - controlLayout.append(latency, {~0, 0}, 5); - controlLayout.append(resamplerLabel, {0, 0}, 5); - controlLayout.append(resampler, {~0, 0}); - append(volume, {~0, 0}); - - switch(config->audio.frequency) { default: - case 32000: frequency.setSelection(0); break; - case 44100: frequency.setSelection(1); break; - case 48000: frequency.setSelection(2); break; - case 96000: frequency.setSelection(3); break; - } - switch(config->audio.latency) { default: - case 20: latency.setSelection(0); break; - case 40: latency.setSelection(1); break; - case 60: latency.setSelection(2); break; - case 80: latency.setSelection(3); break; - case 100: latency.setSelection(4); break; - } - resampler.setSelection(config->audio.resampler); - volume.slider.setPosition(config->audio.volume); - - frequency.onChange = latency.onChange = resampler.onChange = volume.slider.onChange = - {&AudioSettings::synchronize, this}; - - synchronize(); -} - -void AudioSettings::synchronize() { - switch(frequency.selection()) { - case 0: config->audio.frequency = 32000; break; - case 1: config->audio.frequency = 44100; break; - case 2: config->audio.frequency = 48000; break; - case 3: config->audio.frequency = 96000; break; - } - switch(latency.selection()) { - case 0: config->audio.latency = 20; break; - case 1: config->audio.latency = 40; break; - case 2: config->audio.latency = 60; break; - case 3: config->audio.latency = 80; break; - case 4: config->audio.latency = 100; break; - } - config->audio.resampler = resampler.selection(); - config->audio.volume = volume.slider.position(); - - volume.value.setText({config->audio.volume, "%"}); - - utility->synchronizeRuby(); -} diff --git a/target-higan/settings/audio.hpp b/target-higan/settings/audio.hpp deleted file mode 100644 index d27fcfc8..00000000 --- a/target-higan/settings/audio.hpp +++ /dev/null @@ -1,23 +0,0 @@ -struct AudioSlider : HorizontalLayout { - Label name; - Label value; - HorizontalSlider slider; - - AudioSlider(); -}; - -struct AudioSettings : SettingsLayout { - HorizontalLayout controlLayout; - Label frequencyLabel; - ComboButton frequency; - Label latencyLabel; - ComboButton latency; - Label resamplerLabel; - ComboButton resampler; - AudioSlider volume; - - void synchronize(); - AudioSettings(); -}; - -extern AudioSettings* audioSettings; diff --git a/target-higan/settings/hotkey.cpp b/target-higan/settings/hotkey.cpp deleted file mode 100644 index e5ec041e..00000000 --- a/target-higan/settings/hotkey.cpp +++ /dev/null @@ -1,58 +0,0 @@ -HotkeySettings* hotkeySettings = nullptr; - -HotkeySettings::HotkeySettings() { - inputList.setHeaderText({"Name", "Mapping"}); - inputList.setHeaderVisible(); - eraseButton.setText("Erase"); - - append(inputList, {~0, ~0}, 5); - append(controlLayout, {~0, 0}); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(eraseButton, {80, 0}); - - inputList.onChange = {&HotkeySettings::synchronize, this}; - inputList.onActivate = {&HotkeySettings::assignInput, this}; - eraseButton.onActivate = {&HotkeySettings::eraseInput, this}; - - for(auto& hotkey : inputManager->hotkeyMap) inputList.append({"", ""}); - refresh(); -} - -void HotkeySettings::synchronize() { - eraseButton.setEnabled(inputList.selected()); -} - -void HotkeySettings::refresh() { - unsigned index = 0; - for(auto& hotkey : inputManager->hotkeyMap) { - string mapping = inputManager->sanitize(hotkey->mapping, " and "); - inputList.setText(index++, {hotkey->name, mapping}); - } - synchronize(); -} - -void HotkeySettings::eraseInput() { - activeInput = inputManager->hotkeyMap[inputList.selection()]; - inputEvent(hidNull, 0, 0, 0, 1); -} - -void HotkeySettings::assignInput() { - activeInput = inputManager->hotkeyMap[inputList.selection()]; - - settings->setStatusText({"Set assignment for [", activeInput->name, "] ..."}); - settings->layout.setEnabled(false); - setEnabled(false); -} - -void HotkeySettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(activeInput == nullptr) return; - if(device.isMouse()) return; - if(device.isJoypad() && group == HID::Joypad::GroupID::Axis) return; - if(activeInput->bind(device, group, input, oldValue, newValue) == false) return; - - activeInput = nullptr; - settings->setStatusText(""); - settings->layout.setEnabled(true); - setEnabled(true); - refresh(); -} diff --git a/target-higan/settings/hotkey.hpp b/target-higan/settings/hotkey.hpp deleted file mode 100644 index c254df73..00000000 --- a/target-higan/settings/hotkey.hpp +++ /dev/null @@ -1,18 +0,0 @@ -struct HotkeySettings : SettingsLayout { - ListView inputList; - HorizontalLayout controlLayout; - Widget spacer; - Button eraseButton; - - void synchronize(); - void refresh(); - void eraseInput(); - void assignInput(); - void inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - HotkeySettings(); - -private: - HotkeyInput* activeInput = nullptr; -}; - -extern HotkeySettings* hotkeySettings; diff --git a/target-higan/settings/input.cpp b/target-higan/settings/input.cpp deleted file mode 100644 index b720524c..00000000 --- a/target-higan/settings/input.cpp +++ /dev/null @@ -1,187 +0,0 @@ -InputSettings* inputSettings = nullptr; - -InputSettings::InputSettings() { - focusLabel.setText("When Focus is Lost:"); - focusPause.setText("Pause Emulation"); - focusAllow.setText("Allow Input"); - inputList.setHeaderText({"Name", "Mapping"}); - inputList.setHeaderVisible(); - resetButton.setText("Reset"); - eraseButton.setText("Erase"); - - append(focusLayout, {~0, 0}, 5); - focusLayout.append(focusLabel, {0, 0}, 5); - focusLayout.append(focusPause, {0, 0}, 5); - focusLayout.append(focusAllow, {0, 0}); - append(selectionLayout, {~0, 0}, 5); - selectionLayout.append(systemList, {~0, 0}, 5); - selectionLayout.append(portList, {~0, 0}, 5); - selectionLayout.append(deviceList, {~0, 0}); - append(inputList, {~0, ~0}, 5); - append(controlLayout, {~0, 0}); - controlLayout.append(assign[0], {100, 0}, 5); - controlLayout.append(assign[1], {100, 0}, 5); - controlLayout.append(assign[2], {100, 0}, 5); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(resetButton, {80, 0}, 5); - controlLayout.append(eraseButton, {80, 0}); - - for(auto& emulator : program->emulator) { - systemList.append(emulator->information.name); - } - - focusPause.setChecked(config->input.focus.pause); - focusAllow.setChecked(config->input.focus.allow); - focusAllow.setEnabled(!config->input.focus.pause); - - focusPause.onToggle = [&] { config->input.focus.pause = focusPause.checked(); focusAllow.setEnabled(!focusPause.checked()); }; - focusAllow.onToggle = [&] { config->input.focus.allow = focusAllow.checked(); }; - systemList.onChange = {&InputSettings::systemChanged, this}; - portList.onChange = {&InputSettings::portChanged, this}; - deviceList.onChange = {&InputSettings::deviceChanged, this}; - inputList.onChange = {&InputSettings::synchronize, this}; - inputList.onActivate = {&InputSettings::assignInput, this}; - assign[0].onActivate = [&] { assignMouseInput(0); }; - assign[1].onActivate = [&] { assignMouseInput(1); }; - assign[2].onActivate = [&] { assignMouseInput(2); }; - resetButton.onActivate = {&InputSettings::resetInput, this}; - eraseButton.onActivate = {&InputSettings::eraseInput, this}; - - systemChanged(); -} - -void InputSettings::synchronize() { - if(inputList.selected() == false) { - assign[0].setVisible(false); - assign[1].setVisible(false); - assign[2].setVisible(false); - } else { - unsigned number = activeDevice().order[inputList.selection()]; - auto& input = activeDevice().input[number]; - auto selectedInput = inputManager->inputMap[input.guid]; - - if(dynamic_cast<DigitalInput*>(selectedInput)) { - assign[0].setText("Mouse Left"); - assign[1].setText("Mouse Middle"); - assign[2].setText("Mouse Right"); - assign[0].setVisible(true); - assign[1].setVisible(true); - assign[2].setVisible(true); - } - - if(dynamic_cast<RelativeInput*>(selectedInput)) { - assign[0].setText("Mouse X-axis"); - assign[1].setText("Mouse Y-axis"); - assign[0].setVisible(true); - assign[1].setVisible(true); - assign[2].setVisible(false); - } - } - - eraseButton.setEnabled(inputList.selected()); -} - -Emulator::Interface& InputSettings::activeSystem() { - return *program->emulator[systemList.selection()]; -} - -Emulator::Interface::Port& InputSettings::activePort() { - return activeSystem().port[portList.selection()]; -} - -Emulator::Interface::Device& InputSettings::activeDevice() { - return activePort().device[deviceList.selection()]; -} - -void InputSettings::systemChanged() { - portList.reset(); - for(auto& port : activeSystem().port) { - portList.append(port.name); - } - portChanged(); -} - -void InputSettings::portChanged() { - deviceList.reset(); - for(auto& device : activePort().device) { - deviceList.append(device.name); - } - deviceChanged(); -} - -void InputSettings::deviceChanged() { - inputList.reset(); - for(unsigned number : activeDevice().order) inputList.append({"", ""}); - inputChanged(); - synchronize(); -} - -void InputSettings::inputChanged() { - unsigned index = 0; - for(unsigned number : activeDevice().order) { - auto& input = activeDevice().input[number]; - auto abstract = inputManager->inputMap(input.guid); - string mapping = inputManager->sanitize(abstract->mapping, " or "); - inputList.setText(index++, {input.name, mapping}); - } -} - -void InputSettings::resetInput() { - if(MessageWindow().setParent(*settings).setText("All inputs will be erased. Are you sure you want to do this?") - .question() == MessageWindow::Response::No) return; - - auto& device = activeDevice(); - unsigned length = device.input.size(); - for(unsigned n = 0; n < length; n++) { - activeInput = inputManager->inputMap[device.input[n].guid]; - inputEvent(hidNull, 0, 0, 0, 1); - } -} - -void InputSettings::eraseInput() { - unsigned number = activeDevice().order[inputList.selection()]; - auto& input = activeDevice().input[number]; - activeInput = inputManager->inputMap[input.guid]; - inputEvent(hidNull, 0, 0, 0, 1); -} - -void InputSettings::assignInput() { - unsigned number = activeDevice().order[inputList.selection()]; - auto& input = activeDevice().input[number]; - activeInput = inputManager->inputMap[input.guid]; - - settings->setStatusText({"Set assignment for [", activeDevice().name, "::", input.name, "] ..."}); - settings->layout.setEnabled(false); - setEnabled(false); -} - -void InputSettings::assignMouseInput(unsigned n) { - unsigned number = activeDevice().order[inputList.selection()]; - auto& input = activeDevice().input[number]; - activeInput = inputManager->inputMap[input.guid]; - - if(dynamic_cast<DigitalInput*>(activeInput)) { - if(auto hidMouse = inputManager->findMouse()) { - return inputEvent(*hidMouse, HID::Mouse::GroupID::Button, n, 0, 1, true); - } - } - - if(dynamic_cast<RelativeInput*>(activeInput)) { - if(auto hidMouse = inputManager->findMouse()) { - return inputEvent(*hidMouse, HID::Mouse::GroupID::Axis, n, 0, +32767, true); - } - } -} - -void InputSettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue, bool allowMouseInput) { - if(activeInput == nullptr) return; - if(allowMouseInput == false && device.isMouse()) return; - if(activeInput->bind(device, group, input, oldValue, newValue) == false) return; - - activeInput = nullptr; - inputChanged(); - settings->setStatusText(""); - settings->layout.setEnabled(true); - setEnabled(true); - synchronize(); -} diff --git a/target-higan/settings/input.hpp b/target-higan/settings/input.hpp deleted file mode 100644 index 20a505f3..00000000 --- a/target-higan/settings/input.hpp +++ /dev/null @@ -1,38 +0,0 @@ -struct InputSettings : SettingsLayout { - HorizontalLayout focusLayout; - Label focusLabel; - CheckLabel focusPause; - CheckLabel focusAllow; - HorizontalLayout selectionLayout; - ComboButton systemList; - ComboButton portList; - ComboButton deviceList; - ListView inputList; - HorizontalLayout controlLayout; - Button assign[3]; - Widget spacer; - Button resetButton; - Button eraseButton; - - void synchronize(); - - Emulator::Interface& activeSystem(); - Emulator::Interface::Port& activePort(); - Emulator::Interface::Device& activeDevice(); - - void systemChanged(); - void portChanged(); - void deviceChanged(); - void inputChanged(); - void resetInput(); - void eraseInput(); - void assignInput(); - void assignMouseInput(unsigned n); - void inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue, bool allowMouseInput = false); - InputSettings(); - -private: - AbstractInput* activeInput = nullptr; -}; - -extern InputSettings* inputSettings; diff --git a/target-higan/settings/server.cpp b/target-higan/settings/server.cpp deleted file mode 100644 index 44e4fd1a..00000000 --- a/target-higan/settings/server.cpp +++ /dev/null @@ -1,29 +0,0 @@ -ServerSettings* serverSettings = nullptr; - -ServerSettings::ServerSettings() { - hostLabel.setText("Hostname:"); - userLabel.setText("Username:"); - passLabel.setText("Password:"); - - unsigned width = min( - Font::size(program->normalFont, "Hostname:").width, - Font::size(program->normalFont, "Username:").width - ); - - append(hostLayout, {~0, 0}, 5); - hostLayout.append(hostLabel, {width, 0}, 5); - hostLayout.append(hostEdit, {~0, 0}); - append(userLayout, {~0, 0}); - userLayout.append(userLabel, {width, 0}, 5); - userLayout.append(userEdit, {~0, 0}, 5); - userLayout.append(passLabel, {0, 0}, 5); - userLayout.append(passEdit, {~0, 0}); - - hostEdit.setText(config->server.hostname); - userEdit.setText(config->server.username); - passEdit.setText(config->server.password); - - hostEdit.onChange = [&] { config->server.hostname = hostEdit.text(); }; - userEdit.onChange = [&] { config->server.username = userEdit.text(); }; - passEdit.onChange = [&] { config->server.password = passEdit.text(); }; -} diff --git a/target-higan/settings/server.hpp b/target-higan/settings/server.hpp deleted file mode 100644 index 617c49c2..00000000 --- a/target-higan/settings/server.hpp +++ /dev/null @@ -1,14 +0,0 @@ -struct ServerSettings : SettingsLayout { - HorizontalLayout hostLayout; - Label hostLabel; - LineEdit hostEdit; - HorizontalLayout userLayout; - Label userLabel; - LineEdit userEdit; - Label passLabel; - LineEdit passEdit; - - ServerSettings(); -}; - -extern ServerSettings* serverSettings; diff --git a/target-higan/settings/settings.cpp b/target-higan/settings/settings.cpp deleted file mode 100644 index b9be5910..00000000 --- a/target-higan/settings/settings.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "../higan.hpp" -#include "video.cpp" -#include "audio.cpp" -#include "input.cpp" -#include "hotkey.cpp" -#include "timing.cpp" -#include "server.cpp" -#include "advanced.cpp" -Settings* settings = nullptr; - -SettingsLayout::SettingsLayout() { - setMargin(5); -} - -Settings::Settings() { - setGeometry({128, 128, 640, 360}); - windowManager->append(this, "Settings"); - - setTitle("Configuration Settings"); - setStatusVisible(); - - layout.setMargin(5); - panels.append("Video", {resource::video, sizeof resource::video}); - panels.append("Audio", {resource::audio, sizeof resource::audio}); - panels.append("Input", {resource::input, sizeof resource::input}); - panels.append("Hotkeys", {resource::hotkeys, sizeof resource::hotkeys}); - panels.append("Timing", {resource::timing, sizeof resource::timing}); - panels.append("Server", {resource::server, sizeof resource::server}); - panels.append("Advanced", {resource::advanced, sizeof resource::advanced}); - panels.setLayout(0, *videoSettings); - panels.setLayout(1, *audioSettings); - panels.setLayout(2, *inputSettings); - panels.setLayout(3, *hotkeySettings); - panels.setLayout(4, *timingSettings); - panels.setLayout(5, *serverSettings); - panels.setLayout(6, *advancedSettings); - panels.setSelection(2); - - append(layout); - layout.append(panels, {~0, ~0}); - - onClose = [&] { - timingSettings->analysis.stop = true; - setVisible(false); - }; -} diff --git a/target-higan/settings/settings.hpp b/target-higan/settings/settings.hpp deleted file mode 100644 index db3e8235..00000000 --- a/target-higan/settings/settings.hpp +++ /dev/null @@ -1,20 +0,0 @@ -struct SettingsLayout : VerticalLayout { - SettingsLayout(); -}; - -#include "video.hpp" -#include "audio.hpp" -#include "input.hpp" -#include "hotkey.hpp" -#include "timing.hpp" -#include "server.hpp" -#include "advanced.hpp" - -struct Settings : Window { - VerticalLayout layout; - TabFrame panels; - - Settings(); -}; - -extern Settings* settings; diff --git a/target-higan/settings/timing.cpp b/target-higan/settings/timing.cpp deleted file mode 100644 index 3fdc0c36..00000000 --- a/target-higan/settings/timing.cpp +++ /dev/null @@ -1,126 +0,0 @@ -TimingSettings* timingSettings = nullptr; - -TimingAdjustment::TimingAdjustment() { - assign.setEnabled(false); - assign.setText("Assign"); - analyze.setText("Analyze"); - stop.setEnabled(false); - stop.setText("Stop"); - - append(name, {40, 0}); - append(value, {100, 0}, 5); - append(assign, {80, 0}, 5); - append(spacer, {~0, 0}); - append(analyze, {80, 0}, 5); - append(stop, {80, 0}); -} - -TimingSettings::TimingSettings() { - videoAdjust.name.setText("Video:"); - videoAdjust.value.setText({config->timing.video}); - audioAdjust.name.setText("Audio:"); - audioAdjust.value.setText({config->timing.audio}); - - append(videoAdjust, {~0, 0}, 5); - append(audioAdjust, {~0, 0}, 5); - - videoAdjust.value.onChange = [&] { videoAdjust.assign.setEnabled(true); }; - audioAdjust.value.onChange = [&] { audioAdjust.assign.setEnabled(true); }; - videoAdjust.assign.onActivate = [&] { - config->timing.video = atof(videoAdjust.value.text()); - videoAdjust.value.setText({config->timing.video}); - videoAdjust.assign.setEnabled(false); - utility->synchronizeDSP(); - }; - audioAdjust.assign.onActivate = [&] { - config->timing.audio = atof(audioAdjust.value.text()); - audioAdjust.value.setText({config->timing.audio}); - audioAdjust.assign.setEnabled(false); - utility->synchronizeDSP(); - }; - videoAdjust.analyze.onActivate = {&TimingSettings::analyzeVideoFrequency, this}; - audioAdjust.analyze.onActivate = {&TimingSettings::analyzeAudioFrequency, this}; - videoAdjust.stop.onActivate = audioAdjust.stop.onActivate = [&] { analysis.stop = true; }; -} - -void TimingSettings::analyzeVideoFrequency() { - video.set(Video::Synchronize, true); - audio.set(Audio::Synchronize, false); - videoAdjust.stop.setEnabled(true); - analyzeStart(); - do { - uint32_t* output; - unsigned pitch; - if(video.lock(output, pitch, 16, 16)) { - pitch >>= 2; - for(unsigned y = 0; y < 16; y++) memset(output + y * pitch, 0, 4 * 16); - video.unlock(); - video.refresh(); - } - } while(analyzeTick("Video")); - analyzeStop(); -} - -void TimingSettings::analyzeAudioFrequency() { - video.set(Video::Synchronize, false); - audio.set(Audio::Synchronize, true); - audioAdjust.stop.setEnabled(true); - analyzeStart(); - do { - audio.sample(0, 0); - } while(analyzeTick("Audio")); - analyzeStop(); -} - -void TimingSettings::analyzeStart() { - audio.clear(); - -//settings->panels.setEnabled(false); - videoAdjust.analyze.setEnabled(false); - audioAdjust.analyze.setEnabled(false); - settings->setStatusText("Initializing ..."); - Application::processEvents(); - - analysis.stop = false; - analysis.seconds = 0; - analysis.counter = 0; - analysis.sample.reset(); - analysis.systemTime = time(0); -} - -bool TimingSettings::analyzeTick(string type) { - analysis.counter++; - - time_t systemTime = time(0); - if(systemTime > analysis.systemTime) { - analysis.systemTime = systemTime; - Application::processEvents(); - - if(analysis.seconds < 3) { - analysis.seconds++; - } else { - analysis.sample.append(analysis.counter); - uintmax_t sum = 0; - for(auto& point : analysis.sample) sum += point; - settings->setStatusText({ - type, " sample rate: ", (double)sum / analysis.sample.size(), "hz", - " (", analysis.sample.size(), " sample points)" - }); - } - - analysis.counter = 0; - } - - return !analysis.stop; -} - -void TimingSettings::analyzeStop() { - video.set(Video::Synchronize, config->video.synchronize); - audio.set(Audio::Synchronize, config->audio.synchronize); - -//settings->panels.setEnabled(true); - videoAdjust.analyze.setEnabled(true); - audioAdjust.analyze.setEnabled(true); - videoAdjust.stop.setEnabled(false); - audioAdjust.stop.setEnabled(false); -} diff --git a/target-higan/settings/timing.hpp b/target-higan/settings/timing.hpp deleted file mode 100644 index 8c89cc9b..00000000 --- a/target-higan/settings/timing.hpp +++ /dev/null @@ -1,34 +0,0 @@ -struct TimingAdjustment : HorizontalLayout { - Label name; - LineEdit value; - Button assign; - Widget spacer; - Button analyze; - Button stop; - - TimingAdjustment(); -}; - -struct TimingSettings : SettingsLayout { - TimingAdjustment videoAdjust; - TimingAdjustment audioAdjust; - - void analyzeVideoFrequency(); - void analyzeAudioFrequency(); - - void analyzeStart(); - bool analyzeTick(string type); - void analyzeStop(); - - TimingSettings(); - - struct Analysis { - bool stop; - unsigned seconds; - unsigned counter; - vector<unsigned> sample; - time_t systemTime; - } analysis; -}; - -extern TimingSettings* timingSettings; diff --git a/target-higan/settings/video.cpp b/target-higan/settings/video.cpp deleted file mode 100644 index 6d33aadf..00000000 --- a/target-higan/settings/video.cpp +++ /dev/null @@ -1,64 +0,0 @@ -VideoSettings* videoSettings = nullptr; - -VideoSlider::VideoSlider() { - append(name, {75, 0}); - append(value, {75, 0}); - append(slider, {~0, 0}); -} - -VideoSettings::VideoSettings() { - colorAdjustment.setFont(program->boldFont); - colorAdjustment.setText("Color adjustment:"); - saturation.name.setText("Saturation:"); - saturation.slider.setLength(201); - gamma.name.setText("Gamma:"); - gamma.slider.setLength(101); - luminance.name.setText("Luminance:"); - luminance.slider.setLength(101); - colorEmulation.setText("Color emulation"); - overscanAdjustment.setFont(program->boldFont); - overscanAdjustment.setText("Overscan mask:"); - overscanHorizontal.name.setText("Horizontal:"); - overscanHorizontal.slider.setLength(17); - overscanVertical.name.setText("Vertical:"); - overscanVertical.slider.setLength(17); - - append(colorAdjustment, {~0, 0}); - append(saturation, {~0, 0}); - append(gamma, {~0, 0}); - append(luminance, {~0, 0}); - append(colorEmulation, {~0, 0}, 5); - append(overscanAdjustment, {~0, 0}); - append(overscanHorizontal, {~0, 0}); - append(overscanVertical, {~0, 0}, 5); - - colorEmulation.setChecked(config->video.colorEmulation); - saturation.slider.setPosition(config->video.saturation); - gamma.slider.setPosition(config->video.gamma - 100); - luminance.slider.setPosition(config->video.luminance); - overscanHorizontal.slider.setPosition(config->video.maskOverscan.horizontal); - overscanVertical.slider.setPosition(config->video.maskOverscan.vertical); - - synchronize(); - - saturation.slider.onChange = gamma.slider.onChange = luminance.slider.onChange = colorEmulation.onToggle = - overscanHorizontal.slider.onChange = overscanVertical.slider.onChange = - {&VideoSettings::synchronize, this}; -} - -void VideoSettings::synchronize() { - config->video.saturation = saturation.slider.position(); - config->video.gamma = 100 + gamma.slider.position(); - config->video.luminance = luminance.slider.position(); - config->video.colorEmulation = colorEmulation.checked(); - config->video.maskOverscan.horizontal = overscanHorizontal.slider.position(); - config->video.maskOverscan.vertical = overscanVertical.slider.position(); - - saturation.value.setText({config->video.saturation, "%"}); - gamma.value.setText({config->video.gamma, "%"}); - luminance.value.setText({config->video.luminance, "%"}); - overscanHorizontal.value.setText({config->video.maskOverscan.horizontal, "px"}); - overscanVertical.value.setText({config->video.maskOverscan.vertical, "px"}); - - utility->updatePalette(); -} diff --git a/target-higan/settings/video.hpp b/target-higan/settings/video.hpp deleted file mode 100644 index 3e47f882..00000000 --- a/target-higan/settings/video.hpp +++ /dev/null @@ -1,23 +0,0 @@ -struct VideoSlider : HorizontalLayout { - Label name; - Label value; - HorizontalSlider slider; - - VideoSlider(); -}; - -struct VideoSettings : SettingsLayout { - Label colorAdjustment; - VideoSlider saturation; - VideoSlider gamma; - VideoSlider luminance; - CheckLabel colorEmulation; - Label overscanAdjustment; - VideoSlider overscanHorizontal; - VideoSlider overscanVertical; - - void synchronize(); - VideoSettings(); -}; - -extern VideoSettings* videoSettings; diff --git a/target-higan/tools/cheat-database.cpp b/target-higan/tools/cheat-database.cpp deleted file mode 100644 index 5063188a..00000000 --- a/target-higan/tools/cheat-database.cpp +++ /dev/null @@ -1,68 +0,0 @@ -CheatDatabase* cheatDatabase = nullptr; - -CheatDatabase::CheatDatabase() { - setGeometry({256, 256, 600, 360}); - windowManager->append(this, "CheatDatabase"); - - layout.setMargin(5); - cheatList.setCheckable(); - selectAllButton.setText("Select All"); - unselectAllButton.setText("Unselect All"); - acceptButton.setText("Add Codes"); - - append(layout); - layout.append(cheatList, {~0, ~0}, 5); - layout.append(controlLayout, {~0, 0}); - controlLayout.append(selectAllButton, {100, 0}, 5); - controlLayout.append(unselectAllButton, {100, 0}, 5); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(acceptButton, {80, 0}); - - selectAllButton.onActivate = [&] { - for(unsigned n = 0; n < cheat.size(); n++) cheatList.setChecked(n, true); - }; - - unselectAllButton.onActivate = [&] { - for(unsigned n = 0; n < cheat.size(); n++) cheatList.setChecked(n, false); - }; - - acceptButton.onActivate = {&CheatDatabase::addCodes, this}; -} - -void CheatDatabase::findCodes() { - const string sha256 = system().sha256(); - cheatList.reset(); - cheat.reset(); - - auto document = Markup::Document(string::read(program->path("cheats.bml"))); - for(auto& node : document) { - if(node.name != "cartridge") continue; - if(node["sha256"].text() != sha256) continue; - - setTitle(node["name"].text()); - for(auto& cheat : node) { - if(cheat.name != "cheat") continue; - cheatList.append(cheat["description"].text()); - this->cheat.append({cheat["code"].text(), cheat["description"].text()}); - } - - setVisible(); - return; - } - - MessageWindow().setParent(*tools).setText("Sorry, no cheat codes were found.").information(); -} - -void CheatDatabase::addCodes() { - for(unsigned n = 0; n < cheat.size(); n++) { - if(cheatList.checked(n) == false) continue; - if(cheatEditor->import(cheat[n].code, cheat[n].desc) == false) { - MessageWindow().setParent(*this).setText("Ran out of empty slots for cheat codes.\nNot all cheat codes were added.").warning(); - break; - } - } - - setVisible(false); - cheatEditor->synchronize(); - cheatEditor->refresh(); -} diff --git a/target-higan/tools/cheat-database.hpp b/target-higan/tools/cheat-database.hpp deleted file mode 100644 index 3d0ea5d1..00000000 --- a/target-higan/tools/cheat-database.hpp +++ /dev/null @@ -1,22 +0,0 @@ -struct CheatDatabase : Window { - VerticalLayout layout; - ListView cheatList; - HorizontalLayout controlLayout; - Button selectAllButton; - Button unselectAllButton; - Widget spacer; - Button acceptButton; - - void findCodes(); - void addCodes(); - CheatDatabase(); - -private: - struct Cheat { - string code; - string desc; - }; - vector<Cheat> cheat; -}; - -extern CheatDatabase* cheatDatabase; diff --git a/target-higan/tools/cheat-editor.cpp b/target-higan/tools/cheat-editor.cpp deleted file mode 100644 index 010b8da8..00000000 --- a/target-higan/tools/cheat-editor.cpp +++ /dev/null @@ -1,178 +0,0 @@ -CheatEditor* cheatEditor = nullptr; - -CheatEditor::CheatEditor() { - cheatList.setHeaderText({"Slot", "Code", "Description"}); - cheatList.setHeaderVisible(); - cheatList.setCheckable(); - for(unsigned n = 0; n < Codes; n++) cheatList.append({"", "", ""}); - codeLabel.setText("Code(s):"); - descLabel.setText("Description:"); - findButton.setText("Find Codes ..."); - resetButton.setText("Reset"); - eraseButton.setText("Erase"); - unsigned width = max( - Font::size(program->normalFont, "Codes(s)" ).width, - Font::size(program->normalFont, "Description:").width - ); - - append(cheatList, {~0, ~0}, 5); - append(codeLayout, {~0, 0}, 5); - codeLayout.append(codeLabel, {width, 0}, 5); - codeLayout.append(codeEdit, {~0, 0}); - append(descLayout, {~0, 0}, 5); - descLayout.append(descLabel, {width, 0}, 5); - descLayout.append(descEdit, {~0, 0}); - append(controlLayout, {~0, 0}); - controlLayout.append(findButton, {0, 0}, 5); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(resetButton, {80, 0}, 5); - controlLayout.append(eraseButton, {80, 0}); - - cheatList.onChange = {&CheatEditor::synchronize, this}; - cheatList.onToggle = [&](unsigned) { update(); }; - codeEdit.onChange = {&CheatEditor::updateCode, this}; - descEdit.onChange = {&CheatEditor::updateDesc, this}; - findButton.onActivate = {&CheatDatabase::findCodes, cheatDatabase}; - resetButton.onActivate = [&] { - if(MessageWindow().setParent(*tools).setText("All codes will be erased. Are you sure you want to do this?") - .question() == MessageWindow::Response::Yes) reset(); - }; - eraseButton.onActivate = {&CheatEditor::erase, this}; - - cheatList.setSelection(0); - synchronize(); -} - -void CheatEditor::synchronize() { - setEnabled(program->active); - - if(cheatList.selected()) { - unsigned n = cheatList.selection(); - codeEdit.setText(cheat[n].code); - descEdit.setText(cheat[n].desc); - codeEdit.setEnabled(true); - descEdit.setEnabled(true); - eraseButton.setEnabled(true); - } else { - codeEdit.setText(""); - descEdit.setText(""); - codeEdit.setEnabled(false); - descEdit.setEnabled(false); - eraseButton.setEnabled(false); - } -} - -void CheatEditor::refresh() { - for(unsigned n = 0; n < Codes; n++) { - string code = cheat[n].code; - string desc = cheat[n].code.empty() && cheat[n].desc.empty() ? "(empty)" : cheat[n].desc; - lstring codes = code.split("+"); - if(codes.size() > 1) code = {codes[0], "+..."}; - cheatList.setText(n, {format<3>(1 + n), code, desc}); - } - cheatList.autoSizeColumns(); -} - -void CheatEditor::update() { - lstring codes; - for(unsigned n = 0; n < Codes; n++) { - string code = cheat[n].code; - if(cheatList.checked(n) && !code.empty()) codes.append(code); - } - system().cheatSet(codes); -} - -void CheatEditor::reset() { - for(unsigned n = 0; n < Codes; n++) { - cheatList.setChecked(n, false); - cheat[n].code = ""; - cheat[n].desc = ""; - } - codeEdit.setText(""); - descEdit.setText(""); - refresh(); - update(); -} - -void CheatEditor::erase() { - unsigned n = cheatList.selection(); - cheatList.setChecked(n, false); - cheat[n].code = ""; - cheat[n].desc = ""; - codeEdit.setText(""); - descEdit.setText(""); - refresh(); - update(); -} - -void CheatEditor::updateCode() { - unsigned n = cheatList.selection(); - cheat[n].code = codeEdit.text(); - refresh(); - update(); -} - -void CheatEditor::updateDesc() { - unsigned n = cheatList.selection(); - cheat[n].desc = descEdit.text(); - refresh(); -} - -bool CheatEditor::load(string filename) { - string data = string::read(filename); - if(data.empty()) return false; - - unsigned n = 0; - auto document = Markup::Document(data); - for(auto& node : document["cartridge"]) { - if(node.name != "cheat") continue; - cheatList.setChecked(n, node["enabled"].exists()); - cheat[n].code = node["code"].text(); - cheat[n].desc = node["description"].text(); - if(++n >= Codes) break; - } - - refresh(); - update(); - return true; -} - -bool CheatEditor::save(string filename) { - signed lastSave = -1; - for(signed n = 127; n >= 0; n--) { - if(!cheat[n].code.empty() || !cheat[n].desc.empty()) { - lastSave = n; - break; - } - } - - if(lastSave == -1) { - file::remove(filename); - return true; - } - - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - - fp.print("cartridge sha256:", system().sha256(), "\n"); - for(unsigned n = 0; n <= lastSave; n++) { - fp.print(" cheat", cheatList.checked(n) ? " enabled\n" : "\n"); - fp.print(" description:", cheat[n].desc, "\n"); - fp.print(" code:", cheat[n].code, "\n"); - } - fp.close(); - - return true; -} - -bool CheatEditor::import(string code, string desc) { - for(unsigned n = 0; n < Codes; n++) { - if(cheat[n].code.empty() && cheat[n].desc.empty()) { - cheatList.setChecked(n, false); - cheat[n].code = code; - cheat[n].desc = desc; - return true; - } - } - return false; -} diff --git a/target-higan/tools/cheat-editor.hpp b/target-higan/tools/cheat-editor.hpp deleted file mode 100644 index 0a35317c..00000000 --- a/target-higan/tools/cheat-editor.hpp +++ /dev/null @@ -1,38 +0,0 @@ -struct CheatEditor : ToolsLayout { - ListView cheatList; - HorizontalLayout codeLayout; - Label codeLabel; - LineEdit codeEdit; - HorizontalLayout descLayout; - Label descLabel; - LineEdit descEdit; - HorizontalLayout controlLayout; - Button findButton; - Widget spacer; - Button resetButton; - Button eraseButton; - - void reset(); - void erase(); - void updateCode(); - void updateDesc(); - - bool load(string filename); - bool save(string filename); - bool import(string code, string desc); - - void update(); - void refresh(); - void synchronize(); - CheatEditor(); - -private: - enum : unsigned { Codes = 128 }; - struct Cheat { - string code; - string desc; - }; - Cheat cheat[Codes]; -}; - -extern CheatEditor* cheatEditor; diff --git a/target-higan/tools/state-manager.cpp b/target-higan/tools/state-manager.cpp deleted file mode 100644 index fde3cb96..00000000 --- a/target-higan/tools/state-manager.cpp +++ /dev/null @@ -1,153 +0,0 @@ -StateManager* stateManager = nullptr; - -StateManager::StateManager() { - stateList.setHeaderText({"Slot", "Description"}); - stateList.setHeaderVisible(); - for(unsigned n = 0; n < Slots; n++) stateList.append({format<2>(1 + n), "(empty)"}); - stateList.autoSizeColumns(); - descLabel.setText("Description:"); - saveButton.setText("Save"); - loadButton.setText("Load"); - resetButton.setText("Reset"); - eraseButton.setText("Erase"); - - append(stateList, {~0, ~0}, 5); - append(descLayout, {~0, 0}, 5); - descLayout.append(descLabel, {0, 0}, 5); - descLayout.append(descEdit, {~0, 0}); - append(controlLayout, {~0, 0}); - controlLayout.append(saveButton, {80, 0}, 5); - controlLayout.append(loadButton, {80, 0}, 5); - controlLayout.append(spacer, {~0, 0}); - controlLayout.append(resetButton, {80, 0}, 5); - controlLayout.append(eraseButton, {80, 0}); - - stateList.onChange = {&StateManager::synchronize, this}; - stateList.onActivate = {&StateManager::slotLoad, this}; - descEdit.onChange = {&StateManager::slotSaveDescription, this}; - saveButton.onActivate = {&StateManager::slotSave, this}; - loadButton.onActivate = {&StateManager::slotLoad, this}; - resetButton.onActivate = [&] { - if(MessageWindow().setParent(*tools).setText("All states will be erased. Are you sure you want to do this?") - .question() == MessageWindow::Response::Yes) reset(); - }; - eraseButton.onActivate = {&StateManager::slotErase, this}; - - stateList.setSelection(0); - synchronize(); -} - -void StateManager::synchronize() { - setEnabled(program->active); - - descEdit.setText(""); - descEdit.setEnabled(false); - controlLayout.setEnabled(stateList.selected()); - if(stateList.selected() == false) return; - - if(slot[stateList.selection()].capacity() > 0) { - descEdit.setText(slotLoadDescription(stateList.selection())); - descEdit.setEnabled(true); - } -} - -void StateManager::refresh() { - for(unsigned n = 0; n < Slots; n++) { - stateList.setText(n, {format<2>(1 + n), slotLoadDescription(n)}); - } - stateList.autoSizeColumns(); -} - -void StateManager::reset() { - for(auto& slot : this->slot) slot = serializer(); - synchronize(); - refresh(); -} - -bool StateManager::load(string filename, unsigned revision) { - for(auto& slot : this->slot) slot = serializer(); - synchronize(); - - file fp; - if(fp.open(filename, file::mode::read) == false) return false; - - if(fp.readl(4) == 0x31415342 /* 'BSA1' */ && fp.readl(4) == revision) { - for(auto &slot : this->slot) { - if(fp.read() == false) continue; //slot is empty - unsigned size = fp.readl(4); - uint8_t* data = new uint8_t[size]; - fp.read(data, size); - slot = serializer(data, size); - delete[] data; - } - } - - refresh(); - synchronize(); - return true; -} - -bool StateManager::save(string filename, unsigned revision) { - bool hasSave = false; - for(auto& slot : this->slot) hasSave |= slot.capacity() > 0; - if(hasSave == false) { - file::remove(filename); - return true; - } - - directory::create(dir(filename)); - - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - - fp.writel(0x31415342, 4); //'BSA1' - fp.writel(revision, 4); - for(auto& slot : this->slot) { - fp.write(slot.capacity() > 0); - if(slot.capacity()) { - fp.writel(slot.capacity(), 4); - fp.write(slot.data(), slot.capacity()); - } - } - - return true; -} - -void StateManager::slotLoad() { - if(stateList.selected() == false) return; - serializer s(slot[stateList.selection()].data(), slot[stateList.selection()].capacity()); - system().unserialize(s); -} - -void StateManager::slotSave() { - if(stateList.selected()) { - slot[stateList.selection()] = system().serialize(); - } - refresh(); - synchronize(); - descEdit.setFocused(); -} - -void StateManager::slotErase() { - if(stateList.selected()) { - slot[stateList.selection()] = serializer(); - } - refresh(); - synchronize(); -} - -string StateManager::slotLoadDescription(unsigned id) { - if(slot[id].capacity() == 0) return "(empty)"; - char text[DescriptionLength]; - strmcpy(text, (const char*)slot[id].data() + HeaderLength, DescriptionLength); - return text; -} - -void StateManager::slotSaveDescription() { - if(stateList.selected() == false) return; - string text = descEdit.text(); - if(slot[stateList.selection()].capacity() > 0) { - strmcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, DescriptionLength); - } - refresh(); -} diff --git a/target-higan/tools/state-manager.hpp b/target-higan/tools/state-manager.hpp deleted file mode 100644 index daf06001..00000000 --- a/target-higan/tools/state-manager.hpp +++ /dev/null @@ -1,36 +0,0 @@ -struct StateManager : ToolsLayout { - ListView stateList; - HorizontalLayout descLayout; - Label descLabel; - LineEdit descEdit; - HorizontalLayout controlLayout; - Button saveButton; - Button loadButton; - Widget spacer; - Button resetButton; - Button eraseButton; - - void reset(); - bool load(string filename, unsigned revision); - bool save(string filename, unsigned revision); - - void slotLoad(); - void slotSave(); - void slotErase(); - string slotLoadDescription(unsigned id); - void slotSaveDescription(); - - void refresh(); - void synchronize(); - StateManager(); - -private: - enum : unsigned { - Slots = 32, - HeaderLength = 72, - DescriptionLength = 512, - }; - serializer slot[Slots]; -}; - -extern StateManager* stateManager; diff --git a/target-higan/tools/tools.cpp b/target-higan/tools/tools.cpp deleted file mode 100644 index 894b7d9b..00000000 --- a/target-higan/tools/tools.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "../higan.hpp" -#include "cheat-database.cpp" -#include "cheat-editor.cpp" -#include "state-manager.cpp" -Tools* tools = nullptr; - -ToolsLayout::ToolsLayout() { - setMargin(5); -} - -Tools::Tools() { - setGeometry({128, 128, 640, 360}); - windowManager->append(this, "Tools"); - - setTitle("Tools"); - - layout.setMargin(5); - panels.append("Cheat Editor", {resource::cheatEditor, sizeof resource::cheatEditor}); - panels.append("State Manager", {resource::stateManager, sizeof resource::stateManager}); - panels.setLayout(0, *cheatEditor); - panels.setLayout(1, *stateManager); - - append(layout); - layout.append(panels, {~0, ~0}); -} diff --git a/target-higan/tools/tools.hpp b/target-higan/tools/tools.hpp deleted file mode 100644 index 06680369..00000000 --- a/target-higan/tools/tools.hpp +++ /dev/null @@ -1,16 +0,0 @@ -struct ToolsLayout : VerticalLayout { - ToolsLayout(); -}; - -#include "cheat-database.hpp" -#include "cheat-editor.hpp" -#include "state-manager.hpp" - -struct Tools : Window { - VerticalLayout layout; - TabFrame panels; - - Tools(); -}; - -extern Tools* tools; diff --git a/target-higan/utility/utility.cpp b/target-higan/utility/utility.cpp deleted file mode 100644 index 2645092a..00000000 --- a/target-higan/utility/utility.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "../higan.hpp" - -Utility* utility = nullptr; - -void Utility::setInterface(Emulator::Interface* emulator) { - program->active = emulator; - presentation->synchronize(); -} - -//load from command-line, etc -void Utility::loadMedia(string pathname) { - pathname.transform("\\", "/"); - if(pathname.endsWith("/")) pathname.rtrim("/"); - - if(!directory::exists(pathname)) return; - string type = extension(pathname); - - //determine type by comparing extension against all emulation cores - for(auto& emulator : program->emulator) { - for(auto& media : emulator->media) { - if(media.bootable == false) continue; - if(type != media.type) continue; - loadMedia(emulator, media, {pathname, "/"}); - libraryManager->setVisible(false); - return; - } - } - - MessageWindow().setText("Unable to determine media type.").warning(); -} - -//load base cartridge -void Utility::loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname) { - unload(); - setInterface(emulator); - path(0) = program->path({media.name, ".sys/"}); - path(media.id) = pathname; - this->pathname.append(pathname); - - system().load(media.id); - system().power(); - - presentation->setSystemName(media.name); - presentation->setVisible(); - load(); -} - -//request from emulation core to load non-volatile media folder -void Utility::loadRequest(unsigned id, string name, string type) { - string pathname = libraryManager->load(type); - if(pathname.empty()) return; - path(id) = pathname; - this->pathname.append(pathname); - - system().load(id); -} - -//request from emulation core to load non-volatile media file -void Utility::loadRequest(unsigned id, string path) { - string pathname = {this->path(system().group(id)), path}; - if(file::exists(pathname) == false) return; - mmapstream stream(pathname); - return system().load(id, stream); -} - -//request from emulation core to save non-volatile media file -void Utility::saveRequest(unsigned id, string path) { - string pathname = {this->path(system().group(id)), path}; - filestream stream(pathname, file::mode::write); - return system().save(id, stream); -} - -void Utility::connect(unsigned port, unsigned device) { - if(program->active == nullptr) return; - system().connect(port, device); -} - -void Utility::power() { - if(program->active == nullptr) return; - system().power(); -} - -void Utility::reset() { - if(program->active == nullptr) return; - system().reset(); -} - -void Utility::load() { - presentation->setTitle(system().title()); - - cheatEditor->load({pathname[0], "cheats.bml"}); - stateManager->load({pathname[0], "higan/states.bsa"}, 1); - - synchronizeDSP(); - - resize(); - updateShader(); - cheatEditor->synchronize(); - cheatEditor->refresh(); -} - -void Utility::unload() { - if(program->active == nullptr) return; - - cheatEditor->save({pathname[0], "cheats.bml"}); - stateManager->save({pathname[0], "higan/states.bsa"}, 1); - - system().unload(); - path.reset(); - pathname.reset(); - cheatEditor->reset(); - stateManager->reset(); - setInterface(nullptr); - - video.clear(); - audio.clear(); - presentation->setTitle({Emulator::Name, " v", Emulator::Version}); - cheatDatabase->setVisible(false); - cheatEditor->setVisible(false); - stateManager->setVisible(false); -} - -void Utility::saveState(unsigned slot) { - if(program->active == nullptr) return; - serializer s = system().serialize(); - if(s.size() == 0) return; - directory::create({pathname[0], "higan/"}); - if(file::write({pathname[0], "higan/state-", slot, ".bsa"}, s.data(), s.size()) == false); - showMessage({"Saved to slot ", slot}); -} - -void Utility::loadState(unsigned slot) { - if(program->active == nullptr) return; - auto memory = file::read({pathname[0], "higan/state-", slot, ".bsa"}); - if(memory.size() == 0) return showMessage({"Unable to locate slot ", slot, " state"}); - serializer s(memory.data(), memory.size()); - if(system().unserialize(s) == false) return showMessage({"Slot ", slot, " state incompatible"}); - showMessage({"Loaded from slot ", slot}); -} - -void Utility::synchronizeDSP() { - if(program->active == nullptr) return; - - if(config->video.synchronize == false) { - return dspaudio.setFrequency(system().audioFrequency()); - } - - double inputRatio = system().audioFrequency() / system().videoFrequency(); - double outputRatio = config->timing.audio / config->timing.video; - double frequency = inputRatio / outputRatio * config->audio.frequency; - - dspaudio.setFrequency(frequency); -} - -void Utility::synchronizeRuby() { - video.set(Video::Synchronize, config->video.synchronize); - audio.set(Audio::Synchronize, config->audio.synchronize); - audio.set(Audio::Frequency, config->audio.frequency); - audio.set(Audio::Latency, config->audio.latency); - - switch(config->audio.resampler) { - case 0: dspaudio.setResampler(DSP::ResampleEngine::Linear); break; - case 1: dspaudio.setResampler(DSP::ResampleEngine::Hermite); break; - case 2: dspaudio.setResampler(DSP::ResampleEngine::Sinc); break; - } - dspaudio.setResamplerFrequency(config->audio.frequency); - dspaudio.setVolume(config->audio.mute ? 0.0 : config->audio.volume * 0.01); - synchronizeDSP(); -} - -void Utility::updatePalette() { - if(program->active == nullptr) return; - - if(config->video.shader == "Display Emulation" && config->video.driver == "OpenGL") { - system().paletteUpdate(Emulator::Interface::PaletteMode::Channel); - } else if(config->video.colorEmulation) { - system().paletteUpdate(Emulator::Interface::PaletteMode::Emulation); - } else { - system().paletteUpdate(Emulator::Interface::PaletteMode::Standard); - } -} - -void Utility::updateShader() { - if(config->video.shader == "None") { - video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, Video::FilterNearest); - } else if(config->video.shader == "Blur") { - video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, Video::FilterLinear); - } else if(config->video.shader == "Display Emulation" && config->video.driver != "OpenGL") { - video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, Video::FilterLinear); - } else if(config->video.shader == "Display Emulation") { - if(program->active) { - string pathname = program->path("Video Shaders/"); - pathname.append("Display Emulation/"); - pathname.append(presentation->systemName, ".shader/"); - if(directory::exists(pathname)) { - video.set(Video::Shader, (const char*)pathname); - } else { - video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, Video::FilterLinear); - } - } else { - video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, Video::FilterLinear); - } - } else { - video.set(Video::Shader, (const char*)config->video.shader); - } - updatePalette(); -} - -void Utility::resize(bool resizeWindow) { - if(program->active == nullptr) { - auto geometry = presentation->geometry(); - presentation->viewport.setGeometry({0, 0, geometry.width, geometry.height}); - return; - } - - Geometry geometry = presentation->geometry(); - unsigned width = system().information.width; - unsigned height = system().information.height; - - unsigned scaledWidth = geometry.width / width; - unsigned scaledHeight = geometry.height / height; - unsigned multiplier = max(1u, min(scaledWidth, scaledHeight)); - - if(config->video.aspectCorrection) { - width *= system().information.aspectRatio; - } - - width *= multiplier; - height *= multiplier; - - unsigned scaleMode = 0; - - if(config->video.scaleMode == 1) { - width = (double)width * ((double)geometry.height / height); - height = geometry.height; - } - - if(config->video.scaleMode == 2) { - width = geometry.width; - height = geometry.height; - } - - if(resizeWindow == false) { - if(geometry.width < width ) width = geometry.width; - if(geometry.height < height) height = geometry.height; - - presentation->viewport.setGeometry({ - (geometry.width - width) / 2, (geometry.height - height) / 2, width, height - }); - } else { - presentation->setGeometry({geometry.x, geometry.y, width, height}); - presentation->viewport.setGeometry({0, 0, width, height}); - } - - presentation->synchronize(); -} - -void Utility::toggleFullScreen() { - static Geometry geometry; - - if(presentation->fullScreen() == false) { - geometry = presentation->geometry(); - presentation->setMenuVisible(false); - presentation->setStatusVisible(false); - presentation->setFullScreen(true); - input.acquire(); - } else { - input.unacquire(); - presentation->setMenuVisible(true); - presentation->setStatusVisible(true); - presentation->setFullScreen(false); - presentation->setGeometry(geometry); - } - - resize(); -} - -void Utility::updateStatus() { - time_t currentTime = time(0); - string text; - if((currentTime - statusTime) <= 2) { - text = statusMessage; - } else if(program->active == nullptr) { - text = "No cartridge loaded"; - } else if(program->pause || program->autopause) { - text = "Paused"; - } else { - text = statusText; - } - if(text != presentation->statusText()) { - presentation->setStatusText(text); - } -} - -void Utility::setStatusText(string text) { - statusText = text; -} - -void Utility::showMessage(string message) { - statusTime = time(0); - statusMessage = message; -} - -string Utility::libraryPath() { - string path = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/"); - if(path.empty()) path = {userpath(), "Emulation/"}; - if(path.endsWith("/") == false) path.append("/"); - return path; -} diff --git a/target-higan/utility/utility.hpp b/target-higan/utility/utility.hpp deleted file mode 100644 index 5b3fb92c..00000000 --- a/target-higan/utility/utility.hpp +++ /dev/null @@ -1,42 +0,0 @@ -struct Utility { - void setInterface(Emulator::Interface* emulator); - - void loadMedia(string pathname); - void loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname); - - void loadRequest(unsigned id, string name, string type); - void loadRequest(unsigned id, string path); - void saveRequest(unsigned id, string path); - - void connect(unsigned port, unsigned device); - void power(); - void reset(); - void load(); - void unload(); - - void saveState(unsigned slot); - void loadState(unsigned slot); - - void synchronizeDSP(); - void synchronizeRuby(); - void updatePalette(); - void updateShader(); - void resize(bool resizeWindow = false); - void toggleFullScreen(); - - void updateStatus(); - void setStatusText(string text); - void showMessage(string message); - - string libraryPath(); - - lstring path; - lstring pathname; - -private: - string statusText; - string statusMessage; - time_t statusTime = 0; -}; - -extern Utility* utility; diff --git a/target-higan/window/window.cpp b/target-higan/window/window.cpp deleted file mode 100644 index 582f3817..00000000 --- a/target-higan/window/window.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "../higan.hpp" -WindowManager* windowManager = nullptr; - -void WindowManager::append(Window* window, string name) { - window->setMenuFont(program->normalFont); - window->setWidgetFont(program->normalFont); - window->setStatusFont(program->boldFont); - windowList.append({window, name, window->geometry().text()}); -} - -void WindowManager::loadGeometry() { - static bool initialized = false; - if(initialized == false) { - initialized = true; - Configuration::Node geometry; - for(auto& window : windowList) { - geometry.append(window.geometry, window.name); - } - config.append(geometry, "Geometry"); - } - config.load(program->path("geometry.bml")); - config.save(program->path("geometry.bml")); - for(auto& window : windowList) { - window.window->setGeometry(window.geometry); - } -} - -void WindowManager::saveGeometry() { - for(auto& window : windowList) { - window.geometry = window.window->geometry().text(); - } - config.save(program->path("geometry.bml")); -} - -void WindowManager::hideAll() { - for(auto& window : windowList) { - window.window->setVisible(false); - } -} diff --git a/target-higan/window/window.hpp b/target-higan/window/window.hpp deleted file mode 100644 index caa81e5d..00000000 --- a/target-higan/window/window.hpp +++ /dev/null @@ -1,18 +0,0 @@ -struct WindowManager { - struct WindowList { - Window* window; - string name; - string geometry; - }; - vector<WindowList> windowList; - - void append(Window* window, string name); - void loadGeometry(); - void saveGeometry(); - void hideAll(); - -private: - Configuration::Document config; -}; - -extern WindowManager* windowManager; diff --git a/target-loki/Makefile b/target-loki/Makefile deleted file mode 100644 index 28b9d9be..00000000 --- a/target-loki/Makefile +++ /dev/null @@ -1,96 +0,0 @@ -name := loki - -processors := arm gsu hg51b lr35902 r65816 spc700 upd96050 -include processor/Makefile - -include sfc/Makefile -include gb/Makefile - -ui_objects := ui-loki ui-settings ui-input -ui_objects += ui-interface ui-debugger -ui_objects += ui-presentation ui-terminal -ui_objects += ruby phoenix -ui_objects += $(if $(call streq,$(platform),windows),resource) - -ifeq ($(platform),windows) - ruby := video.wgl audio.xaudio2 input.windows -else ifeq ($(platform),macosx) - ruby := video.cgl audio.openal input.carbon -else ifeq ($(platform),linux) - ruby := video.glx audio.alsa input.udev -else ifeq ($(platform),bsd) - ruby := video.glx audio.openal input.x -endif - -include ruby/Makefile -link += $(rubylink) - -include phoenix/Makefile -link += $(phoenixlink) - -objects := $(ui_objects) $(objects) -objects := $(patsubst %,obj/%.o,$(objects)) - -obj/ui-loki.o: $(ui)/loki.cpp $(call rwildcard,$(ui)/) -obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/) -obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/) -obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/) -obj/ui-debugger.o: $(ui)/debugger/debugger.cpp $(call rwildcard,$(ui)/) -obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/) -obj/ui-terminal.o: $(ui)/terminal/terminal.cpp $(call rwildcard,$(ui)/) - -obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/) - $(compiler) $(rubyflags) -c $< -o $@ - -obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/) - $(compiler) $(phoenixflags) -c $< -o $@ - -obj/resource.o: $(ui)/resource.rc -ifeq ($(arch),win32) - windres --target=pe-i386 $(ui)/resource.rc obj/resource.o -else - windres $(ui)/resource.rc obj/resource.o -endif - -build: $(objects) -ifeq ($(platform),windows) - $(strip $(compiler) -shared -o out/phoenix.dll obj/phoenix.o $(phoenixlink)) - $(strip $(compiler) -o out/$(name) $(subst obj/phoenix.o,,$(objects)) $(link) -Lout -lphoenix) -else ifeq ($(platform),macosx) - if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi - mkdir out/$(name).app - mkdir out/$(name).app/Contents - mkdir out/$(name).app/Contents/MacOS - mkdir out/$(name).app/Contents/Resources - cp data/Info.plist out/$(name).app/Contents/Info.plist - $(strip $(compiler) -o out/$(name).app/Contents/MacOS/$(name) $(objects) $(link)) -else - $(strip $(compiler) -o out/$(name) $(objects) $(link)) -endif - -resource: - sourcery $(ui)/resource/resource.bml $(ui)/resource/resource.cpp $(ui)/resource/resource.hpp - -install: -ifneq ($(shell id -un),root) - $(error "make install must be run as root") -else ifeq ($(platform),windows) -else ifeq ($(platform),macosx) - mkdir -p /Library/Application\ Support/$(name) - cp -R profile/* /Library/Application\ Support/$(name) - chmod -R 777 /Library/Application\ Support/$(name) -else - cp out/$(name) $(prefix)/bin/$(name) - mkdir -p /usr/share/$(name) - cp -R profile/* /usr/share/$(name) - chmod -R 777 /usr/share/$(name) -endif - -uninstall: -ifneq ($(shell id -un),root) - $(error "make uninstall must be run as root") -else ifeq ($(platform),windows) -else ifeq ($(platform),macosx) -else - rm $(prefix)/bin/$(name) -endif diff --git a/target-loki/debugger/debugger.cpp b/target-loki/debugger/debugger.cpp deleted file mode 100644 index 200681fa..00000000 --- a/target-loki/debugger/debugger.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include "../loki.hpp" -Debugger* debugger = nullptr; - -Debugger::Debugger() { - debugger = this; - SFC::cpu.debugger.op_exec = {&Debugger::cpuExec, this}; - SFC::cpu.debugger.op_read = {&Debugger::cpuRead, this}; - SFC::cpu.debugger.op_write = {&Debugger::cpuWrite, this}; - SFC::smp.debugger.op_exec = {&Debugger::smpExec, this}; - SFC::smp.debugger.op_read = {&Debugger::smpRead, this}; - SFC::smp.debugger.op_write = {&Debugger::smpWrite, this}; - SFC::ppu.debugger.vram_read = {&Debugger::ppuVramRead, this}; - SFC::ppu.debugger.vram_write = {&Debugger::ppuVramWrite, this}; - SFC::ppu.debugger.oam_read = {&Debugger::ppuOamRead, this}; - SFC::ppu.debugger.oam_write = {&Debugger::ppuOamWrite, this}; - SFC::ppu.debugger.cgram_read = {&Debugger::ppuCgramRead, this}; - SFC::ppu.debugger.cgram_write = {&Debugger::ppuCgramWrite, this}; -} - -void Debugger::load() { - directory::create({interface->pathname, "loki/"}); - - cpuUsage = new uint8[0x1000000](); - apuUsage = new uint8[0x10000](); - file fp; - - if(fp.open({interface->pathname, "loki/cpu.usage.map"}, file::mode::read)) { - if(fp.size() == 0x1000000) fp.read(cpuUsage, 0x1000000); - fp.close(); - } - - if(fp.open({interface->pathname, "loki/apu.usage.map"}, file::mode::read)) { - if(fp.size() == 0x10000) fp.read(apuUsage, 0x10000); - fp.close(); - } -} - -void Debugger::unload() { - if(cpuTracerFile.open()) cpuTracerFile.close(); - if(smpTracerFile.open()) smpTracerFile.close(); - file::write({interface->pathname, "loki/cpu.usage.map"}, cpuUsage, 0x1000000); - file::write({interface->pathname, "loki/apu.usage.map"}, apuUsage, 0x10000); - delete[] cpuUsage; - delete[] apuUsage; - cpuUsage = nullptr; - apuUsage = nullptr; -} - -void Debugger::main() { - if(running == false) { - usleep(20 * 1000); - return; - } - - emulator->run(); -} - -void Debugger::run() { - running = true; -} - -void Debugger::stop() { - running = false; - cpuRunFor = nothing; - cpuRunTo = nothing; - cpuStepFor = nothing; - cpuStepTo = nothing; - smpRunFor = nothing; - smpRunTo = nothing; - smpStepFor = nothing; - smpStepTo = nothing; -} - -void Debugger::leave() { - stop(); - SFC::scheduler.debug(); -} - -bool Debugger::breakpointTest(Source source, Breakpoint::Mode mode, unsigned addr, uint8 data) { - if(savingState) return false; - for(unsigned n = 0; n < breakpoints.size(); n++) { - auto& bp = breakpoints[n]; - if(bp.source != source) continue; - if(bp.mode != mode) continue; - if(bp.addr != addr) continue; - if(bp.mode != Breakpoint::Mode::Execute && bp.data && bp.data() != data) continue; - string output = {"Breakpoint #", n, " hit"}; - if(bp.mode == Breakpoint::Mode::Read ) output.append("; read ", hex<2>(data)); - if(bp.mode == Breakpoint::Mode::Write) output.append("; wrote ", hex<2>(data)); - output.append("; triggered: ", ++bp.triggered); - echo(output, "\n"); - return true; - } - return false; -} - -string Debugger::cpuDisassemble() { - char text[4096]; - SFC::cpu.disassemble_opcode(text); - return {text, " F:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; -} - -string Debugger::cpuDisassemble(unsigned addr, bool e, bool m, bool x) { - char text[4096]; - SFC::cpu.disassemble_opcode(text, addr, e, m, x); - return {text, " F:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; -} - -void Debugger::cpuExec(uint24 addr) { - cpuUsage[addr] |= Usage::Execute; - if(SFC::cpu.regs.e == 0) cpuUsage[addr] &= ~Usage::FlagE; - if(SFC::cpu.regs.p.m == 0) cpuUsage[addr] &= ~Usage::FlagM; - if(SFC::cpu.regs.p.x == 0) cpuUsage[addr] &= ~Usage::FlagX; - if(SFC::cpu.regs.e == 1) cpuUsage[addr] |= Usage::FlagE; - if(SFC::cpu.regs.p.m == 1) cpuUsage[addr] |= Usage::FlagM; - if(SFC::cpu.regs.p.x == 1) cpuUsage[addr] |= Usage::FlagX; - - cpuInstructionCounter++; - - if(cpuTracerFile.open()) { - if(!cpuTracerMask || cpuTracerMask[addr] == false) { - if(cpuTracerMask) cpuTracerMask[addr] = true; - cpuTracerFile.print(cpuDisassemble(), "\n"); - } - } - - if(savingState) return; - - if(breakpointTest(Source::CPU, Breakpoint::Mode::Execute, addr)) { - echo(cpuDisassemble(), "\n"); - return leave(); - } - - if(cpuRunFor) { - if(--cpuRunFor() == 0) { - echo(cpuDisassemble(), "\n"); - return leave(); - } - } - - if(cpuRunTo) { - if(addr == cpuRunTo()) { - echo(cpuDisassemble(), "\n"); - return leave(); - } - } - - if(cpuStepFor) { - echo(cpuDisassemble(), "\n"); - if(--cpuStepFor() == 0) return leave(); - } - - if(cpuStepTo) { - echo(cpuDisassemble(), "\n"); - if(addr == cpuStepTo()) return leave(); - } -} - -void Debugger::cpuRead(uint24 addr, uint8 data) { - cpuUsage[addr] |= Usage::Read; - if(breakpointTest(Source::CPU, Breakpoint::Mode::Read, addr, data)) leave(); -} - -void Debugger::cpuWrite(uint24 addr, uint8 data) { - cpuUsage[addr] |= Usage::Write; - if(breakpointTest(Source::CPU, Breakpoint::Mode::Write, addr, data)) leave(); -} - -void Debugger::echoBreakpoints() { - if(breakpoints.size() == 0) return; - echo("# source type addr data triggered\n"); - echo("--- ------ -------- ------ ---- ---------\n"); - for(unsigned n = 0; n < breakpoints.size(); n++) { - auto& bp = breakpoints[n]; - string output = {format<-3>(n), " "}; - output.append(format<-6>(sourceName(bp.source)), " "); - if(bp.mode == Breakpoint::Mode::Disabled) output.append("disabled "); - if(bp.mode == Breakpoint::Mode::Read ) output.append("read "); - if(bp.mode == Breakpoint::Mode::Write ) output.append("write "); - if(bp.mode == Breakpoint::Mode::Execute ) output.append("execute "); - output.append(hex<6>(bp.addr), " "); - output.append(bp.data ? hex<2>(bp.data()) : " ", " "); - output.append(format<-9>(bp.triggered)); - echo(output, "\n"); - } -} - -void Debugger::echoDisassemble(Source source, unsigned addr, signed size) { - if(source != Source::CPU && source != Source::SMP) return; - const unsigned maximumDisplacement = (source == Source::CPU ? 5 : 4); //maximum opcode length - uint8* usage = (source == Source::CPU ? cpuUsage : apuUsage); - if(!(usage[addr] & Usage::Execute)) return echo("No usage data available for ", sourceName(source), "/", hex<6>(addr), "\n"); - - while(size > 0) { - string text; - if(source == Source::CPU) { - text = cpuDisassemble(addr, usage[addr] & Usage::FlagE, usage[addr] & Usage::FlagM, usage[addr] & Usage::FlagX); - } - if(source == Source::SMP) { - text = smpDisassemble(addr, usage[addr] & Usage::FlagP); - } - text.resize(20); //remove register information - echo(text, "\n"); - if(--size <= 0) break; - - unsigned displacement = 1; - while(displacement < maximumDisplacement) { //maximum opcode length is four bytes - if(usage[addr + displacement] & Usage::Execute) break; - displacement++; - } - if(displacement >= maximumDisplacement) { - echo("...\n"); - return; - } - addr += displacement; - } -} - -void Debugger::echoHex(Source source, unsigned addr, signed size) { - if(memorySize(source) == 0) return; //not a valid memory pool - while(size > 0) { - string hexdata, asciidata; - for(unsigned n = 0; n < 16; n++) { - unsigned offset = addr; - if(source == Source::CPU && ((offset & 0x40e000) == 0x002000 || (offset & 0x40e000) == 0x004000)) { - //$00-3f,80-bf:2000-5fff - //reading MMIO registers can negatively impact emulation, so disallow these reads - hexdata.append("?? "); - asciidata.append("?"); - } else { - uint8 byte = memoryRead(source, addr + n); - hexdata.append(hex<2>(byte), " "); - asciidata.append(byte >= 0x20 && byte <= 0x7e ? (char)byte : '.'); - } - } - echo(hex<6>(addr % memorySize(source)), " [ ", hexdata, "] ", asciidata, "\n"); - addr += 16, size -= 16; - } -} - -void Debugger::memoryExport(Source source, string filename) { - file fp; - if(fp.open(filename, file::mode::write)) { - unsigned size = memorySize(source); - for(unsigned addr = 0; addr < size; addr++) { - fp.write(memoryRead(source, addr)); - } - echo("Exported memory to ", notdir(filename), "\n"); - } -} - -uint8 Debugger::memoryRead(Source source, unsigned addr) { - if(source == Source::CPU) { - return SFC::bus.read(addr & 0xffffff); - } - - if(source == Source::APU) { - return SFC::smp.apuram[addr & 0xffff]; - } - - if(source == Source::WRAM) { - return SFC::cpu.wram[addr & 0x1ffff]; - } - - if(source == Source::VRAM) { - return SFC::ppu.vram[addr & 0xffff]; - } - - if(source == Source::OAM) { - return SFC::ppu.oam[addr % 544]; - } - - if(source == Source::CGRAM) { - return SFC::ppu.cgram[addr & 511]; - } - - return 0x00; -} - -unsigned Debugger::memorySize(Source source) { - switch(source) { - case Source::CPU: return 0x1000000; - case Source::APU: return 0x10000; - case Source::WRAM: return 0x20000; - case Source::VRAM: return 0x10000; - case Source::OAM: return 544; - case Source::CGRAM: return 512; - } - return 0; -} - -void Debugger::memoryWrite(Source source, unsigned addr, uint8 data) { - if(source == Source::CPU) { - SFC::bus.write(addr & 0xffffff, data); - return; - } - - if(source == Source::APU) { - SFC::smp.apuram[addr & 0xffff] = data; - return; - } - - if(source == Source::WRAM) { - SFC::cpu.wram[addr & 0x1ffff] = data; - return; - } - - if(source == Source::VRAM) { - SFC::ppu.vram[addr & 0xffff] = data; - return; - } - - if(source == Source::OAM) { - SFC::ppu.oam[addr % 544] = data; - SFC::ppu.sprite.update(addr % 544, data); - return; - } - - if(source == Source::CGRAM) { - if(addr & 1) data &= 0x7f; - SFC::ppu.cgram[addr] = data; - return; - } -} - -void Debugger::ppuCgramRead(uint16 addr, uint8 data) { - if(breakpointTest(Source::CGRAM, Breakpoint::Mode::Read, addr, data)) leave(); -} - -void Debugger::ppuCgramWrite(uint16 addr, uint8 data) { - if(breakpointTest(Source::CGRAM, Breakpoint::Mode::Write, addr, data)) leave(); -} - -void Debugger::ppuOamRead(uint16 addr, uint8 data) { - if(breakpointTest(Source::OAM, Breakpoint::Mode::Read, addr, data)) leave(); -} - -void Debugger::ppuOamWrite(uint16 addr, uint8 data) { - if(breakpointTest(Source::OAM, Breakpoint::Mode::Write, addr, data)) leave(); -} - -void Debugger::ppuVramRead(uint16 addr, uint8 data) { - if(breakpointTest(Source::VRAM, Breakpoint::Mode::Read, addr, data)) leave(); -} - -void Debugger::ppuVramWrite(uint16 addr, uint8 data) { - if(breakpointTest(Source::VRAM, Breakpoint::Mode::Write, addr, data)) leave(); -} - -string Debugger::smpDisassemble() { - return SFC::smp.disassemble_opcode(SFC::smp.regs.pc, SFC::smp.regs.p.p); -} - -string Debugger::smpDisassemble(uint16 addr, bool p) { - return SFC::smp.disassemble_opcode(addr, p); -} - -void Debugger::smpExec(uint16 addr) { - apuUsage[addr] |= Usage::Execute; - if(SFC::smp.regs.p.p == 0) apuUsage[addr] &= ~Usage::FlagP; - if(SFC::smp.regs.p.p == 1) apuUsage[addr] |= Usage::FlagP; - - smpInstructionCounter++; - - if(smpTracerFile.open()) { - if(!smpTracerMask || smpTracerMask[addr] == false) { - if(smpTracerMask) smpTracerMask[addr] = true; - smpTracerFile.print(smpDisassemble(), "\n"); - } - } - - if(savingState) return; - - if(breakpointTest(Source::SMP, Breakpoint::Mode::Execute, addr)) { - echo(smpDisassemble(), "\n"); - return leave(); - } - - if(smpRunFor) { - if(--smpRunFor() == 0) { - echo(smpDisassemble(), "\n"); - return leave(); - } - } - - if(smpRunTo) { - if(addr == smpRunTo()) { - echo(smpDisassemble(), "\n"); - return leave(); - } - } - - if(smpStepFor) { - echo(smpDisassemble(), "\n"); - if(--smpStepFor() == 0) return leave(); - } - - if(smpStepTo) { - echo(smpDisassemble(), "\n"); - if(addr == smpStepTo()) return leave(); - } -} - -void Debugger::smpRead(uint16 addr, uint8 data) { - apuUsage[addr] |= Usage::Read; - if(breakpointTest(Source::SMP, Breakpoint::Mode::Read, addr, data)) leave(); - if(breakpointTest(Source::APU, Breakpoint::Mode::Read, addr, data)) leave(); -} - -void Debugger::smpWrite(uint16 addr, uint8 data) { - apuUsage[addr] |= Usage::Write; - if(breakpointTest(Source::SMP, Breakpoint::Mode::Write, addr, data)) leave(); - if(breakpointTest(Source::APU, Breakpoint::Mode::Write, addr, data)) leave(); -} - -string Debugger::sourceName(Source source) { - switch(source) { - case Source::CPU: return "cpu"; - case Source::SMP: return "smp"; - case Source::PPU: return "ppu"; - case Source::DSP: return "dsp"; - case Source::APU: return "apu"; - case Source::WRAM: return "wram"; - case Source::VRAM: return "vram"; - case Source::OAM: return "oam"; - case Source::CGRAM: return "cgram"; - } - return "none"; -} - -void Debugger::stateLoad(string filename) { - auto memory = file::read(filename); - if(memory.size() == 0) return echo("Error: state file ", notdir(filename), " not found\n"); - serializer s(memory.data(), memory.size()); - if(emulator->unserialize(s) == false) return echo("Error: failed to unserialize state from ", notdir(filename), "\n"); - echo("State loaded from ", notdir(filename), "\n"); -} - -void Debugger::stateSave(string filename) { - savingState = true; - serializer s = emulator->serialize(); - if(file::write(filename, s.data(), s.size())) { - echo("State saved to ", notdir(filename), "\n"); - } - savingState = false; -} - -void Debugger::tracerDisable(Source source) { - if(source != Source::CPU && source != Source::SMP) return; - file& tracerFile = (source == Source::CPU ? cpuTracerFile : smpTracerFile); - if(tracerFile.open() == false) return; - tracerFile.close(); - echo(sourceName(source).upper(), " tracer disabled\n"); -} - -void Debugger::tracerEnable(Source source, string filename) { - if(source != Source::CPU && source != Source::SMP) return; - file& tracerFile = (source == Source::CPU ? cpuTracerFile : smpTracerFile); - if(tracerFile.open() == true) return; - if(tracerFile.open(filename, file::mode::write)) { - echo(sourceName(source).upper(), " tracer enabled\n"); - } -} - -void Debugger::tracerMaskDisable(Source source) { - if(source != Source::CPU && source != Source::SMP) return; - bitvector& tracerMask = (source == Source::CPU ? cpuTracerMask : smpTracerMask); - tracerMask.reset(); - echo(sourceName(source).upper(), " tracer mask disabled\n"); -} - -void Debugger::tracerMaskEnable(Source source) { - if(source != Source::CPU && source != Source::SMP) return; - bitvector& tracerMask = (source == Source::CPU ? cpuTracerMask : smpTracerMask); - unsigned size = (source == Source::CPU ? 0x1000000 : 0x10000); - tracerMask.resize(size); - tracerMask.clear(); - echo(sourceName(source).upper(), " tracer mask enabled\n"); -} diff --git a/target-loki/debugger/debugger.hpp b/target-loki/debugger/debugger.hpp deleted file mode 100644 index 3ed978cb..00000000 --- a/target-loki/debugger/debugger.hpp +++ /dev/null @@ -1,92 +0,0 @@ -struct Debugger { - enum class Source : unsigned { CPU, SMP, PPU, DSP, APU, WRAM, VRAM, OAM, CGRAM }; - - struct Breakpoint { - Source source = Source::CPU; - enum class Mode : unsigned { Disabled, Read, Write, Execute } mode = Mode::Disabled; - unsigned addr = 0; - maybe<uint8> data; - unsigned triggered = 0; //counter for number of times breakpoint was hit - }; - - struct Usage { - enum : unsigned { - Read = 0x01, - Write = 0x02, - Execute = 0x04, - //CPU - FlagE = 0x08, - FlagM = 0x10, - FlagX = 0x20, - //APU - FlagP = 0x08, - DspRead = 0x10, - DspWrite = 0x20, - }; - }; - - Debugger(); - - void load(); - void unload(); - void main(); - - void run(); - void stop(); - void leave(); - - bool breakpointTest(Source source, Breakpoint::Mode mode, unsigned addr, uint8 data = 0x00); - string cpuDisassemble(); - string cpuDisassemble(unsigned addr, bool e, bool m, bool x); - void cpuExec(uint24 addr); - void cpuRead(uint24 addr, uint8 data); - void cpuWrite(uint24 addr, uint8 data); - void echoBreakpoints(); - void echoDisassemble(Source source, unsigned addr, signed size); - void echoHex(Source source, unsigned addr, signed size); - void memoryExport(Source source, string filename); - uint8 memoryRead(Source source, unsigned addr); - unsigned memorySize(Source source); - void memoryWrite(Source source, unsigned addr, uint8 data); - void ppuCgramRead(uint16 addr, uint8 data); - void ppuCgramWrite(uint16 addr, uint8 data); - void ppuOamRead(uint16 addr, uint8 data); - void ppuOamWrite(uint16 addr, uint8 data); - void ppuVramRead(uint16 addr, uint8 data); - void ppuVramWrite(uint16 addr, uint8 data); - string smpDisassemble(); - string smpDisassemble(uint16 addr, bool p); - void smpExec(uint16 addr); - void smpRead(uint16 addr, uint8 data); - void smpWrite(uint16 addr, uint8 data); - string sourceName(Source source); - void stateLoad(string filename); - void stateSave(string filename); - void tracerDisable(Source source); - void tracerEnable(Source source, string filename); - void tracerMaskDisable(Source source); - void tracerMaskEnable(Source source); - - bool running = false; //emulation runs asynchronously (cooperatively) to terminal commands - bool savingState = false; //suppresses all break events to allow state to be captured synchronously - - uint8* apuUsage = nullptr; - vector<Breakpoint> breakpoints; - unsigned cpuInstructionCounter = 0; - maybe<unsigned> cpuRunFor; - maybe<unsigned> cpuRunTo; - maybe<unsigned> cpuStepFor; - maybe<unsigned> cpuStepTo; - file cpuTracerFile; - bitvector cpuTracerMask; - uint8* cpuUsage = nullptr; - unsigned smpInstructionCounter = 0; - maybe<unsigned> smpRunFor; - maybe<unsigned> smpRunTo; - maybe<unsigned> smpStepFor; - maybe<unsigned> smpStepTo; - file smpTracerFile; - bitvector smpTracerMask; -}; - -extern Debugger* debugger; diff --git a/target-loki/input/input.cpp b/target-loki/input/input.cpp deleted file mode 100644 index a45105a4..00000000 --- a/target-loki/input/input.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "../loki.hpp" -InputManager* inputManager = nullptr; - -void AbstractInput::bind() { - for(auto device : inputManager->devices) { - if(device->isKeyboard() == false) continue; - if(auto group = device->find("Button")) { - if(auto input = device->group[group()].find(mapping)) { - this->device = device; - this->group = group(); - this->input = input(); - break; - } - } - } -} - -int16_t AbstractInput::poll() { - if(device == nullptr) return 0; - return device->group[group].input[input].value; -} - -InputManager::InputManager() { - inputManager = this; -} - -void InputManager::load() { - unsigned guid = 0; - Configuration::Node emulatorNode; - - for(auto& port : emulator->port) { - Configuration::Node portNode; - - for(auto& device : port.device) { - Configuration::Node deviceNode; - - for(auto& number : device.order) { - auto& input = device.input[number]; - input.guid = guid++; - - auto abstract = new AbstractInput; - abstract->name = string{input.name}.replace(" ", ""); - abstract->mapping = "None"; - inputMap.append(abstract); - - deviceNode.append(abstract->mapping, abstract->name); - } - - portNode.append(deviceNode, string{device.name}.replace(" ", "")); - } - - emulatorNode.append(portNode, string{port.name}.replace(" ", "")); - } - - append(emulatorNode, "SuperFamicom"); - - Configuration::Document::load(program->path("input.bml")); - Configuration::Document::save(program->path("input.bml")); -} - -void InputManager::unload() { - Configuration::Document::save(program->path("input.bml")); -} - -void InputManager::bind() { - for(auto input : inputMap) input->bind(); -} - -void InputManager::poll() { - auto devices = input.poll(); - bool changed = devices.size() != this->devices.size(); - if(changed == false) { - for(unsigned n = 0; n < devices.size(); n++) { - changed = devices[n] != this->devices[n]; - if(changed) break; - } - } - if(changed == true) { - this->devices = devices; - bind(); - } -} diff --git a/target-loki/input/input.hpp b/target-loki/input/input.hpp deleted file mode 100644 index d8b84a87..00000000 --- a/target-loki/input/input.hpp +++ /dev/null @@ -1,25 +0,0 @@ -struct AbstractInput { - void bind(); - int16_t poll(); - - string name; - string mapping; - - HID::Device* device = nullptr; - unsigned group = 0; - unsigned input = 0; -}; - -struct InputManager : Configuration::Document { - InputManager(); - void load(); - void unload(); - - void bind(); - void poll(); - - vector<HID::Device*> devices; - vector<AbstractInput*> inputMap; -}; - -extern InputManager* inputManager; diff --git a/target-loki/interface/interface.cpp b/target-loki/interface/interface.cpp deleted file mode 100644 index 388b30db..00000000 --- a/target-loki/interface/interface.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "../loki.hpp" -Interface* interface = nullptr; -SuperFamicom::Interface* emulator = nullptr; - -Interface::Interface() { - interface = this; - emulator = new SuperFamicom::Interface; - emulator->bind = this; -} - -bool Interface::load(string pathname) { - pathname.transform("\\", "/").rtrim("/"); - if(!directory::exists(pathname)) return false; - - string type = extension(pathname); - - for(auto& media : emulator->media) { - if(media.bootable == false) continue; - if(type != media.type) continue; - - this->pathname = pathname.append("/"); - pathnames.reset(); - pathnames(0) = program->path({media.name, ".sys/"}); - pathnames(media.id) = pathname; - echo("Loaded ", pathname, "\n"); - - emulator->load(media.id); - emulator->paletteUpdate(Emulator::Interface::PaletteMode::Standard); - emulator->power(); - presentation->setTitle(emulator->title()); - - return true; - } - - return false; -} - -void Interface::unload() { - emulator->unload(); -} - -//bindings - -void Interface::loadRequest(unsigned id, string name, string type) { -} - -void Interface::loadRequest(unsigned id, string path) { - string pathname = {pathnames(emulator->group(id)), path}; - if(file::exists(pathname) == false) return; - mmapstream stream(pathname); - emulator->load(id, stream); - echo("Loaded ", path, "\n"); -} - -void Interface::saveRequest(unsigned id, string path) { - string pathname = {pathnames(emulator->group(id)), path}; - filestream stream(pathname, file::mode::write); - emulator->save(id, stream); - echo("Saved ", path, "\n"); -} - -uint32_t Interface::videoColor(unsigned source, uint16_t alpha, uint16_t red, uint16_t green, uint16_t blue) { - return ((alpha >> 8) << 24) | ((red >> 8) << 16) | ((green >> 8) << 8) | ((blue >> 8) << 0); -} - -void Interface::videoRefresh(const uint32_t* palette, const uint32_t* data, unsigned pitch, unsigned width, unsigned height) { - uint32_t* output; - unsigned outputPitch; - - if(video.lock(output, outputPitch, width, height)) { - pitch >>= 2, outputPitch >>= 2; - - for(unsigned y = 0; y < height; y++) { - const uint32_t* sp = data + y * pitch; - uint32_t* dp = output + y * outputPitch; - for(unsigned x = 0; x < width; x++) { - *dp++ = palette[*sp++]; - } - } - - video.unlock(); - video.refresh(); - } -} - -void Interface::audioSample(int16_t lsample, int16_t rsample) { - if(settings->audio.mute) lsample = 0, rsample = 0; - signed samples[] = {lsample, rsample}; - dspaudio.sample(samples); - while(dspaudio.pending()) { - dspaudio.read(samples); - audio.sample(samples[0], samples[1]); - } -} - -int16_t Interface::inputPoll(unsigned port, unsigned device, unsigned input) { - unsigned guid = emulator->port[port].device[device].input[input].guid; - return inputManager->inputMap[guid]->poll(); -} - -void Interface::inputRumble(unsigned port, unsigned device, unsigned input, bool enable) { -} - -unsigned Interface::dipSettings(const Markup::Node& node) { - return 0; -} - -string Interface::path(unsigned group) { - return pathnames(group); -} - -string Interface::server() { - return ""; -} - -void Interface::notify(string text) { -} diff --git a/target-loki/interface/interface.hpp b/target-loki/interface/interface.hpp deleted file mode 100644 index 1438075e..00000000 --- a/target-loki/interface/interface.hpp +++ /dev/null @@ -1,25 +0,0 @@ -struct Interface : Emulator::Interface::Bind { - Interface(); - bool load(string pathname); - void unload(); - - //bindings - void loadRequest(unsigned id, string name, string type); - void loadRequest(unsigned id, string path); - void saveRequest(unsigned id, string path); - uint32_t videoColor(unsigned source, uint16_t alpha, uint16_t red, uint16_t green, uint16_t blue); - void videoRefresh(const uint32_t* palette, const uint32_t* data, unsigned pitch, unsigned width, unsigned height); - void audioSample(int16_t lsample, int16_t rsample); - int16_t inputPoll(unsigned port, unsigned device, unsigned input); - void inputRumble(unsigned port, unsigned device, unsigned input, bool enable); - unsigned dipSettings(const Markup::Node& node); - string path(unsigned group); - string server(); - void notify(string text); - - string pathname; //path to game folder - lstring pathnames; -}; - -extern Interface* interface; -extern SuperFamicom::Interface* emulator; diff --git a/target-loki/loki.cpp b/target-loki/loki.cpp deleted file mode 100644 index 26232e1c..00000000 --- a/target-loki/loki.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "loki.hpp" -#include "resource/resource.cpp" - -Program* program = nullptr; -DSP dspaudio; - -string Program::path(string name) { - string path = {basepath, name}; - if(file::exists(path) || directory::exists(path)) return path; - path = {userpath, name}; - if(file::exists(path) || directory::exists(path)) return path; - path = {sharedpath, name}; - if(file::exists(path) || directory::exists(path)) return path; - return {userpath, name}; -} - -void Program::main() { - inputManager->poll(); - debugger->main(); -} - -Program::Program(string pathname) { - program = this; - - basepath = nall::programpath(); - userpath = {nall::configpath(), "loki/"}; - sharedpath = {nall::sharedpath(), "loki/"}; - directory::create(userpath); - - new Settings; - new InputManager; - new Interface; - new Debugger; - new Presentation; - new Terminal; - - presentation->setVisible(); - terminal->setVisible(); - Application::processEvents(); - - video.driver(settings->video.driver); - video.set(Video::Handle, presentation->viewport.handle()); - video.set(Video::Synchronize, settings->video.synchronize); - video.set(Video::Filter, Video::FilterNearest); - if(video.init() == false) { video.driver("None"); video.init(); } - - audio.driver(settings->audio.driver); - audio.set(Audio::Handle, presentation->viewport.handle()); - audio.set(Audio::Synchronize, settings->audio.synchronize); - audio.set(Audio::Frequency, 48000u); - if(audio.init() == false) { audio.driver("None"); audio.init(); } - - input.driver(settings->input.driver); - input.set(Input::Handle, presentation->viewport.handle()); - if(input.init() == false) { input.driver("None"); input.init(); } - input.onChange = {&Terminal::inputEvent, terminal}; - - dspaudio.setPrecision(16); - dspaudio.setBalance(0.0); - dspaudio.setFrequency(32000); - dspaudio.setResampler(DSP::ResampleEngine::Hermite); - dspaudio.setResamplerFrequency(48000); - - presentation->showSplash(); - - inputManager->load(); - interface->load(pathname); - debugger->load(); - terminal->load(); - - Application::main = {&Program::main, this}; - Application::run(); - - terminal->unload(); - debugger->unload(); - interface->unload(); - inputManager->unload(); - settings->unload(); -} - -int main(int argc, char** argv) { - #if defined(PLATFORM_WINDOWS) - utf8_args(argc, argv); - #endif - - if(argc != 2 || !directory::exists(argv[1])) { - print("loki v", Emulator::Version, "\n"); - print("usage: loki /path/game.sfc/\n"); - return 0; - } - - Application::setName("loki"); - new Program(argv[1]); - delete program; - - return 0; -} diff --git a/target-loki/loki.hpp b/target-loki/loki.hpp deleted file mode 100644 index 293b21ea..00000000 --- a/target-loki/loki.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#include <emulator/emulator.hpp> -#include <sfc/sfc.hpp> -namespace SFC = SuperFamicom; - -#include <nall/platform.hpp> -#include <nall/bitvector.hpp> -#include <nall/config.hpp> -#include <nall/directory.hpp> -#include <nall/dsp.hpp> -#include <nall/invoke.hpp> -#include <nall/map.hpp> -#include <nall/stream/file.hpp> -#include <nall/stream/memory.hpp> -#include <nall/stream/mmap.hpp> -#include <nall/stream/vector.hpp> -using namespace nall; - -#include <ruby/ruby.hpp> -using namespace ruby; - -#include <phoenix/phoenix.hpp> -using namespace phoenix; - -#include "settings/settings.hpp" -#include "input/input.hpp" -#include "interface/interface.hpp" -#include "debugger/debugger.hpp" -#include "presentation/presentation.hpp" -#include "terminal/terminal.hpp" -#include "resource/resource.hpp" - -struct Program { - string basepath; - string userpath; - string sharedpath; - - string path(string name); - void main(); - Program(string pathname); -}; - -template<typename... Args> void echo(Args&&... args) { - terminal->print({std::forward<Args>(args)...}); -} - -extern Program* program; -extern DSP dspaudio; diff --git a/target-loki/presentation/presentation.cpp b/target-loki/presentation/presentation.cpp deleted file mode 100644 index 00a85862..00000000 --- a/target-loki/presentation/presentation.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "../loki.hpp" -Presentation* presentation = nullptr; - -Presentation::Presentation() { - presentation = this; - if(settings->geometry.presentation.empty()) { - settings->geometry.presentation = "64,64,512,480"; - } - - setTitle({"loki v", Emulator::Version}); - setGeometry(settings->geometry.presentation); - setResizable(false); - - layout.append(viewport, {0, 0, 512, 480}); - append(layout); - - onClose = &Application::quit; - - splash.allocate(512, 480); - splash.verticalGradient(0xff00005f, 0xff000000, 512, 480, 256, 0); - nall::image floor; - floor.allocate(512, 480); - floor.radialGradient(0xffff0000, 0x00000000, 384, 240, 256, 415); - splash.impose(image::blend::sourceAlpha, 0, 0, floor, 0, 0, floor.width, floor.height); - nall::image loki(resource::loki, sizeof resource::loki); - splash.impose(image::blend::sourceAlpha, (512 - loki.width) / 2, (480 - loki.height) / 2, loki, 0, 0, loki.width, loki.height); -} - -void Presentation::showSplash() { - uint32_t* data; - unsigned pitch; - if(video.lock(data, pitch, 512, 480)) { - for(unsigned y = 0; y < 480; y++) { - memcpy((uint8_t*)data + y * pitch, splash.data + y * splash.pitch, 512 * sizeof(uint32_t)); - } - video.unlock(); - video.refresh(); - } -} diff --git a/target-loki/presentation/presentation.hpp b/target-loki/presentation/presentation.hpp deleted file mode 100644 index f5094b11..00000000 --- a/target-loki/presentation/presentation.hpp +++ /dev/null @@ -1,11 +0,0 @@ -struct Presentation : Window { - Presentation(); - void showSplash(); - - FixedLayout layout; - Viewport viewport; - - nall::image splash; -}; - -extern Presentation* presentation; diff --git a/target-loki/resource/loki.png b/target-loki/resource/loki.png deleted file mode 100644 index 7b031d9c..00000000 Binary files a/target-loki/resource/loki.png and /dev/null differ diff --git a/target-loki/resource/resource.bml b/target-loki/resource/resource.bml deleted file mode 100644 index 9d8482c8..00000000 --- a/target-loki/resource/resource.bml +++ /dev/null @@ -1,2 +0,0 @@ -resource name=resource - binary id=loki name=loki.png diff --git a/target-loki/resource/resource.cpp b/target-loki/resource/resource.cpp deleted file mode 100644 index 5f8cffbf..00000000 --- a/target-loki/resource/resource.cpp +++ /dev/null @@ -1,3816 +0,0 @@ -namespace resource { - -const uint8_t loki[121905] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,32,0,0,1,104,8,6,0,0,0,247,136,38, - 129,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,4,103,65,77,65,0,0, - 177,142,124,251,81,147,0,0,0,32,99,72,82,77,0,0,122,37,0,0,128,131,0,0,249,255,0,0,128,233,0,0, - 117,48,0,0,234,96,0,0,58,152,0,0,23,111,146,95,197,70,0,1,219,167,73,68,65,84,120,218,236,253,119,152, - 100,215,117,222,11,255,246,62,161,114,85,231,220,51,61,57,103,12,114,14,36,2,193,28,36,81,129,162,2,149,124,229, - 251,73,150,174,172,123,45,75,126,244,93,203,178,37,75,178,44,90,209,164,40,81,34,197,12,18,32,0,34,199,193,0, - 147,83,247,116,206,93,93,93,185,234,196,189,239,31,85,51,24,128,32,197,128,72,246,122,158,126,122,166,186,234,156,83, - 59,188,123,173,119,37,81,187,239,125,188,26,98,10,137,18,146,55,131,68,226,22,255,242,224,4,31,248,143,79,240,86, - 144,255,1,244,0,255,127,224,111,129,191,4,54,3,231,129,63,251,46,175,245,21,96,14,56,2,124,28,24,5,2,224, - 52,176,23,184,23,216,222,252,187,15,104,192,0,20,208,14,180,129,184,14,228,81,48,218,65,100,33,92,128,160,23,184, - 237,251,252,158,117,96,6,216,4,252,28,176,3,200,1,78,243,153,126,5,168,189,9,231,231,131,192,6,192,2,126,23, - 248,123,224,16,240,54,32,211,124,246,231,154,99,56,12,172,109,142,101,25,120,7,112,79,115,156,199,128,46,96,13,112, - 13,240,123,205,107,143,0,133,230,56,76,0,235,128,241,230,123,119,1,207,3,155,119,238,163,239,193,23,48,61,221,188, - 218,171,35,251,6,223,216,61,107,178,42,63,116,34,155,160,147,105,44,0,209,9,134,9,118,20,226,2,18,199,32,19, - 129,214,18,200,24,44,118,73,57,211,166,84,185,38,132,54,163,81,64,124,119,55,20,2,195,247,80,190,191,58,248,171, - 178,10,64,63,140,18,54,79,216,13,64,43,24,123,192,182,32,17,66,26,104,23,141,3,183,79,66,111,20,186,93,41, - 123,124,132,182,85,248,76,196,180,239,245,60,231,220,161,214,142,96,241,255,248,61,116,52,14,74,125,199,247,246,147,105, - 54,223,251,207,180,220,251,25,172,213,169,88,149,85,0,250,225,17,221,52,125,210,32,135,193,238,128,84,30,58,5,244, - 43,88,35,97,16,24,112,160,191,98,199,122,150,251,250,187,138,61,93,169,83,139,179,241,3,83,51,179,59,96,26,207, - 137,152,169,140,40,253,135,255,73,213,144,72,253,237,77,0,45,4,82,26,152,145,40,174,214,4,158,71,128,32,4,236, - 213,41,89,149,85,0,250,225,208,120,2,96,17,140,50,36,98,66,116,197,96,77,168,245,6,27,54,123,66,110,204,167, - 50,107,179,241,84,231,98,212,200,208,149,78,248,29,237,178,218,213,75,110,100,148,173,217,229,153,29,97,248,152,128,103, - 77,88,52,93,39,236,125,236,107,44,93,125,27,202,52,17,175,0,66,66,26,24,177,56,218,169,81,203,103,25,57,252, - 56,239,172,85,120,252,208,163,164,42,165,213,73,89,149,85,0,250,65,151,0,72,0,187,64,62,6,113,3,250,226,176, - 205,210,122,47,66,236,200,153,246,186,137,150,206,129,165,77,27,90,229,186,158,72,58,41,201,196,124,124,43,198,145,227, - 211,180,125,249,158,218,187,87,138,103,58,225,17,15,30,76,194,177,9,88,238,242,92,117,205,125,159,229,212,229,55,224, - 89,54,232,240,2,234,16,88,54,88,22,193,242,2,147,143,126,149,59,206,30,69,140,156,226,241,192,167,79,107,20,223, - 53,107,180,42,171,0,180,42,111,69,137,3,62,216,87,64,187,11,59,12,184,218,133,203,207,39,90,182,77,172,219,208, - 163,183,15,196,90,59,99,162,95,57,224,148,136,138,12,211,101,120,254,201,231,184,250,220,248,220,53,120,135,52,60,236, - 193,83,14,140,236,129,242,28,168,218,37,54,157,22,2,109,152,4,150,141,85,175,48,116,234,24,222,217,227,44,31,126, - 156,133,82,30,5,92,160,170,245,234,148,172,202,42,0,189,53,197,6,142,211,112,237,14,54,205,42,247,95,209,38,34, - 96,172,129,30,23,110,0,110,155,138,197,47,159,61,112,217,218,112,109,38,154,76,199,241,125,77,101,113,133,186,116,137, - 181,165,152,40,20,201,62,252,130,247,225,197,236,240,32,250,81,23,30,52,225,72,20,22,142,129,59,1,108,107,242,72, - 8,129,147,72,129,20,36,10,57,182,61,245,32,226,241,175,179,185,94,229,108,224,147,93,213,116,94,19,209,128,48,4, - 58,13,162,40,208,1,160,245,42,0,173,202,107,43,17,224,33,94,140,141,201,1,7,128,202,183,249,140,4,211,131,117, - 26,222,54,223,59,240,54,245,193,187,186,230,74,211,20,231,75,164,242,138,164,89,39,19,9,49,91,211,156,154,205,211, - 245,240,243,249,31,175,212,143,217,240,144,11,143,104,56,101,64,241,147,16,246,53,65,79,92,0,22,207,101,207,3,159, - 167,115,252,28,189,195,39,48,125,143,17,173,145,171,83,245,154,138,0,188,153,25,236,143,255,111,130,187,62,128,221,26, - 193,180,77,188,10,232,239,194,27,249,102,148,213,181,243,22,56,33,82,64,43,141,128,181,86,96,99,83,43,217,242,178, - 159,237,64,6,12,5,9,7,186,23,174,189,188,99,232,186,253,144,93,166,152,155,39,52,107,36,45,73,38,222,206,241, - 51,203,36,30,58,154,191,171,82,127,214,128,127,9,224,115,2,158,47,65,254,72,3,119,88,15,172,0,109,205,251,77, - 250,30,251,191,242,15,12,158,60,140,233,185,63,48,167,240,91,1,128,252,220,18,230,191,251,57,190,116,160,151,242,47, - 254,12,143,254,237,39,8,125,7,157,150,72,67,34,132,120,203,174,239,85,121,139,136,75,35,58,186,11,56,215,60,61, - 76,26,241,61,23,248,150,24,4,109,144,79,9,57,91,59,114,186,242,84,127,75,250,221,239,184,150,165,130,199,225,179, - 227,100,11,101,142,141,47,208,114,236,92,237,71,235,181,243,62,60,166,225,97,31,70,226,224,215,155,38,223,94,224,102, - 160,175,105,126,117,94,48,195,86,229,141,3,162,48,192,171,148,153,253,220,39,121,254,115,159,164,255,207,126,159,53,191, - 252,127,225,190,227,131,136,182,40,182,48,9,235,26,241,22,98,222,86,53,160,183,152,186,42,129,98,243,255,123,155,192, - 240,110,224,110,224,125,192,65,240,21,76,249,90,61,125,197,244,228,11,149,39,143,120,231,23,114,244,36,76,126,241,253, - 239,226,224,109,55,48,93,46,176,195,169,123,166,82,10,48,52,100,108,104,53,33,214,6,70,6,68,186,121,143,36,141, - 20,3,86,249,157,55,149,214,96,2,245,241,17,82,191,249,49,126,251,178,62,30,252,185,159,36,56,122,146,72,82,144, - 202,72,132,148,171,0,180,42,175,157,74,158,108,114,67,135,155,154,143,251,162,137,166,5,100,5,60,17,117,235,95,217, - 255,252,137,231,22,159,92,116,203,50,202,217,51,79,115,249,222,65,62,241,55,255,133,142,159,252,137,248,145,84,219,80, - 5,110,143,194,135,37,188,199,129,235,99,176,235,122,232,235,130,68,30,228,170,145,245,230,20,125,225,64,10,3,170,149, - 50,222,151,62,77,225,206,3,212,126,238,39,249,235,191,250,59,148,91,195,72,75,120,147,155,103,171,0,244,22,151,11, - 218,201,2,112,31,240,32,240,0,120,45,48,234,194,215,59,85,240,249,29,223,120,248,208,241,7,158,115,236,161,29,76, - 61,51,130,63,126,158,119,255,231,143,217,87,63,248,143,221,227,63,242,227,151,63,148,234,254,192,188,48,63,22,192,47, - 75,248,185,24,124,64,194,117,243,176,201,129,54,7,236,101,16,106,117,184,223,212,27,217,242,61,114,159,251,123,254,224, - 215,63,202,115,55,239,162,246,241,191,68,151,43,184,118,136,142,201,55,165,14,187,10,64,63,64,11,48,108,254,30,2, - 178,224,250,66,140,251,82,62,210,165,220,175,111,250,242,163,39,31,253,187,111,248,201,29,219,8,85,129,83,247,126,134, - 193,190,8,63,251,233,63,177,14,124,246,239,186,30,185,237,242,125,159,217,216,241,246,175,182,118,254,200,73,97,253,156, - 134,159,181,225,199,21,220,169,224,178,121,88,51,3,153,115,13,48,146,149,75,78,226,87,55,63,123,85,190,31,205,248, - 2,196,20,39,199,168,254,246,47,51,117,112,128,23,126,225,35,116,29,59,73,152,20,68,51,18,195,120,243,108,251,85, - 18,250,45,174,130,155,52,74,92,196,64,238,132,72,28,98,123,32,82,6,43,166,117,2,104,245,161,214,175,130,197,200, - 215,190,158,251,219,185,185,204,109,191,241,145,216,181,155,54,51,253,220,33,18,99,51,188,237,230,183,113,217,13,255,204, - 3,95,254,188,125,254,145,39,218,78,141,140,183,77,14,207,173,237,158,205,30,88,27,250,51,105,56,111,194,176,130,241, - 89,152,93,128,101,160,96,66,197,6,119,1,130,16,148,209,220,0,171,154,210,155,3,140,172,48,192,43,23,73,126,225, - 31,232,187,231,179,100,223,249,35,28,186,246,22,54,189,235,3,116,181,197,168,85,87,1,104,85,190,7,147,75,52,249, - 31,11,228,46,136,204,67,70,65,71,10,122,5,12,248,208,158,128,24,208,82,211,186,199,133,78,29,141,13,4,134,109, - 4,147,11,222,63,255,201,39,98,238,237,215,176,251,250,189,200,184,201,233,71,191,64,207,192,90,62,116,199,157,204,95, - 113,37,199,159,57,204,212,11,47,36,138,249,108,226,212,236,210,96,231,124,97,103,219,124,33,107,46,101,23,98,42,156, - 181,27,152,55,227,55,126,22,134,97,217,130,194,58,168,70,192,115,33,176,65,201,85,205,232,205,35,190,71,199,231,62, - 201,103,63,247,73,158,250,147,255,196,47,125,236,215,121,215,135,126,178,113,116,173,2,208,170,124,167,38,86,20,164,15, - 86,39,196,103,161,43,6,131,186,81,227,107,115,29,134,10,210,30,200,71,51,173,37,83,70,74,17,25,9,186,59,147, - 173,67,221,150,238,50,69,44,147,17,59,77,67,72,175,74,110,250,12,167,31,94,161,119,247,78,118,92,125,3,238,204, - 56,179,11,103,176,218,58,185,226,242,13,108,90,223,203,244,240,56,194,194,240,188,82,139,151,93,105,145,217,202,250,197, - 147,147,110,253,228,104,41,62,183,180,210,230,123,75,9,21,206,217,48,19,194,76,0,179,157,176,16,192,130,3,203,239, - 132,90,5,130,55,39,251,240,195,107,162,229,39,206,243,251,191,245,11,124,226,227,127,200,244,196,249,85,0,90,149,111, - 109,102,105,26,9,166,221,192,187,32,102,67,151,128,53,26,214,89,13,208,217,90,74,36,55,102,215,172,233,245,183,108, - 204,68,55,14,68,186,134,58,89,159,18,152,182,65,38,145,36,21,73,160,113,241,106,101,242,217,34,147,19,243,20,125, - 65,247,224,6,218,163,54,165,209,195,164,59,123,145,145,78,170,217,5,170,179,11,88,118,11,194,173,48,57,50,77,204, - 142,99,72,65,203,134,30,99,199,85,59,227,66,136,120,113,33,219,179,112,122,118,235,194,185,37,71,143,206,151,219,114, - 139,185,120,105,101,49,230,121,51,17,24,14,224,76,59,140,45,193,220,46,40,218,224,85,65,197,86,167,245,77,35,51, - 147,163,171,38,216,170,124,235,211,202,1,118,131,116,32,146,131,150,40,108,240,225,160,134,253,158,97,172,243,182,111,31, - 140,220,124,85,231,186,171,46,139,237,219,181,149,174,222,86,18,134,143,187,188,64,173,176,66,189,158,167,90,46,82,90, - 89,96,113,198,225,252,200,12,11,139,115,84,42,21,52,154,186,231,113,199,157,55,35,60,147,249,177,73,2,165,145,94, - 72,173,92,226,212,233,103,57,121,102,129,68,42,131,45,43,172,223,48,196,145,103,198,153,158,157,97,227,166,245,108,220, - 188,150,125,119,94,38,115,55,86,226,227,243,115,241,220,66,177,123,102,198,223,102,78,228,170,241,231,143,45,117,230,151, - 198,82,112,86,192,169,8,156,155,131,73,96,73,64,77,129,10,87,167,120,85,86,1,232,205,169,245,132,52,106,68,239, - 130,104,4,186,13,88,175,97,91,8,251,253,100,122,175,185,127,199,154,246,119,95,149,105,191,249,114,187,189,187,7,83, - 24,248,65,141,218,114,142,114,177,74,173,152,101,121,113,145,233,137,44,83,19,5,242,185,2,158,23,224,123,62,8,69, - 123,71,59,123,246,110,231,236,185,83,204,206,76,49,48,48,64,16,212,241,157,58,197,124,141,83,167,39,152,153,207,99, - 24,6,61,61,25,182,110,216,134,38,228,236,240,89,234,53,135,177,225,57,166,207,205,146,157,88,162,163,43,142,116,86, - 216,56,48,128,215,37,197,226,166,174,100,112,195,254,228,236,249,197,65,253,204,11,187,219,199,206,78,119,248,222,176,132, - 19,33,28,43,193,185,71,96,97,23,212,98,205,162,30,171,230,217,42,0,173,202,155,68,106,192,187,193,176,26,209,201, - 155,3,184,50,132,203,107,241,196,22,174,61,56,212,255,222,107,91,218,247,14,200,120,103,154,170,227,178,56,126,26,171, - 226,227,107,147,92,169,192,252,248,20,115,99,43,44,47,151,240,3,23,173,3,12,35,74,166,37,138,97,71,232,237,237, - 225,178,131,251,104,105,73,176,148,27,101,165,48,75,60,33,72,216,38,181,98,153,51,39,167,153,157,171,98,88,38,187, - 246,13,176,255,192,46,38,207,45,114,236,216,57,240,99,152,34,32,244,53,169,68,146,241,51,227,84,115,109,184,190,75, - 118,230,44,67,27,6,8,22,179,184,161,195,208,149,91,173,232,29,63,222,85,24,47,116,142,223,255,220,38,243,201,39, - 246,245,122,245,51,54,28,10,225,153,235,225,204,52,228,98,16,60,191,10,66,171,0,180,42,111,172,214,163,128,61,64, - 90,136,72,0,253,66,235,253,2,110,168,152,230,149,165,131,187,55,164,223,182,163,165,123,231,128,72,102,98,84,150,179, - 20,23,75,132,118,18,95,105,130,208,34,59,49,202,244,217,17,148,19,16,141,9,6,7,44,42,53,240,189,24,169,84, - 146,104,90,209,183,166,151,173,155,119,83,173,214,153,158,158,102,112,112,128,149,149,121,226,49,73,173,84,228,236,153,9, - 102,23,92,214,172,31,228,186,27,119,208,213,157,230,228,145,179,156,56,122,14,161,109,148,167,48,36,40,237,17,232,50, - 209,152,65,177,178,140,101,69,113,106,117,70,199,203,236,217,188,159,82,54,207,241,7,159,164,173,183,155,129,157,59,197, - 246,95,123,111,122,225,3,55,167,143,127,254,145,181,173,143,62,188,121,200,247,54,85,225,145,78,120,110,16,166,179,80, - 75,128,94,117,223,175,2,208,170,188,1,18,0,189,192,207,64,52,167,245,122,19,110,242,17,111,31,235,235,61,160,110, - 220,215,53,176,175,203,108,77,197,17,37,141,99,69,209,173,237,76,230,28,202,203,130,173,125,157,84,230,158,69,85,23, - 88,55,216,70,185,88,162,144,175,83,42,7,152,81,73,215,64,156,150,76,43,155,182,109,32,153,206,48,62,58,207,83, - 79,29,2,2,238,120,251,245,12,116,247,18,4,46,163,99,203,100,75,1,7,175,219,205,101,151,239,161,179,35,201,241, - 231,143,112,234,216,73,146,169,52,197,66,158,100,44,192,13,20,117,87,19,104,137,176,99,8,229,35,76,77,75,164,21, - 237,4,76,143,143,113,229,213,87,209,222,223,201,161,67,71,88,122,228,41,226,137,35,108,220,185,143,107,255,175,95,138, - 21,127,244,253,219,167,254,248,127,116,182,157,60,54,152,130,161,50,60,121,13,156,42,195,202,213,224,63,180,186,28,86, - 1,104,85,94,63,105,7,182,130,140,66,186,10,155,13,184,169,140,184,227,252,229,59,47,107,185,110,107,162,45,29,65, - 40,73,45,189,134,192,202,4,167,142,79,250,247,62,241,141,232,141,7,47,19,63,241,206,43,200,207,60,71,57,59,73, - 107,122,144,220,92,153,153,233,105,12,43,164,107,160,157,68,107,154,150,246,46,246,236,217,137,235,132,60,245,196,17,158, - 63,124,140,82,185,204,174,93,27,105,107,109,165,94,54,120,225,217,51,44,45,213,185,233,174,119,48,56,212,74,123,71, - 23,99,167,71,120,254,217,23,216,180,126,13,249,124,157,82,14,82,137,54,42,110,133,114,181,130,10,45,76,51,130,37, - 192,182,21,137,136,6,83,226,122,112,236,244,121,174,184,230,50,2,35,224,244,209,83,184,229,128,83,79,61,195,209,67, - 207,178,227,170,155,197,158,63,255,175,93,147,159,250,236,53,211,159,248,68,255,160,231,110,240,225,27,54,60,245,23,48, - 245,235,224,127,101,117,89,172,2,208,170,188,246,210,10,252,21,200,86,104,173,194,126,19,222,158,179,172,155,231,110,56, - 176,99,224,170,117,182,169,29,202,178,133,149,160,63,116,62,243,76,221,120,224,193,194,76,44,94,252,240,31,254,135,77, - 63,118,215,94,251,196,67,95,66,121,154,109,91,110,225,241,71,30,36,191,56,67,166,61,195,192,218,181,40,203,164,115, - 160,143,189,7,14,50,63,183,192,151,63,127,63,227,195,83,248,65,72,58,147,226,186,27,174,194,176,52,167,78,159,32, - 183,92,226,246,119,223,141,213,210,202,82,193,67,137,26,143,63,246,48,251,118,239,197,64,114,238,236,51,248,129,139,20, - 96,154,2,165,60,16,17,194,208,37,147,180,137,89,18,97,10,68,194,64,59,117,202,245,5,206,159,63,198,222,93,187, - 112,75,101,150,230,178,8,105,83,118,2,158,254,250,151,24,31,57,205,59,126,225,23,227,139,183,222,180,237,153,127,247, - 219,157,187,167,198,58,99,144,88,129,111,252,58,76,206,128,119,100,117,121,172,2,208,91,215,166,81,12,245,167,248,104, - 204,36,94,15,222,116,143,39,104,212,245,249,40,200,53,208,86,134,131,6,188,103,50,154,184,173,240,174,221,107,217,176, - 70,156,158,245,48,74,34,104,157,122,161,218,57,242,47,225,96,62,111,44,173,221,144,254,137,191,253,179,142,157,87,174, - 181,135,31,252,2,169,100,23,117,87,241,141,175,63,64,177,176,196,174,45,107,104,233,236,166,26,73,17,177,108,118,221, - 120,51,185,5,135,251,62,251,48,147,19,179,8,13,65,205,231,170,59,111,97,243,229,87,240,232,87,63,67,33,183,192, - 141,31,248,8,166,213,201,99,143,223,199,187,127,228,102,14,223,243,5,246,93,117,128,181,93,67,60,248,185,127,33,12, - 67,236,72,132,13,59,58,41,29,117,113,67,129,182,5,161,31,96,96,99,199,45,132,37,136,89,54,150,105,226,4,62, - 197,133,25,178,109,105,182,236,187,140,74,253,49,98,65,149,221,215,220,196,218,66,200,163,159,249,60,255,244,7,255,149, - 219,126,226,131,226,214,207,252,69,231,151,127,241,223,95,183,239,200,243,86,43,24,2,30,252,67,152,248,3,112,31,88, - 221,159,171,0,244,86,20,215,11,217,179,181,141,191,89,147,134,115,43,111,202,103,60,2,194,133,150,50,92,110,192,123, - 78,183,244,222,185,242,246,253,125,139,97,9,239,203,71,195,93,203,197,149,205,229,106,37,89,173,24,85,116,98,106,203, - 118,251,170,79,252,81,116,211,238,1,49,124,228,27,196,218,7,153,31,30,231,200,83,143,97,101,210,92,119,235,53,152, - 134,137,136,167,73,122,16,198,147,212,42,240,249,79,124,146,233,233,81,226,210,100,185,234,209,218,155,228,250,119,222,206, - 204,244,34,217,51,103,185,250,182,187,17,45,29,252,239,63,249,115,222,255,225,119,49,125,242,24,27,247,236,102,104,112, - 3,15,127,249,171,204,231,107,24,74,210,217,155,34,149,72,160,252,0,219,180,16,66,161,209,4,174,70,9,69,58,147, - 33,168,58,180,102,146,172,84,106,24,210,96,126,126,129,237,3,91,217,188,125,43,51,195,39,153,62,119,148,93,55,125, - 16,251,125,119,243,240,61,247,242,197,191,254,43,110,184,253,38,222,243,201,191,74,125,237,55,126,239,234,161,123,191,104, - 12,128,136,195,253,127,14,19,191,10,222,189,172,22,183,95,5,160,183,160,8,165,121,108,99,43,75,231,86,136,190,137, - 22,176,160,209,147,61,6,86,20,54,90,240,246,231,83,233,183,141,92,182,182,79,59,14,137,35,147,206,221,83,211,167, - 19,232,9,5,201,10,172,29,219,185,43,115,197,159,255,135,104,95,166,34,150,142,61,65,88,79,241,220,11,143,48,55, - 114,130,205,219,46,99,221,206,109,84,107,53,226,189,27,33,48,56,126,232,16,55,223,125,19,159,251,248,167,152,25,61, - 135,21,53,113,11,62,90,187,236,58,120,45,86,75,154,35,159,253,59,118,238,191,150,68,219,102,254,244,79,255,148,157, - 251,182,210,158,12,9,173,14,98,177,56,227,195,167,153,60,55,73,24,104,122,6,51,244,182,165,113,156,0,29,64,196, - 18,72,20,66,8,66,109,162,181,162,165,189,29,199,42,35,181,207,218,129,126,22,151,22,49,172,24,11,51,227,108,222, - 190,147,234,202,50,209,120,148,51,71,30,229,192,141,119,80,169,228,152,57,113,130,35,143,60,70,53,95,227,93,127,242, - 159,18,255,24,56,87,69,30,184,79,117,128,154,129,7,126,23,38,62,2,254,111,209,232,171,190,42,171,0,244,150,17, - 165,225,234,15,110,229,239,31,158,98,164,230,191,105,190,104,72,131,120,222,3,182,11,253,121,196,174,177,173,91,7,172, - 84,20,207,180,216,92,115,22,82,232,23,60,152,171,192,238,225,237,91,219,238,252,227,255,51,221,221,150,19,249,108,157, - 225,163,11,44,156,58,139,142,150,185,250,237,55,210,187,102,19,179,217,58,235,182,239,167,88,11,249,234,151,191,200,93, - 239,126,39,143,124,241,203,204,158,62,135,29,143,147,207,175,32,137,144,110,177,184,230,230,59,152,124,246,16,118,44,32, - 185,237,0,255,248,231,159,33,29,137,112,249,21,91,177,35,9,102,22,230,233,145,146,179,199,39,88,41,86,24,90,223, - 67,166,45,74,87,111,23,83,99,203,24,40,44,41,8,3,31,35,158,64,99,128,14,8,8,73,182,183,82,93,154,39, - 157,78,81,172,214,73,36,227,148,139,203,184,129,199,250,237,91,25,31,27,167,191,191,155,147,207,61,206,45,239,125,39, - 15,212,139,36,39,22,88,56,241,12,45,189,157,252,236,223,254,89,236,239,223,247,225,203,15,28,58,164,18,16,58,112, - 95,15,204,232,102,141,234,55,242,208,88,149,85,0,250,174,68,123,33,230,134,22,254,231,250,22,14,159,204,190,169,158, - 109,29,240,73,16,6,68,235,66,196,172,142,148,236,137,39,24,173,72,10,94,24,24,96,215,97,221,83,91,215,94,254, - 142,255,250,163,157,29,93,54,197,34,60,241,224,163,228,38,230,24,236,235,224,218,155,238,68,117,116,48,182,82,99,247, - 238,93,228,230,10,124,225,239,255,137,107,111,189,129,201,225,97,78,28,122,148,68,36,66,177,6,181,186,65,34,226,178, - 102,251,110,162,49,201,137,227,135,216,115,203,29,124,233,11,159,167,184,56,201,157,239,127,39,61,237,157,140,13,79,48, - 122,234,44,108,217,196,137,23,70,24,92,219,199,198,109,189,136,48,164,88,113,153,95,88,70,10,69,212,50,241,116,136, - 52,37,94,224,227,7,26,215,169,211,223,223,15,78,21,45,52,107,214,111,96,102,114,148,254,158,118,102,103,103,89,179, - 115,43,177,229,28,137,68,27,197,106,141,220,194,20,215,188,251,71,120,232,111,254,28,195,142,114,254,169,199,25,220,188, - 133,31,255,244,223,165,255,238,166,187,46,191,126,106,162,106,64,54,132,242,255,128,149,95,162,145,203,241,70,200,157,192, - 41,88,237,107,191,10,64,223,165,248,154,63,248,217,221,124,242,183,30,37,246,38,33,163,3,26,133,222,45,208,30,4, - 150,86,126,88,169,106,217,153,18,118,232,144,174,149,45,31,118,63,188,161,171,247,186,255,240,190,238,205,61,67,148,115, - 33,247,221,251,56,243,147,75,92,181,111,43,123,174,28,162,158,238,97,97,185,194,222,77,67,76,159,25,231,51,159,254, - 10,67,107,186,104,75,68,120,226,203,247,97,9,15,55,2,249,233,10,145,120,10,83,21,184,236,178,131,76,15,31,98, - 253,238,237,28,125,126,134,217,23,142,177,123,215,102,246,237,219,193,82,110,153,227,143,62,66,186,173,155,71,30,121,1, - 133,98,223,101,123,8,205,26,38,146,167,159,126,26,161,37,201,148,77,213,115,41,87,20,194,0,67,132,40,213,208,130, - 34,81,155,84,71,23,245,90,149,206,174,62,140,120,130,120,58,195,114,190,64,93,197,24,216,186,157,217,99,103,216,116, - 217,181,28,125,242,235,92,255,142,237,236,184,253,29,156,190,231,11,68,8,121,244,179,127,207,135,126,245,223,115,213,199, - 255,180,229,217,119,126,224,224,245,129,59,173,97,54,1,199,174,3,231,93,52,26,47,190,94,230,180,160,209,2,105,8, - 56,182,138,21,171,0,244,93,147,209,126,200,205,7,123,137,189,237,114,106,247,188,64,50,116,222,112,46,72,52,65,168, - 42,68,96,65,190,69,235,101,39,183,236,22,183,182,69,141,88,192,11,102,44,49,220,18,111,217,245,203,239,200,28,88, - 183,153,226,66,137,175,127,229,81,102,22,23,185,226,170,131,236,191,238,50,220,120,156,249,133,49,54,246,244,50,117,102, - 152,47,125,238,33,12,13,151,95,125,5,79,220,255,16,94,165,66,36,146,96,58,183,130,17,51,8,252,26,157,131,189, - 180,24,14,11,229,34,210,90,195,243,247,127,129,174,182,118,174,185,237,42,234,213,37,14,61,248,32,182,25,99,114,106, - 150,243,227,243,188,253,230,27,105,233,109,69,136,62,190,113,207,131,228,203,30,189,157,237,40,175,68,60,22,197,205,150, - 145,134,36,26,19,4,190,34,172,215,240,92,151,100,71,55,70,97,9,199,41,211,187,102,136,82,181,72,111,79,47,185, - 185,101,54,238,216,72,177,99,28,183,84,99,219,142,203,24,126,225,105,118,222,240,46,102,78,30,71,207,12,163,170,121, - 30,254,204,95,243,206,95,253,247,156,254,165,159,239,27,255,211,63,187,122,8,198,235,144,253,29,152,52,32,124,130,70, - 195,198,215,235,176,24,4,54,208,168,185,157,92,197,139,85,0,250,174,57,151,186,199,169,107,174,71,143,57,140,158,120, - 1,255,77,96,211,251,192,101,90,251,235,96,62,2,19,3,211,139,165,178,179,62,26,139,216,60,222,25,239,248,137,15, - 94,203,173,91,118,144,159,94,228,254,135,30,165,180,156,103,247,142,141,92,113,235,1,114,126,146,194,236,50,157,145,8, - 165,185,105,238,255,234,19,44,231,86,184,235,125,111,103,122,114,150,236,204,50,118,36,194,74,197,195,175,128,142,249,216, - 150,205,150,13,107,169,150,230,232,236,216,194,3,247,61,142,233,229,217,125,219,173,88,173,157,60,125,207,61,88,245,34, - 185,178,199,212,76,158,206,84,156,43,174,222,67,188,175,135,67,247,60,196,249,115,211,180,175,93,71,166,205,164,152,45, - 227,122,53,66,101,82,173,213,24,236,238,164,82,244,33,240,241,156,58,118,75,15,201,150,12,142,227,144,238,236,98,170, - 88,160,181,163,139,252,228,28,245,250,38,122,182,236,99,250,244,17,6,247,188,141,153,153,5,170,217,105,246,222,113,39, - 135,254,106,132,104,194,98,105,250,28,71,238,253,28,63,250,91,255,70,254,229,211,207,109,237,125,238,153,27,44,152,172, - 192,202,151,160,240,31,223,0,243,235,83,171,56,177,10,64,223,215,151,172,85,57,115,203,173,76,207,79,161,151,151,223, - 112,0,114,128,187,33,148,141,190,127,83,221,229,242,242,241,115,11,93,253,253,107,185,243,134,237,28,216,219,207,92,174, - 192,177,195,231,153,155,42,177,123,247,102,246,94,127,13,243,139,57,168,101,145,229,28,178,179,147,251,31,58,198,236,82, - 137,221,7,54,211,221,191,134,175,252,195,23,176,67,240,112,112,235,62,166,157,164,84,175,208,219,31,37,29,171,98,70, - 58,56,127,106,140,194,236,18,173,3,61,108,220,212,205,217,135,31,32,63,151,101,197,181,152,207,151,241,116,145,187,110, - 123,15,61,59,246,113,244,249,195,28,127,238,24,101,4,87,239,219,128,63,49,73,162,127,55,231,166,142,18,143,72,44, - 21,18,79,39,41,151,74,88,126,26,211,55,128,16,51,211,69,186,93,18,250,54,237,221,189,148,36,116,173,233,39,63, - 55,204,224,222,91,137,45,230,41,85,86,216,182,107,23,147,135,159,102,251,29,31,160,99,215,30,166,158,123,142,142,214, - 22,142,63,253,36,155,118,109,225,154,223,253,88,114,228,67,35,251,118,149,115,35,37,24,91,7,181,35,224,101,120,125, - 88,105,5,44,241,237,59,209,174,202,42,0,253,235,11,73,107,34,134,201,71,15,94,206,173,247,126,237,77,241,76,115, - 192,104,3,132,252,65,100,125,238,244,233,176,163,199,54,222,113,240,6,220,162,195,217,137,19,140,156,153,103,253,166,126, - 54,31,220,199,82,190,68,220,180,152,31,155,96,221,224,32,207,29,58,66,118,49,71,34,30,227,134,235,175,225,209,71, - 159,32,168,87,144,134,164,232,128,235,75,66,29,176,156,93,228,178,45,173,88,145,24,133,178,203,201,99,47,96,9,159, - 3,187,247,48,123,126,130,241,241,25,10,165,144,133,114,13,79,5,220,176,239,74,174,121,251,141,204,204,143,243,212,231, - 239,35,87,118,233,93,59,64,202,148,4,153,52,35,51,57,188,208,37,149,177,80,190,38,29,79,82,107,113,209,66,35, - 180,194,150,6,134,48,201,116,247,176,188,84,33,221,217,141,31,84,105,27,218,74,233,228,11,248,165,69,186,55,239,101, - 114,244,20,235,55,109,66,159,51,88,26,61,78,255,182,45,204,140,156,34,148,146,238,246,14,158,253,210,61,92,251,225, - 31,99,226,195,239,238,47,126,252,111,174,72,192,153,93,48,119,24,178,255,9,72,188,198,243,83,5,222,9,252,6,171, - 49,72,171,0,244,42,240,46,132,33,19,93,221,124,218,178,89,241,189,55,172,29,136,15,220,14,44,131,169,160,219,132, - 161,69,51,222,150,234,77,27,87,237,90,131,95,90,98,97,197,229,204,232,44,169,22,131,45,91,215,177,82,45,210,158, - 106,225,220,11,71,88,191,110,29,163,99,83,156,59,55,73,221,117,185,254,198,107,40,23,74,204,143,76,96,138,144,58, - 154,92,197,64,72,141,83,89,161,45,105,145,140,154,216,137,14,142,157,28,70,121,21,134,134,122,49,60,135,83,103,207, - 145,173,4,148,28,73,221,115,88,219,222,198,53,183,221,130,39,3,30,253,199,127,162,92,172,178,88,169,112,199,193,189, - 212,22,166,168,213,234,156,159,24,39,17,129,84,202,164,86,242,177,132,69,91,103,148,122,177,142,48,4,182,52,49,13, - 139,74,185,142,176,162,216,81,129,87,168,33,19,29,116,12,109,165,180,56,78,251,142,107,73,183,117,224,84,43,172,217, - 178,141,133,201,115,180,68,147,108,234,236,97,120,108,134,190,129,77,172,20,203,44,12,31,103,237,135,111,52,143,125,249, - 129,173,87,207,77,237,43,194,209,1,200,223,7,129,249,26,3,67,216,156,171,202,235,0,118,171,0,244,67,32,86,24, - 144,235,238,230,119,58,58,152,155,159,123,67,159,229,19,192,46,200,4,176,51,64,238,249,106,202,236,187,226,134,237,36, - 133,65,185,230,113,106,116,158,122,32,217,185,103,16,39,8,232,203,100,152,30,25,37,98,88,168,80,113,246,236,56,97, - 40,73,38,227,108,217,184,134,71,30,126,12,225,73,66,9,139,213,34,136,86,68,80,98,176,39,131,16,73,218,59,186, - 40,149,92,150,231,150,104,111,73,16,77,70,56,59,60,74,97,217,165,162,13,102,23,151,232,73,89,236,220,187,145,68, - 87,146,199,62,255,53,102,39,150,88,88,42,177,101,221,26,218,18,154,211,249,5,230,151,125,156,74,157,222,182,56,134, - 45,201,86,28,234,46,116,244,180,177,232,47,162,77,11,165,13,34,241,20,147,75,43,180,246,174,193,76,216,216,174,139, - 87,117,137,247,108,36,91,88,193,173,20,72,181,245,81,201,205,211,214,222,67,108,126,138,154,83,198,111,73,18,233,74, - 113,100,248,40,151,93,113,45,165,185,57,182,239,216,197,147,59,55,181,85,231,166,182,153,176,81,192,120,59,20,186,94, - 7,243,235,12,171,29,62,86,1,232,85,18,13,104,165,249,191,59,58,152,158,159,123,67,120,160,0,216,12,108,4,171, - 2,67,17,184,242,1,219,220,25,63,56,24,217,209,217,142,19,106,78,141,44,49,53,190,200,190,131,67,4,129,164,22, - 132,196,80,120,133,34,93,93,253,156,56,113,22,215,215,84,42,21,174,223,127,128,153,233,41,230,103,22,64,167,240,13, - 73,197,201,97,186,43,108,93,147,36,157,73,178,82,170,210,218,217,199,185,115,19,68,132,198,178,34,228,235,30,11,203, - 53,2,199,96,62,159,197,196,101,215,206,77,236,186,124,43,39,158,121,146,177,211,147,76,45,215,48,165,224,138,141,189, - 44,206,156,97,227,101,59,89,250,198,8,218,13,72,153,54,75,69,151,137,133,89,10,117,197,134,76,55,42,12,48,19, - 73,132,29,199,136,165,176,18,6,161,17,39,146,72,224,213,92,66,167,140,76,117,17,233,88,71,80,88,38,210,190,6, - 59,209,142,178,76,82,109,93,248,229,28,6,81,58,18,9,86,86,86,24,30,59,203,229,251,47,35,234,4,180,29,92, - 99,14,63,104,108,220,171,194,221,10,142,157,134,210,92,35,214,244,53,3,159,12,141,70,0,171,230,215,42,0,189,106, - 98,75,193,51,155,55,243,201,19,199,223,176,103,248,101,96,7,100,52,236,42,10,246,159,236,74,116,95,181,126,19,117, - 223,228,204,236,44,99,83,89,118,109,92,79,151,105,83,93,41,83,143,39,201,23,138,132,74,51,183,144,37,183,82,161, - 238,134,196,226,22,107,215,246,243,252,115,207,163,148,137,231,43,166,150,151,209,166,77,198,172,115,235,53,151,115,242,236, - 44,126,42,201,66,54,79,49,151,39,110,71,112,125,200,45,85,169,249,38,78,221,163,176,178,194,205,215,238,98,231,190, - 173,76,143,141,115,252,133,147,12,143,45,163,3,147,104,218,192,165,68,79,87,15,78,32,25,29,31,165,163,163,133,72, - 36,205,212,217,19,244,118,181,81,169,215,137,39,186,112,131,58,50,30,131,104,156,192,138,16,104,159,194,74,145,129,238, - 22,108,211,196,115,202,68,188,58,177,76,59,70,190,138,174,150,136,165,219,81,161,67,44,213,66,224,213,105,233,236,97, - 246,204,89,34,194,102,105,108,146,197,158,33,182,116,247,179,255,170,45,252,195,96,186,123,247,100,126,187,9,131,117,152, - 106,17,56,81,33,94,19,13,69,105,152,209,154,204,42,62,172,2,208,247,203,253,24,198,75,207,48,17,188,113,1,137, - 221,192,219,32,226,55,58,90,92,118,38,30,223,52,176,111,187,140,26,38,103,198,102,153,43,58,164,50,22,173,29,38, - 132,146,114,121,133,206,53,3,228,242,14,133,74,149,192,119,240,85,132,82,117,145,171,175,216,69,185,88,100,97,33,71, - 46,95,197,247,171,140,77,76,33,77,155,15,254,232,213,180,183,218,228,75,30,118,42,206,202,194,28,6,224,32,169,150, - 92,28,79,224,7,146,185,236,60,91,54,12,178,117,219,58,68,16,48,114,102,154,231,207,205,19,81,81,76,229,208,215, - 213,70,251,230,13,68,35,113,30,252,204,3,216,194,161,103,176,143,177,209,60,166,17,161,167,53,73,110,57,139,136,167, - 177,220,4,177,136,69,44,147,38,16,26,21,106,178,243,51,208,151,193,10,125,180,1,97,117,9,51,22,129,104,2,183, - 84,37,154,105,69,105,133,178,227,84,61,159,214,181,189,56,118,43,149,165,9,16,130,211,39,78,209,51,212,199,230,129, - 94,50,87,110,139,205,77,62,53,216,7,107,210,112,52,121,93,143,211,241,43,219,161,250,42,207,103,212,192,123,122,137, - 194,159,158,186,216,131,109,85,222,34,0,36,66,31,180,70,232,111,61,115,90,74,180,52,95,23,240,177,45,197,83,195, - 105,230,10,54,166,161,241,124,159,161,161,117,252,175,206,78,98,217,236,235,110,223,39,128,118,104,9,97,79,89,136,253, - 75,67,67,157,3,125,61,156,30,31,70,210,78,61,95,98,235,254,65,60,81,198,140,183,80,203,105,100,80,103,110,170, - 140,235,9,28,207,163,238,64,34,149,102,211,230,33,158,125,242,41,234,53,143,68,186,149,192,119,217,180,113,136,233,233, - 28,189,61,173,148,42,69,66,34,40,165,241,74,43,24,34,77,222,245,169,187,33,102,96,145,93,92,32,22,179,217,180, - 174,159,84,58,198,217,115,195,156,56,54,131,242,19,24,17,131,206,76,72,207,218,78,90,218,123,120,232,75,223,96,126, - 126,133,158,158,40,21,191,200,200,194,18,59,214,246,210,106,249,148,242,5,202,158,75,34,221,2,97,128,157,138,227,4, - 33,137,104,140,229,233,89,156,245,157,4,202,193,204,164,240,43,57,68,221,71,71,186,112,148,32,82,93,70,91,22,102, - 44,129,246,125,132,25,167,111,231,65,206,31,57,73,172,59,73,189,144,229,196,11,135,232,28,90,207,142,45,59,152,146, - 207,244,174,81,106,75,21,186,71,94,200,21,150,126,227,185,240,33,165,95,213,192,68,71,10,150,170,62,31,1,188,85, - 124,120,139,105,64,226,146,51,67,235,111,77,198,188,142,224,115,255,137,86,44,67,53,74,58,104,141,25,137,112,109,95, - 31,219,179,175,111,126,152,6,38,192,156,134,62,19,246,12,183,182,110,180,183,247,202,217,233,69,164,72,115,108,228,60, - 107,122,227,180,91,9,92,55,68,91,130,48,208,120,245,144,229,165,44,210,202,80,174,130,235,20,217,190,181,135,202,74, - 129,226,138,75,36,146,34,48,67,178,185,34,61,241,24,187,175,218,198,99,207,159,100,239,182,1,234,94,29,101,36,16, - 50,66,185,28,195,49,60,108,51,32,87,9,169,73,159,125,235,186,233,236,78,115,234,220,4,199,143,156,163,94,49,216, - 50,180,150,120,220,199,169,251,108,221,188,145,83,135,142,114,250,244,52,233,214,20,157,61,93,156,56,57,65,95,107,134, - 84,139,32,29,137,145,155,206,147,43,213,105,221,49,72,117,105,5,225,25,216,82,147,72,26,212,202,5,74,249,25,44, - 11,12,67,16,202,40,166,246,9,107,115,196,226,105,38,199,102,105,235,233,38,38,77,210,153,36,243,231,79,179,118,235, - 62,156,76,27,178,90,163,61,109,176,60,91,162,183,31,114,97,157,195,241,72,251,213,149,250,78,19,182,234,138,63,251, - 217,138,95,252,143,175,193,92,221,13,68,86,1,232,117,17,249,90,236,126,45,5,136,55,70,121,125,37,240,145,151,60, - 74,8,28,217,188,229,117,127,174,57,96,188,193,253,108,211,49,123,215,242,166,13,237,174,136,178,130,226,232,124,141,137, - 185,101,54,111,28,196,169,214,136,69,18,228,139,53,234,174,67,97,165,132,33,13,180,8,8,117,29,116,141,193,254,78, - 74,249,2,201,88,6,169,35,184,149,0,165,5,151,239,31,226,206,107,215,83,171,133,140,205,150,9,181,135,246,3,74, - 85,143,26,101,12,195,162,80,87,228,114,69,214,36,91,217,186,126,128,74,81,113,228,217,89,170,213,40,123,47,223,192, - 238,61,237,84,75,33,189,131,59,89,200,213,121,230,217,83,164,18,146,189,123,214,178,176,156,39,8,108,90,210,22,201, - 136,164,88,83,76,46,174,176,48,51,71,186,181,3,35,18,199,173,86,241,106,14,241,168,137,227,212,88,94,92,194,173, - 150,168,151,114,104,183,138,10,61,138,217,5,76,29,176,56,61,205,242,236,12,97,173,68,52,18,165,86,40,99,20,231, - 233,104,109,161,230,133,132,190,198,201,151,88,158,93,228,150,107,246,225,108,236,140,157,128,173,54,28,4,214,108,7,235, - 5,26,197,221,134,95,133,159,49,224,126,26,45,145,86,193,231,45,206,1,105,41,26,10,145,126,125,253,8,134,161,191, - 37,248,0,72,165,112,98,49,78,89,22,117,223,127,221,80,190,4,166,108,104,63,251,167,6,82,91,11,67,182,204,21, - 10,248,85,55,44,158,56,231,236,218,191,62,222,22,141,9,207,169,32,140,56,213,186,143,101,155,132,94,136,129,196,113, - 107,4,94,157,246,182,4,17,203,96,33,191,66,168,20,129,22,44,231,74,68,146,130,237,155,187,232,138,105,134,122,186, - 153,205,86,17,134,133,143,166,226,107,204,168,71,224,184,104,124,210,41,69,87,123,134,207,63,114,152,145,169,42,217,108, - 137,116,91,138,150,13,67,140,207,140,210,155,137,17,181,202,28,121,106,4,203,15,184,249,166,61,228,10,75,44,47,231, - 73,164,186,104,77,43,80,146,217,229,58,21,108,38,70,70,160,126,43,201,76,6,191,94,129,168,73,128,160,173,53,73, - 110,49,75,210,110,35,84,154,168,22,141,14,32,245,58,181,220,50,150,10,88,30,31,165,51,38,48,149,34,157,105,97, - 242,204,11,108,236,111,103,228,228,9,90,99,157,196,82,6,227,231,206,49,184,161,143,95,251,141,159,230,19,191,249,103, - 131,3,211,43,87,167,97,100,16,150,214,193,98,203,171,56,87,47,52,181,159,85,239,215,15,0,9,253,189,130,80,163, - 135,245,119,175,65,89,134,230,252,82,140,175,31,111,197,54,191,25,124,0,204,32,96,182,171,151,199,110,184,140,205,76, - 17,190,150,124,148,33,16,121,23,255,153,121,52,216,41,24,148,182,177,109,177,61,222,94,10,125,188,154,230,170,195,167, - 244,181,42,112,39,135,122,35,97,221,51,237,136,77,165,230,80,119,5,145,168,141,82,26,83,154,132,174,34,12,13,58, - 90,218,169,151,235,56,117,15,199,245,89,42,20,81,166,207,186,53,93,156,58,125,142,53,215,237,166,61,29,50,53,94, - 71,102,58,200,57,117,164,97,163,188,24,78,221,99,219,150,1,114,115,115,36,99,146,122,201,32,105,11,118,95,213,133, - 165,5,143,127,245,97,202,150,73,255,80,146,222,169,4,235,162,105,222,127,215,78,18,241,20,71,142,157,37,145,76,98, - 133,1,177,136,77,190,92,35,87,241,137,198,50,44,205,44,82,92,204,17,239,104,195,117,106,16,106,194,32,164,163,53, - 69,118,120,140,206,140,32,40,231,105,109,15,176,35,49,34,82,80,90,156,167,51,19,227,228,209,179,248,67,29,132,190, - 166,165,181,149,233,169,97,34,134,69,111,58,205,226,114,137,100,87,27,237,49,131,211,207,31,231,234,155,174,226,182,95, - 125,159,253,248,127,252,196,142,187,43,222,213,30,156,125,26,10,55,128,27,127,149,166,44,191,10,62,63,56,0,244,61, - 129,144,10,27,149,114,190,23,11,78,128,231,55,62,40,191,205,231,181,227,211,122,199,229,220,114,211,32,248,175,97,76, - 116,212,132,99,89,170,207,204,243,28,68,4,116,85,226,86,207,76,44,98,230,243,130,203,207,12,115,192,113,228,61,109, - 233,84,34,106,154,245,114,133,68,50,73,174,92,197,215,6,81,105,162,128,192,15,81,74,18,4,10,195,20,184,174,71, - 185,226,178,82,113,8,12,131,206,238,65,182,236,220,197,220,169,231,169,215,61,44,83,35,13,131,154,235,226,6,130,56, - 54,149,165,69,174,189,241,0,43,203,51,100,90,90,153,93,206,210,27,85,252,232,29,87,115,195,45,123,120,250,201,163, - 12,182,230,241,80,140,206,79,115,126,120,153,229,214,58,219,74,91,145,211,231,169,121,33,65,8,237,209,128,90,5,38, - 22,11,84,93,69,75,170,149,236,66,145,243,231,199,217,158,138,160,188,42,166,157,34,116,125,210,9,155,145,92,158,226, - 114,156,72,202,194,169,228,81,161,143,82,38,197,66,133,150,142,54,234,149,2,203,217,44,173,201,4,182,109,2,22,174, - 87,34,211,102,227,87,163,76,205,231,88,187,111,3,229,92,150,217,153,37,174,62,176,149,133,15,94,219,62,241,183,15, - 237,29,130,189,192,248,121,152,223,253,166,229,36,86,229,13,5,160,151,130,144,250,215,193,231,251,229,128,196,119,130,93, - 2,225,121,80,246,112,188,215,112,201,121,33,86,205,191,48,208,73,9,221,217,184,108,61,47,163,12,78,140,115,121,174, - 160,179,160,139,29,29,70,171,52,241,132,192,215,6,78,40,240,131,0,132,65,168,160,230,6,248,210,34,212,14,97,88, - 193,113,13,20,49,140,88,130,236,236,28,207,158,56,204,87,30,120,150,119,223,184,19,66,133,34,69,16,113,240,189,50, - 86,24,163,86,169,113,112,111,134,158,78,205,200,249,42,158,105,176,88,45,242,254,219,182,113,227,141,251,120,228,248,56, - 71,79,77,144,136,117,82,43,215,56,184,125,11,191,245,43,123,89,88,28,231,190,135,143,112,236,252,18,189,3,253,12, - 181,37,136,69,5,147,179,37,114,249,18,177,84,138,68,196,162,88,23,12,159,27,103,243,246,117,84,86,150,200,152,38, - 129,231,19,248,46,149,98,157,165,133,101,50,97,28,211,180,0,19,203,142,224,212,139,4,142,133,20,33,203,75,203,196, - 227,54,34,8,233,78,119,49,154,205,163,18,96,135,17,90,204,8,139,75,75,108,221,190,133,236,114,129,254,181,29,92, - 125,231,205,60,246,208,185,245,3,19,179,151,197,225,248,60,228,55,128,243,253,164,76,132,77,243,107,21,128,126,0,1, - 232,69,16,18,175,41,248,124,199,167,156,212,20,170,38,165,186,137,149,146,4,175,209,178,211,9,139,200,87,38,200,129, - 225,67,91,28,6,71,205,68,107,109,46,199,205,139,133,170,173,9,231,77,17,9,123,218,109,223,13,81,82,80,115,53, - 1,6,86,196,32,12,21,1,10,95,73,28,213,232,187,5,18,199,215,56,129,96,38,91,224,200,240,24,185,66,25,37, - 35,60,118,124,152,95,184,235,50,42,85,240,80,132,161,70,121,117,218,146,46,215,223,114,61,95,252,234,97,42,53,147, - 66,121,158,171,118,173,231,242,61,219,152,61,63,193,200,211,199,137,201,22,150,75,5,122,6,91,120,247,123,222,70,123, - 52,164,191,67,163,61,77,189,22,97,114,102,153,254,116,130,106,96,144,47,231,233,110,73,163,109,139,154,83,197,83,154, - 209,243,147,120,181,18,94,181,128,114,91,49,16,212,42,21,220,80,83,173,56,196,226,38,97,50,164,232,172,16,73,196, - 80,126,29,191,90,34,30,143,145,95,46,210,217,213,142,235,86,137,69,34,8,211,192,182,18,232,160,206,192,96,55,11, - 217,9,178,133,42,81,203,98,108,100,134,13,219,183,179,233,67,55,181,204,252,193,167,246,12,193,30,15,198,70,27,90, - 208,247,108,61,105,26,9,168,171,113,63,63,160,0,212,0,33,121,33,39,226,101,127,120,125,173,110,83,106,22,10,17, - 62,127,184,135,247,113,156,104,169,134,146,175,1,8,69,12,196,112,158,42,88,26,186,149,45,215,140,214,189,212,45,181, - 122,169,191,234,157,243,193,46,180,199,214,183,116,219,17,199,113,176,19,54,78,45,192,247,3,220,48,192,22,22,142,227, - 161,100,148,98,65,81,200,149,184,108,219,16,229,98,141,108,190,196,249,169,41,234,129,203,109,119,221,198,35,79,62,195, - 120,182,192,216,146,162,82,171,98,40,31,29,196,112,41,243,158,119,30,96,41,95,226,252,116,1,167,88,227,198,171,215, - 178,119,251,58,254,215,23,159,64,27,22,182,52,153,95,158,227,224,181,59,184,237,214,171,201,196,77,202,203,115,56,85, - 56,125,122,150,182,182,24,109,109,235,89,90,92,97,37,167,217,176,113,13,182,97,51,54,91,160,98,40,180,33,41,172, - 20,88,158,159,195,112,107,204,207,205,146,238,237,195,148,146,88,52,69,177,148,39,98,67,220,78,96,199,99,148,253,2, - 58,244,41,23,86,144,192,226,252,50,155,214,15,225,84,170,24,177,4,117,215,33,226,219,40,167,128,163,11,116,117,118, - 50,61,58,207,198,93,235,88,156,89,198,52,206,177,229,109,123,197,99,95,124,118,157,119,110,228,50,27,142,47,195,74, - 245,251,208,130,70,128,5,126,112,34,115,47,180,251,190,180,163,136,15,108,7,10,64,180,249,218,109,66,80,3,254,127, - 64,43,200,19,64,7,176,95,32,42,32,109,13,69,208,25,96,14,212,156,144,106,141,148,220,22,190,10,1,160,90,191, - 1,227,45,52,66,135,47,49,135,244,27,112,238,216,166,98,44,151,160,240,143,231,25,92,124,237,146,83,235,192,50,68, - 109,232,94,50,69,111,143,172,235,43,115,225,41,87,115,196,132,181,174,157,88,23,137,199,168,20,115,152,106,128,114,169, - 140,138,40,100,16,226,25,18,169,34,248,182,197,220,202,40,145,192,71,134,1,110,16,16,218,138,80,123,220,125,235,205, - 12,172,93,207,195,135,158,192,117,66,166,86,106,212,61,129,210,38,117,127,133,91,175,92,199,182,141,235,248,155,207,60, - 207,242,138,195,205,151,247,115,231,141,59,8,48,145,113,139,231,78,206,177,110,176,139,247,189,255,26,246,31,216,141,54, - 193,119,92,12,51,198,244,226,18,115,139,85,140,68,18,148,79,38,99,114,228,236,57,118,238,186,3,175,84,197,50,12, - 240,192,50,4,150,116,152,157,203,179,169,51,197,236,196,4,177,182,86,132,147,37,244,28,150,43,144,72,24,20,202,117, - 218,13,16,150,73,40,12,106,78,128,169,161,88,88,161,144,207,34,157,18,113,101,131,39,241,66,80,210,164,156,119,88, - 211,27,67,198,45,10,181,10,45,221,105,38,78,158,101,115,75,130,214,247,92,223,58,247,159,71,246,174,133,61,53,24, - 27,129,185,189,223,163,22,228,208,112,189,191,85,0,72,240,205,137,178,33,141,96,215,43,105,148,253,213,96,244,129,92, - 0,121,4,44,31,34,239,1,227,253,52,98,133,47,92,39,214,32,223,77,31,34,151,131,84,160,115,166,140,251,82,38, - 2,95,99,106,37,114,90,7,49,33,150,93,59,146,141,168,176,74,248,253,171,13,226,141,31,239,55,6,124,46,136,101, - 194,211,251,246,96,222,55,135,255,26,45,18,191,177,80,82,22,244,22,44,187,115,171,171,151,173,192,59,18,192,88,96, - 136,181,180,167,109,173,4,146,8,190,239,98,68,108,44,219,100,114,97,146,245,29,237,248,41,201,161,83,195,108,236,234, - 197,162,68,169,236,82,117,52,245,42,172,233,105,227,238,187,174,227,239,62,251,69,214,12,117,147,27,89,96,169,84,66, - 186,62,158,27,210,55,144,225,166,171,247,144,205,213,120,250,216,48,91,182,36,121,239,59,118,33,148,197,3,143,156,96, - 102,106,137,24,54,43,139,33,209,222,237,24,9,69,80,145,232,48,192,208,14,51,195,141,54,207,74,91,72,71,34,173, - 50,251,247,108,98,97,106,12,167,226,35,147,73,132,43,81,94,149,164,29,101,102,114,142,205,125,187,201,231,87,200,228, - 86,136,25,38,90,249,56,1,84,29,15,179,34,136,26,130,138,227,208,209,223,141,31,56,104,173,240,253,144,66,161,72, - 92,56,216,118,128,16,6,85,167,2,72,42,101,7,217,103,82,173,46,51,20,31,228,233,51,227,108,90,51,200,233,103, - 159,99,205,174,203,121,114,99,223,134,129,243,115,7,34,112,44,7,185,58,56,177,239,97,174,14,243,230,46,187,161,94, - 166,221,12,2,105,16,43,96,252,58,136,182,6,125,21,5,236,63,7,233,131,229,8,50,129,38,213,9,209,18,180,216, - 208,33,26,101,181,69,243,154,34,124,209,244,180,37,196,107,96,9,80,218,87,41,80,45,102,195,159,35,45,112,208,250, - 240,86,207,125,112,9,38,254,30,130,239,119,231,254,248,27,11,64,111,44,248,64,195,37,63,190,117,59,127,240,252,243, - 156,207,46,189,234,93,15,170,192,31,129,56,8,137,58,244,120,97,16,27,10,229,168,15,167,36,132,117,73,138,76,204, - 244,157,0,219,74,162,148,196,138,25,60,125,122,150,106,181,196,250,193,54,74,51,211,129,59,54,73,164,175,197,172,59, - 121,132,53,128,227,135,204,78,101,121,231,59,175,35,26,79,226,155,9,182,110,106,103,206,181,176,45,3,223,146,4,58, - 228,142,155,174,34,30,143,113,232,244,56,233,4,252,244,135,175,198,204,68,121,232,171,243,140,158,90,226,230,245,189,108, - 218,210,199,200,82,158,175,125,250,51,56,239,184,145,253,251,215,32,178,14,245,108,141,137,169,105,100,50,129,17,212,49, - 227,81,106,142,230,242,29,107,89,219,187,158,143,255,229,103,136,217,22,130,8,17,4,81,108,166,70,39,152,223,182,6, - 43,26,101,250,220,8,109,49,147,88,196,98,178,94,161,221,183,136,56,6,21,17,48,187,148,195,76,164,72,196,37,10, - 141,109,90,44,45,46,211,223,17,197,245,92,164,105,226,251,1,166,105,224,120,14,110,208,56,221,205,192,97,118,116,78, - 205,44,150,197,157,7,7,197,194,232,4,246,149,187,83,203,231,231,118,117,195,182,16,206,253,41,56,135,248,206,235,70, - 95,168,251,220,10,108,105,254,255,205,96,62,133,151,252,187,187,9,54,117,48,222,222,0,3,179,15,18,26,210,37,104, - 233,129,136,130,88,8,93,10,218,234,13,16,137,26,154,238,0,58,60,136,185,208,186,212,232,194,107,215,65,42,137,148, - 45,81,211,76,181,27,153,116,43,73,219,22,178,37,110,215,45,195,202,248,4,90,41,171,144,138,70,77,5,195,139,139, - 166,58,57,86,221,83,175,216,105,173,142,181,193,212,171,69,154,152,63,172,224,115,193,6,245,108,155,223,236,235,101,83, - 118,233,85,215,130,4,144,23,24,37,77,204,144,36,83,17,225,91,43,238,24,130,73,67,211,89,71,91,85,203,48,133, - 150,40,45,48,12,240,74,94,232,77,158,87,221,91,215,90,132,161,190,245,196,72,184,211,136,232,115,182,52,116,61,46, - 92,71,83,171,6,4,129,203,219,111,191,150,19,203,57,58,187,50,244,245,174,97,75,79,63,253,201,144,163,243,37,6, - 54,15,178,177,183,13,87,216,76,45,151,249,185,15,221,202,96,91,43,15,30,26,102,106,118,146,159,124,255,21,12,118, - 39,0,159,237,7,215,114,71,165,204,67,135,206,240,130,146,236,31,138,48,159,203,147,243,125,44,171,149,208,119,49,35, - 30,137,68,156,253,59,215,178,178,88,162,119,176,143,201,98,153,122,221,167,63,29,37,34,76,74,181,42,103,71,167,25, - 234,76,178,48,62,67,172,173,133,68,34,138,167,53,133,82,141,132,29,161,46,52,232,40,217,197,60,201,161,118,10,43, - 43,152,194,160,82,170,19,25,108,167,92,173,16,248,1,82,8,132,144,4,74,162,13,19,97,219,148,124,135,43,194,186, - 119,246,159,159,50,102,7,127,204,138,71,193,78,217,204,36,173,129,158,138,191,222,134,150,20,100,243,160,163,223,169,163, - 178,201,121,116,189,193,128,115,1,116,90,26,38,145,184,12,100,103,195,237,16,217,12,81,175,209,164,50,19,133,120,0, - 45,1,244,3,253,17,232,213,144,240,33,234,67,187,111,209,90,4,171,22,137,70,172,206,174,132,234,104,137,120,221,153, - 136,234,107,183,253,100,218,112,181,166,181,107,128,150,206,62,58,122,162,100,50,17,146,241,56,81,163,5,105,36,209,70, - 17,219,174,97,153,41,86,170,113,142,63,119,26,249,169,79,234,76,224,23,98,176,160,161,178,8,218,121,149,8,123,243, - 135,22,124,154,98,40,197,244,129,203,24,56,125,154,136,239,191,234,9,170,105,67,26,62,196,170,40,35,29,181,23,12, - 237,159,83,66,47,40,65,107,104,72,225,106,139,184,97,97,154,6,158,82,12,30,59,18,252,70,165,194,61,118,82,119, - 158,154,100,99,37,176,166,90,147,74,70,219,132,81,215,40,63,164,86,170,177,125,91,55,109,3,41,138,217,113,166,38, - 167,184,245,230,247,112,253,190,62,22,31,253,18,207,157,112,56,120,112,7,17,91,242,252,212,50,201,100,140,237,123,182, - 114,98,116,146,104,107,47,107,247,71,248,203,7,79,50,50,159,67,71,12,58,91,219,185,253,242,157,220,118,211,110,142, - 29,158,225,72,49,65,217,247,177,12,19,35,16,32,21,53,167,206,186,161,94,122,58,51,140,158,155,64,218,38,137,76, - 11,139,217,89,54,247,15,161,180,34,17,77,50,57,189,200,250,190,118,68,168,41,230,202,68,35,22,210,128,82,205,163, - 43,16,184,82,35,164,77,110,185,76,119,103,10,161,37,82,107,170,85,15,207,83,212,106,53,84,24,98,154,38,94,16, - 18,4,10,164,69,44,153,196,215,96,91,166,184,9,170,71,254,238,254,136,252,229,59,98,209,164,36,155,238,75,233,202, - 228,128,7,29,59,97,124,59,248,198,119,184,241,101,147,47,249,223,188,49,1,136,94,227,190,114,8,100,9,204,86,136, - 104,72,26,208,26,64,135,134,30,7,58,13,232,50,161,39,132,148,215,40,102,215,225,24,180,228,108,145,172,181,182,89, - 254,154,193,104,106,219,58,187,107,235,70,57,180,109,155,76,116,117,138,104,212,198,52,20,49,91,99,104,141,22,105,36, - 33,82,7,168,48,68,249,17,194,48,66,72,13,109,186,248,9,7,233,183,177,48,86,228,236,51,95,231,133,127,190,63, - 232,62,125,50,123,64,135,103,227,240,180,47,196,67,62,204,174,211,58,216,218,164,23,222,98,0,244,230,2,31,104,148, - 231,40,119,118,17,219,190,131,125,199,142,190,234,215,31,214,90,204,106,148,138,26,37,85,113,79,43,244,9,132,88,17, - 154,80,41,45,221,58,196,132,198,140,69,113,206,142,168,173,243,203,86,214,142,74,237,150,217,183,152,45,187,160,118,106, - 109,158,206,150,68,89,229,13,39,180,240,117,157,253,91,118,147,232,72,227,10,143,227,71,207,49,113,126,148,31,185,177, - 155,66,220,160,187,183,147,205,125,237,132,150,199,240,216,12,87,238,221,78,61,168,208,211,222,205,174,246,36,247,124,227, - 81,254,249,171,207,51,91,174,33,12,31,17,154,124,234,179,143,241,238,183,93,197,31,254,219,219,153,152,56,199,83,15, - 204,16,77,117,224,133,11,36,4,84,20,236,191,108,23,158,231,83,174,186,132,134,65,224,185,116,180,36,169,86,242,100, - 58,90,49,132,201,217,19,231,216,177,161,151,104,60,73,53,95,194,72,68,73,197,108,242,185,18,43,249,42,177,206,24, - 134,101,81,47,7,20,11,14,182,105,99,89,30,85,87,129,54,240,61,15,161,12,208,16,134,10,195,176,168,212,125,218, - 210,9,132,72,50,231,4,34,3,229,253,185,229,250,125,159,255,134,61,112,215,141,70,216,151,140,150,231,232,137,67,71, - 180,145,31,230,231,1,227,95,1,31,1,252,20,175,95,239,121,113,137,217,87,5,174,3,115,25,98,45,208,38,160,189, - 21,90,52,116,27,13,237,102,64,65,191,7,93,158,160,213,137,154,73,63,30,139,217,93,157,102,56,212,111,235,161,129, - 72,106,235,6,99,239,222,93,70,219,192,26,209,218,217,73,38,149,66,16,82,175,22,168,101,243,248,117,151,208,87,4, - 21,141,175,5,210,168,32,209,104,165,64,40,180,89,193,76,152,8,43,67,49,43,41,63,242,156,90,186,255,1,167,242, - 212,211,133,200,114,121,225,54,152,141,194,233,80,136,163,14,156,10,17,83,81,173,202,31,3,45,94,5,13,232,200,235, - 11,64,111,62,240,185,168,5,133,33,79,31,56,192,142,211,167,176,95,229,252,176,64,19,134,144,53,148,126,94,6,202, - 214,48,44,108,163,38,125,5,90,9,29,8,76,219,162,92,171,211,123,98,76,183,131,113,175,101,177,117,122,182,208,94, - 241,206,250,16,169,71,229,134,211,99,19,178,187,59,70,190,110,99,38,51,12,244,102,48,204,56,185,149,2,29,107,44, - 54,175,143,66,105,145,186,97,51,56,56,64,75,20,42,174,102,247,182,45,12,118,166,17,212,104,137,181,162,29,201,173, - 183,222,196,143,158,26,99,105,161,78,58,157,161,230,154,156,158,153,226,51,15,63,201,137,209,113,254,228,255,252,32,142, - 243,2,174,204,16,143,165,8,209,8,2,34,150,162,86,15,89,90,174,163,181,160,94,172,209,221,154,32,102,42,106,190, - 131,23,64,91,60,69,97,165,198,218,222,78,22,23,115,68,45,131,164,13,181,88,138,124,169,78,91,166,14,18,66,5, - 165,98,64,79,87,138,48,200,17,120,62,165,146,131,82,26,165,154,155,68,107,180,214,184,190,135,29,77,81,11,193,43, - 23,116,4,194,8,136,202,100,62,124,230,208,113,99,109,187,37,11,130,84,139,38,238,129,241,88,195,243,248,109,23,183, - 4,114,192,187,128,206,215,208,13,78,243,250,57,16,251,192,168,64,36,128,216,97,65,194,214,180,133,176,198,128,109,192, - 122,23,58,106,208,153,53,232,46,116,180,182,6,3,125,241,204,150,13,102,199,230,33,177,249,178,125,180,111,218,104,196, - 58,219,101,178,165,21,75,36,46,49,222,52,42,112,169,45,173,80,45,228,241,106,53,36,33,162,153,24,174,12,133,22, - 2,67,75,2,237,35,34,18,43,222,142,83,55,89,58,57,198,202,163,247,184,197,123,238,91,142,140,78,207,38,52,227, - 25,56,175,96,220,145,114,174,36,141,25,59,12,103,187,181,42,181,161,131,231,128,9,160,244,214,226,128,222,188,224,115, - 129,140,206,117,118,243,55,111,123,59,153,175,222,131,241,42,46,194,37,165,131,107,97,161,210,150,122,82,85,92,218,12, - 149,117,163,134,233,59,1,50,98,72,211,48,16,150,141,51,126,92,111,41,86,228,162,132,32,226,132,151,175,168,115,46, - 188,32,97,104,74,249,155,111,247,139,65,49,140,235,101,207,176,167,23,23,200,180,40,158,126,230,52,165,37,201,7,126, - 242,110,90,35,37,194,48,141,76,117,176,101,83,59,200,0,203,136,176,177,63,133,214,117,164,178,209,198,50,129,17,98, - 248,109,252,252,135,63,74,217,180,241,204,58,170,170,57,117,116,130,209,145,191,224,200,68,150,31,253,157,79,240,222,253, - 235,137,214,86,168,233,126,180,21,98,72,77,181,144,195,21,105,170,149,144,106,197,37,42,108,18,134,32,22,139,80,168, - 87,113,61,69,79,107,7,249,124,153,174,206,118,132,101,225,185,30,49,91,34,165,65,165,90,160,86,47,17,139,199,177, - 172,8,181,170,143,235,132,160,53,174,227,82,173,214,137,217,18,199,11,209,65,136,144,2,75,218,4,94,128,17,161,145, - 152,187,82,213,113,136,78,65,196,221,188,217,76,34,88,10,20,197,88,44,161,107,245,88,25,172,143,55,72,219,111,239, - 85,122,223,32,191,117,52,79,251,104,229,85,39,158,85,211,180,138,131,60,7,70,8,209,168,20,45,10,186,18,74,247, - 74,232,69,211,229,193,128,7,67,43,146,161,74,79,107,135,222,183,59,97,239,217,26,233,216,185,93,30,216,178,141,158, - 53,253,116,180,247,33,69,180,121,213,0,8,209,58,68,43,7,80,132,126,136,83,174,80,206,47,35,188,34,190,82,96, - 74,66,105,128,2,83,128,169,65,10,141,101,219,120,86,154,249,165,50,163,95,254,186,170,220,123,111,53,250,252,241,92, - 186,86,63,223,213,104,254,122,74,193,152,50,228,156,134,124,183,210,213,245,97,224,58,90,171,58,47,150,169,125,85,247, - 222,155,20,124,36,223,75,61,112,161,249,94,227,9,109,207,101,97,243,22,254,219,232,40,163,103,207,188,154,3,172,127, - 10,106,63,23,132,211,194,13,245,147,155,219,212,238,146,151,150,5,87,4,166,33,61,51,66,197,149,172,29,158,162,29, - 56,19,143,178,207,241,231,227,65,120,216,131,49,23,6,214,87,235,42,81,15,245,189,107,135,228,201,241,37,242,11,211, - 74,162,228,23,255,225,94,238,121,226,24,29,109,30,239,253,237,95,2,87,178,166,205,192,146,146,208,215,152,26,148,14, - 240,132,129,52,53,132,38,10,65,96,215,233,222,121,128,132,175,41,101,115,56,134,207,76,253,36,50,97,208,167,109,150, - 202,43,124,237,148,207,71,175,184,130,201,229,89,98,233,20,113,13,201,214,4,139,229,10,181,64,17,56,117,162,113,131, - 192,52,145,70,4,215,171,18,132,154,76,50,65,189,86,103,114,114,154,214,100,138,74,190,136,33,162,216,162,74,93,88, - 44,149,20,27,226,6,66,249,20,234,14,29,42,13,150,69,32,45,10,133,26,209,142,40,158,14,240,180,137,36,64,154, - 10,39,80,180,119,246,82,158,93,193,46,84,132,134,212,177,238,54,59,181,166,93,82,243,88,200,57,132,158,27,54,220, - 10,255,250,98,211,29,49,42,31,222,192,232,137,195,175,10,216,248,77,18,59,11,98,47,24,181,70,220,87,42,2,109, - 115,130,22,67,138,238,152,102,67,160,244,134,26,172,45,27,244,122,93,45,45,198,150,237,233,250,250,181,137,158,235,175, - 180,46,191,250,160,232,29,218,68,220,74,54,129,198,107,130,141,131,82,30,34,84,8,165,192,48,17,134,129,10,60,74, - 133,101,156,82,25,28,15,67,105,124,35,64,10,11,48,16,10,4,10,211,16,88,241,24,165,186,203,243,39,198,152,249, - 198,131,97,237,222,135,138,61,83,75,115,107,97,202,128,147,2,94,240,225,84,8,243,62,84,66,165,188,130,70,175,208, - 72,182,211,52,226,217,94,147,195,255,77,170,148,124,215,38,185,105,104,202,117,131,39,207,165,190,169,12,235,119,180,144, - 180,38,33,37,31,187,235,29,124,74,41,142,15,159,123,117,76,48,224,48,232,15,47,85,131,54,224,137,152,197,254,177, - 162,246,5,58,162,66,165,13,137,51,59,205,166,21,175,230,131,231,137,192,90,231,233,211,30,60,35,165,88,118,37,107, - 211,62,103,133,98,192,175,185,93,29,53,167,124,176,37,145,237,50,195,181,119,175,247,141,53,102,63,67,91,214,179,182, - 51,133,242,67,82,182,137,144,146,80,11,132,48,80,65,136,41,52,104,208,194,64,104,133,22,81,140,84,11,45,166,69, - 75,166,135,170,91,226,252,223,252,21,3,235,123,200,46,45,162,86,66,114,75,14,247,157,26,230,198,61,131,12,15,143, - 113,249,213,7,233,239,239,226,137,135,14,81,114,5,158,103,210,154,138,18,137,74,202,78,185,65,88,155,38,166,109,224, - 148,170,96,4,164,162,49,180,144,13,198,32,240,137,167,146,148,234,101,92,47,196,48,36,65,16,82,173,59,8,36,65, - 8,94,160,48,140,8,16,160,53,24,166,129,86,30,160,72,180,164,8,135,71,117,199,114,77,30,49,236,232,226,142,205, - 70,151,225,224,36,35,172,61,114,162,180,51,84,199,125,152,78,130,243,175,45,106,239,238,181,232,206,24,120,234,123,6, - 157,11,191,195,134,185,103,196,32,102,65,70,64,103,18,6,12,88,167,96,157,214,116,215,66,221,145,179,228,96,126,235, - 186,238,244,181,87,166,214,221,118,139,53,180,255,0,109,125,253,36,162,9,26,141,159,125,52,146,80,151,26,166,19,205, - 138,16,186,81,23,66,27,141,240,10,25,132,56,203,57,156,124,145,192,245,208,194,71,9,159,64,42,108,47,5,34,68, - 154,130,72,52,129,39,108,166,39,23,56,253,232,99,122,241,190,251,234,177,19,199,178,61,117,127,178,3,206,1,195,72, - 70,208,98,212,215,122,78,64,201,129,224,113,224,61,26,166,121,125,58,130,252,64,0,144,105,104,170,174,228,211,79,117, - 50,151,183,137,88,223,219,208,133,74,97,72,201,143,223,253,78,254,241,171,247,112,244,85,210,132,4,141,72,219,94,224, - 231,78,47,19,184,65,16,66,45,229,134,165,104,189,70,218,93,10,218,20,35,161,41,103,91,133,142,24,129,122,18,33, - 142,99,136,101,195,70,201,90,184,16,129,219,163,179,227,173,183,153,134,185,46,214,18,141,218,49,125,112,255,70,54,236, - 18,100,29,133,19,4,216,34,138,208,32,48,27,105,47,82,162,9,137,232,16,95,25,104,17,34,9,49,100,43,161,142, - 162,133,194,138,90,204,44,207,209,179,166,133,236,82,1,35,19,161,51,235,50,59,186,204,211,19,83,116,182,152,116,182, - 182,18,105,137,96,104,193,244,228,34,133,90,136,29,137,147,180,45,132,17,176,92,171,209,22,111,193,182,77,74,181,50, - 150,105,18,145,38,217,165,28,137,100,26,195,240,240,125,31,76,80,65,72,177,82,35,22,75,130,10,240,92,31,59,26, - 37,240,67,10,165,42,126,79,11,90,52,180,102,67,10,124,191,17,174,175,77,129,187,88,81,158,130,83,219,55,25,109, - 221,157,72,81,161,245,169,99,229,107,151,139,15,75,205,215,93,56,187,5,234,223,174,52,135,247,158,117,184,63,181,5, - 81,169,126,207,139,50,13,226,86,48,218,32,226,65,42,215,160,121,134,162,176,41,132,141,14,12,229,161,223,237,104,235, - 52,246,239,79,198,47,219,27,93,119,195,126,235,250,253,91,232,239,24,68,98,161,81,132,40,66,85,67,104,1,72,132, - 12,154,247,145,23,217,29,33,77,36,2,237,123,132,133,2,197,210,50,190,83,193,8,105,104,59,161,64,10,19,33,21, - 102,74,19,216,105,178,217,42,231,159,124,150,153,175,223,235,170,39,159,46,116,46,21,103,246,193,168,13,231,20,156,85, - 112,62,148,204,213,52,133,184,214,78,11,4,9,96,180,73,142,27,188,126,57,113,111,249,212,151,11,224,243,143,223,39, - 248,188,28,132,62,252,142,187,1,94,21,16,18,77,210,238,44,80,116,2,98,16,68,32,23,13,89,138,230,178,193,90, - 51,168,200,144,231,107,113,158,73,36,76,95,149,194,147,113,173,39,59,4,229,41,41,29,52,241,16,174,75,73,33,54, - 184,42,26,109,209,162,98,184,242,175,254,247,33,14,94,115,53,7,111,222,77,170,173,23,93,175,67,165,136,212,10,80, - 4,42,68,72,141,8,0,105,130,112,145,42,64,34,8,13,19,45,192,194,199,17,37,60,25,80,175,251,152,50,78,36, - 19,101,253,174,24,213,179,30,143,156,154,225,221,215,238,102,231,154,126,142,29,27,103,169,172,8,84,149,116,84,17,141, - 71,88,40,214,49,68,2,91,154,164,19,113,150,86,150,72,71,99,72,37,41,22,74,212,3,72,91,54,182,33,113,195, - 0,41,37,139,133,50,131,177,52,182,105,82,42,215,72,201,4,142,227,99,91,49,234,174,143,235,249,104,4,90,43,76, - 41,48,165,198,64,112,104,50,43,135,147,105,177,123,87,15,126,80,163,235,208,169,194,129,201,149,135,77,248,188,7,143, - 9,88,252,57,80,83,175,176,176,47,144,194,159,122,247,58,182,3,206,119,145,72,16,208,168,146,40,64,60,3,137,46, - 104,87,208,173,161,39,10,107,21,108,168,194,166,9,201,250,234,250,53,93,173,55,220,156,28,186,253,22,123,224,224,54, - 186,6,250,137,26,177,198,167,117,136,14,61,180,172,163,209,13,62,69,112,17,128,16,2,113,9,101,33,53,72,29,224, - 215,29,138,185,37,130,74,30,194,56,182,106,107,104,77,162,138,145,180,9,173,12,149,130,207,216,115,231,89,122,232,33, - 183,250,192,131,249,216,212,220,194,122,173,231,18,48,34,224,76,0,195,10,166,21,228,138,80,233,85,248,109,155,218,208, - 107,91,201,156,88,196,91,172,124,91,208,17,151,104,124,171,0,244,26,129,207,165,32,4,188,106,32,244,203,192,7,47, - 57,85,206,65,48,39,200,107,197,66,87,33,91,233,180,236,101,31,206,200,152,124,50,210,106,231,163,243,110,126,113,119, - 135,255,111,71,11,234,63,7,218,5,12,101,202,248,160,8,141,116,45,192,137,39,164,83,13,196,154,238,30,222,113,227, - 94,84,34,137,236,221,140,118,43,184,99,103,208,78,1,105,134,8,161,64,75,2,109,160,81,104,29,66,24,130,159,195, - 84,30,138,4,161,174,179,152,159,229,217,167,143,147,157,112,9,253,16,105,91,236,220,63,200,14,175,151,199,14,157,103, - 114,165,198,117,251,47,227,11,95,251,26,11,101,72,89,38,173,73,131,188,83,161,92,9,105,77,165,176,76,240,156,26, - 82,74,52,130,114,217,37,87,172,19,213,146,88,139,77,60,158,160,86,113,136,68,44,170,181,128,186,235,97,1,126,168, - 113,253,16,203,182,9,148,64,55,141,15,21,42,164,173,209,66,19,49,36,65,224,51,177,52,45,250,111,56,32,156,154, - 71,234,169,163,197,131,185,242,55,20,124,78,193,227,54,44,236,132,96,188,49,190,223,82,220,122,128,252,46,58,138,57, - 64,1,140,27,32,42,161,189,14,91,76,56,32,97,83,21,250,114,208,95,237,77,119,26,119,222,210,214,255,238,119,219, - 187,14,238,166,167,187,239,197,130,122,90,65,232,190,168,210,75,129,198,110,150,44,22,141,121,145,205,26,50,58,104,2, - 147,198,64,163,3,159,90,62,71,181,144,39,244,61,148,148,88,113,15,195,20,40,146,84,43,41,150,94,56,173,86,238, - 255,107,103,249,137,103,202,242,252,84,182,37,8,167,6,224,172,132,17,13,83,33,76,187,176,216,1,165,4,184,213,102, - 16,225,105,224,39,223,191,3,239,195,123,80,227,121,156,223,127,148,241,103,102,144,188,114,63,52,221,32,213,169,1,87, - 208,104,91,109,3,191,14,148,127,24,1,232,181,2,159,151,131,208,7,222,113,55,119,172,228,48,151,150,190,39,155,56, - 108,14,242,151,154,150,126,243,52,209,221,154,98,0,103,215,19,30,201,132,65,46,132,225,120,38,154,45,38,35,229,167, - 41,187,31,61,216,205,246,243,5,162,245,144,58,40,165,116,208,231,135,174,4,229,24,22,237,153,148,216,183,206,198,155, - 29,65,119,15,96,244,121,205,218,209,141,133,44,66,191,17,243,97,68,80,134,36,212,33,66,107,164,214,232,242,28,42, - 55,134,213,127,128,197,149,2,133,98,145,160,102,224,86,61,28,63,143,233,38,41,45,151,233,27,104,99,123,161,151,115, - 195,19,60,119,252,28,75,43,57,20,6,61,233,54,12,83,242,194,201,83,172,31,88,135,109,248,24,182,65,173,236,17, - 139,197,240,67,152,203,21,241,180,69,80,13,40,152,117,44,59,130,161,170,152,210,66,152,17,60,165,176,100,35,70,193, - 241,21,150,29,65,171,11,44,178,64,235,16,83,154,212,252,144,68,50,70,185,232,48,212,191,14,119,121,153,190,67,71, - 151,175,170,235,71,52,124,46,3,143,231,96,225,73,8,175,249,22,188,197,26,26,45,150,87,190,67,126,71,54,41,224, - 69,48,92,136,71,160,91,194,70,9,59,44,216,191,4,187,178,157,173,61,246,45,55,166,215,190,251,174,200,198,107,175, - 164,191,127,8,3,7,133,36,84,1,154,0,83,6,77,156,177,65,11,2,195,69,96,33,154,126,86,173,21,66,132,205, - 140,44,141,198,70,160,144,58,36,112,234,212,242,121,220,90,5,75,8,146,169,52,117,223,101,100,58,203,249,163,167,117, - 238,240,11,202,59,114,156,158,201,217,122,79,213,153,26,128,51,18,134,53,156,15,13,57,42,18,246,12,117,63,231,250, - 97,61,222,116,159,141,2,22,80,4,6,219,162,176,191,135,112,190,140,217,147,36,104,143,243,56,141,250,218,127,13,220, - 8,204,3,159,166,17,41,30,3,102,129,25,224,87,155,224,35,224,251,246,24,155,111,85,240,169,56,146,79,63,253,218, - 128,207,75,64,200,48,88,115,227,77,188,251,139,95,32,230,121,223,181,203,246,2,255,19,52,255,45,27,155,65,143,192, - 138,13,79,164,82,166,111,133,70,217,135,227,53,105,84,122,126,108,155,90,99,12,163,86,28,222,237,134,20,32,136,194, - 34,154,163,49,211,138,104,188,158,146,231,244,137,104,210,238,234,74,82,169,46,99,85,210,88,179,35,4,218,67,121,69, - 164,169,209,161,64,138,6,151,16,202,16,169,12,164,150,168,208,199,93,94,164,92,122,148,129,206,61,124,227,235,207,50, - 188,120,158,254,158,22,70,14,159,193,78,70,113,189,42,239,184,227,61,108,220,220,13,127,253,87,220,55,58,205,231,30, - 126,154,181,45,22,25,225,145,73,165,56,61,179,130,167,45,226,49,11,59,34,40,148,203,88,42,130,64,80,40,87,8, - 35,81,220,154,130,138,199,162,95,96,77,127,111,147,12,215,72,51,66,185,82,37,145,137,226,169,0,169,163,40,165,9, - 252,0,167,238,160,1,211,50,26,174,99,203,196,178,77,102,167,230,88,58,62,172,110,28,159,154,217,21,232,39,92,248, - 178,5,143,215,97,241,167,32,188,254,91,140,127,23,240,251,192,31,127,7,0,228,0,237,32,111,4,99,14,98,2,186, - 227,176,197,130,125,62,236,27,131,77,51,189,237,125,153,15,190,51,115,195,207,127,212,216,186,125,23,70,83,95,80,65, - 0,74,54,10,226,153,54,10,137,175,13,164,110,120,35,5,96,104,11,180,68,160,154,161,124,32,154,142,109,45,20,129, - 14,49,5,248,213,42,94,169,220,56,44,148,193,233,177,9,61,252,194,201,202,200,195,207,80,123,230,233,200,186,170,195, - 0,200,76,163,118,40,2,124,13,117,5,66,66,135,161,180,208,37,39,161,160,104,129,31,64,181,8,197,86,168,215,165, - 168,215,162,150,155,142,219,33,125,113,162,90,32,164,226,191,41,197,127,190,100,204,126,189,73,25,156,164,81,35,91,54, - 249,33,221,244,250,25,175,2,248,188,37,1,232,34,225,252,116,39,179,121,155,168,245,218,114,245,194,247,89,90,191,129, - 71,222,243,94,222,255,133,207,97,122,223,127,160,226,116,99,114,235,183,69,140,243,149,76,36,107,44,57,254,12,148,31, - 245,116,240,95,119,119,232,61,55,244,178,248,27,79,179,59,212,76,54,22,208,121,91,235,207,163,25,5,174,15,131,242, - 109,245,96,62,190,41,99,81,171,135,24,122,5,51,63,140,162,225,110,87,194,66,9,19,161,5,82,11,180,240,17,218, - 68,8,65,173,86,197,114,3,130,202,12,71,31,125,132,103,158,62,195,228,226,89,174,189,102,39,243,163,179,44,44,58, - 184,70,141,88,58,193,237,119,126,152,193,182,36,167,206,255,22,95,123,246,40,31,190,114,63,189,182,196,48,235,200,116, - 146,142,238,54,108,83,19,6,18,47,52,136,199,108,10,217,28,190,180,193,142,35,92,31,25,72,156,176,74,177,90,38, - 147,140,83,116,92,76,59,78,88,115,80,97,128,52,76,234,78,195,68,137,68,34,56,110,13,105,68,16,194,0,67,99, - 219,54,42,12,56,117,126,146,53,35,147,185,125,240,100,21,190,160,225,73,15,150,254,13,132,179,205,77,242,74,114,35, - 112,217,37,218,231,43,29,16,186,249,249,24,68,90,27,7,126,79,0,107,34,176,211,135,253,39,96,199,200,64,79,223, - 192,143,191,47,254,158,143,252,132,216,186,101,55,160,80,65,133,80,7,200,166,9,21,24,33,146,8,50,144,72,84,67, - 213,69,19,52,1,72,42,137,144,52,52,30,169,80,104,20,18,133,1,72,44,1,213,252,10,203,179,179,172,100,151,56, - 119,118,148,211,195,227,12,143,78,213,219,202,245,177,141,90,119,237,187,246,42,203,72,197,140,138,97,136,98,224,235,48, - 244,162,241,233,169,181,153,66,61,93,23,166,23,56,245,48,146,205,151,109,215,95,1,42,17,168,75,200,9,88,12,96, - 209,132,145,13,112,54,168,122,43,39,191,58,170,73,88,252,247,167,166,249,167,135,39,94,98,110,5,151,104,147,226,18, - 109,231,213,38,167,205,183,34,248,252,227,83,175,15,248,92,16,203,113,56,53,180,1,235,3,239,228,125,99,15,17,126, - 31,173,240,140,230,98,223,234,43,189,231,150,1,103,204,85,110,252,217,69,253,216,92,153,251,128,63,245,5,110,41,160, - 227,182,53,24,15,76,243,44,40,3,150,251,160,232,151,189,37,13,45,201,124,241,64,97,50,223,174,135,6,8,98,53, - 100,52,131,54,35,40,229,129,110,122,80,154,43,37,208,26,17,154,52,104,93,3,59,146,68,219,53,122,12,77,245,252, - 189,204,62,241,53,198,202,6,27,182,237,230,142,159,186,129,92,161,64,164,213,192,110,171,224,215,231,217,177,115,31,215, - 238,189,10,127,41,135,44,251,120,105,151,157,123,55,49,249,213,51,244,39,210,8,83,80,173,215,73,71,226,44,101,107, - 212,125,3,43,30,37,112,93,16,62,174,112,49,66,73,110,197,193,232,76,128,168,147,208,30,85,101,82,114,5,118,84, - 129,23,16,134,62,177,72,28,223,53,209,166,66,168,0,180,66,74,3,97,180,147,61,123,154,235,97,198,133,167,52,60, - 187,17,22,127,20,212,201,239,194,109,14,32,163,38,36,44,4,166,64,52,74,227,185,192,14,136,182,195,218,0,174,181, - 224,114,9,67,71,97,232,204,186,129,193,117,31,249,96,236,23,126,242,67,108,24,218,222,216,154,170,4,90,32,37,104, - 109,162,164,70,8,129,208,2,161,53,200,176,89,112,71,160,181,70,135,10,132,64,27,18,33,100,67,79,17,23,66,221, - 4,66,55,12,191,153,185,5,22,230,231,177,165,36,217,219,207,149,107,214,115,203,123,83,36,146,201,184,29,139,239,209, - 134,13,72,12,36,47,50,72,46,245,114,177,197,171,214,90,10,117,23,191,82,68,45,206,18,22,115,202,169,213,241,207, - 77,121,198,200,100,85,79,206,151,39,78,141,228,218,43,149,175,217,53,111,101,33,30,47,236,94,219,17,78,254,221,243, - 252,237,51,211,111,88,33,254,183,12,0,73,169,169,56,6,255,244,116,199,235,10,62,23,36,230,212,57,219,191,158,23, - 222,21,103,207,224,10,142,255,189,15,93,10,184,29,112,37,152,83,85,109,28,93,126,105,43,24,5,65,103,12,131,139, - 33,105,234,65,112,175,145,98,73,134,122,36,153,11,102,103,78,206,175,223,179,101,139,97,184,14,66,216,104,105,54,106, - 249,43,208,170,233,71,17,128,144,104,45,176,8,27,175,197,146,208,35,80,78,133,117,25,205,239,255,230,79,243,223,63, - 241,0,95,254,155,47,208,189,126,45,45,237,25,122,58,225,206,159,234,32,48,210,140,29,127,134,31,185,170,157,167,14, - 173,176,84,14,249,233,219,110,66,21,171,104,39,32,154,49,240,202,37,226,182,73,169,90,163,84,171,34,236,8,126,189, - 78,24,134,168,208,199,50,13,132,18,184,158,71,161,84,35,21,181,9,125,15,41,44,252,80,96,95,168,146,41,26,62, - 22,199,181,65,123,196,164,66,40,27,33,5,149,208,35,117,126,182,218,11,163,46,156,201,64,182,23,212,210,165,135,68, - 243,247,191,118,52,84,158,93,196,88,168,49,125,182,160,83,19,53,158,7,43,14,173,29,176,14,184,70,194,109,163,176, - 251,112,103,111,91,219,135,223,17,253,165,255,227,167,216,178,110,91,99,187,171,202,139,228,178,80,104,125,1,232,27,222, - 43,137,113,81,235,65,92,40,252,41,144,23,163,99,197,37,241,61,141,185,185,168,81,104,77,107,75,43,61,221,61,205, - 218,217,151,178,136,23,156,242,206,139,196,182,208,132,190,143,87,173,18,120,46,202,115,233,242,60,252,132,129,183,113,29, - 138,77,50,97,69,176,238,136,68,199,231,115,209,111,252,243,231,218,35,217,201,68,119,133,152,6,217,107,74,230,239,59, - 71,223,201,197,215,45,23,238,45,13,64,2,248,226,225,54,166,87,108,98,182,122,253,239,47,64,187,138,175,62,209,133, - 216,235,179,99,160,72,16,126,111,10,169,110,146,156,134,37,209,190,250,166,217,215,52,194,231,1,54,55,189,12,247,1, - 251,108,195,73,251,225,116,38,208,163,39,159,24,222,51,122,203,158,214,13,17,137,112,125,116,52,104,156,194,77,125,89, - 8,217,44,89,39,80,8,164,14,145,40,28,105,160,34,73,100,196,198,8,3,54,182,69,249,179,223,253,8,95,253,198, - 211,252,197,23,158,225,204,211,19,108,191,233,74,118,245,95,137,191,178,64,75,238,8,190,214,28,159,154,226,231,255,237, - 47,176,53,99,240,197,47,61,65,213,138,96,248,14,9,45,176,60,159,217,66,141,64,130,170,151,137,70,19,248,42,36, - 12,66,108,9,210,48,208,90,81,171,59,180,36,91,0,141,129,129,235,213,73,136,20,74,132,23,249,49,47,208,8,35, - 36,105,106,162,86,156,72,92,82,172,102,105,203,22,139,2,198,108,152,93,6,239,31,128,247,210,136,208,213,77,222,226, - 159,128,31,5,254,27,141,246,58,175,36,243,127,113,138,243,13,173,199,254,8,36,21,244,107,216,103,194,149,57,56,240, - 92,38,186,185,252,182,235,91,126,254,119,255,31,118,108,219,117,209,35,39,116,136,16,47,166,96,94,244,226,11,209,124, - 253,197,72,33,33,26,154,143,66,53,56,33,33,64,74,228,203,154,117,138,38,128,9,209,0,166,104,44,142,16,16,40, - 191,241,94,193,37,224,3,82,27,160,20,129,23,80,43,22,168,151,75,104,223,107,120,205,164,164,174,53,194,87,68,34, - 16,8,139,225,137,37,142,220,255,117,74,95,255,146,187,113,98,101,166,99,185,244,164,47,197,115,166,214,121,103,169,34, - 70,191,112,134,4,112,249,37,252,100,0,180,93,98,154,138,75,158,64,252,48,3,144,210,130,170,39,177,140,55,174,107, - 147,20,154,32,148,60,63,209,198,206,129,2,175,85,184,86,212,146,252,250,87,199,249,23,26,245,97,46,40,235,27,220, - 208,191,75,50,231,193,153,158,137,229,153,195,143,30,107,25,186,243,42,33,170,69,140,116,10,161,26,17,221,90,92,136, - 49,105,28,195,18,8,165,198,71,55,204,17,213,56,173,165,246,9,253,10,66,86,121,247,157,251,184,245,246,203,152,171, - 175,161,84,5,127,101,154,72,249,56,9,237,240,201,167,207,179,239,134,155,216,217,223,78,121,110,154,179,217,60,42,106, - 96,213,29,66,219,68,116,245,241,182,91,15,96,164,18,4,149,10,231,207,141,112,242,228,41,108,211,38,240,124,44,219, - 38,150,136,19,6,30,149,154,75,50,150,64,185,1,74,131,235,42,180,18,132,126,8,177,0,95,5,68,13,3,33,52, - 133,124,158,190,150,30,150,103,150,216,228,185,89,5,99,38,228,74,160,254,170,65,24,95,228,39,198,129,71,129,39,155, - 174,226,87,138,229,105,3,214,129,156,109,100,157,175,51,96,155,13,187,43,112,224,217,72,100,187,250,192,29,157,55,124, - 244,253,198,222,125,7,104,111,25,36,84,46,26,7,137,66,72,235,69,187,182,233,78,191,0,60,151,174,72,253,34,50, - 33,164,184,228,35,226,21,15,213,11,181,81,181,166,193,9,105,133,209,220,246,141,178,133,205,164,92,21,226,59,37,220, - 90,21,183,90,195,119,29,164,166,241,94,173,145,82,225,27,30,190,7,163,39,199,56,252,181,7,116,237,193,135,217,60, - 189,236,109,119,152,83,232,99,190,33,206,34,113,3,45,6,129,150,13,232,218,10,184,127,4,161,120,233,183,99,17,194, - 12,184,123,193,179,32,12,64,249,47,139,169,250,161,35,161,141,55,65,62,171,16,188,230,32,24,26,130,143,20,61,238, - 184,100,146,21,208,171,180,174,41,86,2,33,142,116,184,122,199,210,61,71,187,135,247,108,236,218,220,219,134,84,33,88, - 54,66,169,139,39,150,210,205,152,90,13,218,104,20,61,147,74,35,84,136,8,131,134,166,36,37,129,80,4,53,133,37, - 124,54,12,118,34,186,119,146,127,254,211,104,97,242,213,19,101,162,235,54,242,209,95,253,21,152,59,193,76,161,140,87, - 171,96,187,62,182,109,114,224,174,91,184,249,199,126,134,100,162,163,177,165,66,31,183,84,228,191,253,225,127,229,196,147, - 135,73,70,163,32,124,148,104,84,223,241,125,240,35,26,69,64,168,66,156,186,79,52,102,33,165,137,105,90,13,86,68, - 131,198,34,91,152,165,199,238,167,101,116,165,214,171,24,13,27,26,80,229,243,77,183,240,119,218,62,217,111,186,226,255, - 75,35,182,175,67,192,65,75,112,139,167,217,55,97,152,67,11,183,222,216,187,235,223,124,36,114,227,109,183,17,179,227, - 64,149,144,21,16,2,67,91,13,186,70,7,23,13,189,75,181,150,11,187,86,107,253,178,230,10,151,232,12,23,114,43, - 46,1,41,33,154,237,203,47,124,166,169,237,8,33,64,105,132,214,104,215,39,112,61,188,106,21,223,119,80,65,13,165, - 21,82,9,162,182,133,214,18,33,12,234,142,199,244,232,212,202,249,103,158,173,231,30,122,34,33,142,156,74,116,85,125, - 99,176,57,148,181,198,50,234,36,212,251,129,109,2,28,1,69,9,5,11,106,10,92,1,74,188,148,120,118,4,228,226, - 176,124,225,189,2,138,187,193,139,64,88,7,21,252,176,1,208,15,131,104,91,162,198,138,236,124,102,129,157,175,240,247, - 28,212,206,74,206,248,33,15,175,159,173,245,157,251,242,179,215,247,254,252,237,49,103,114,140,193,205,59,81,58,64,43, - 133,48,26,133,190,80,141,83,212,84,178,1,224,34,36,148,33,161,80,8,37,65,75,164,144,24,202,68,11,77,205,157, - 33,230,117,147,220,112,5,207,191,112,138,106,172,206,199,126,249,231,177,109,131,122,60,67,49,48,192,243,177,162,54,183, - 252,196,7,185,254,157,119,83,170,58,100,179,83,8,199,37,101,26,68,186,58,120,255,135,127,132,225,23,78,18,11,37, - 117,63,192,48,13,148,1,90,11,66,165,9,181,7,66,82,171,55,178,186,209,18,207,13,208,134,194,16,18,165,45,234, - 8,188,186,75,102,116,54,31,133,17,31,166,11,224,118,2,73,94,204,204,22,52,130,228,254,238,21,180,159,11,81,232, - 191,14,70,7,116,20,225,74,27,222,181,160,185,102,118,247,214,190,173,255,207,111,37,223,119,247,123,72,68,108,80,121, - 116,152,3,33,144,58,14,202,108,84,87,150,77,72,191,164,146,187,18,23,186,247,234,139,224,35,94,118,95,160,145,70, - 113,129,43,186,128,53,66,188,168,246,104,221,12,74,108,2,91,216,32,166,67,207,163,144,93,194,171,214,136,72,3,80, - 120,74,224,123,138,48,208,100,179,139,12,143,142,177,148,91,97,118,126,145,229,233,133,133,100,32,196,254,116,50,189,115, - 239,118,77,44,174,114,235,7,68,189,61,99,25,129,209,237,213,85,71,44,212,202,46,231,67,170,101,229,85,92,191,90, - 169,251,245,252,138,175,114,139,158,44,150,125,233,163,162,26,221,56,154,240,58,97,57,218,0,160,172,1,19,6,140,11, - 200,234,134,133,155,141,67,97,63,132,23,28,43,122,21,128,222,250,98,8,65,169,30,242,84,197,127,69,3,79,129,78, - 135,58,107,194,33,19,214,25,79,12,175,27,191,109,231,102,34,17,74,238,41,182,109,223,214,168,193,32,4,58,84,77, - 30,186,97,138,53,56,135,176,201,75,152,141,214,209,161,192,8,65,201,198,194,143,155,105,130,68,18,17,239,96,243,110, - 147,3,215,223,128,21,145,248,165,37,100,162,143,147,211,57,252,100,156,15,253,155,95,97,219,21,151,113,242,153,103,9, - 150,39,57,55,50,130,244,32,25,143,178,249,242,253,244,110,222,75,223,64,55,213,241,5,194,80,225,41,143,132,25,197, - 196,196,247,61,164,33,16,1,4,190,38,176,66,98,182,133,101,198,240,194,42,49,105,83,117,92,42,218,162,54,187,172, - 251,242,249,121,224,188,132,229,35,160,206,54,53,160,75,221,232,15,210,136,83,121,185,172,7,210,141,154,201,253,21,56, - 40,224,206,179,177,216,245,241,95,251,216,192,7,254,237,207,152,189,237,27,208,97,136,242,139,96,248,72,17,111,92,81, - 104,180,104,128,164,86,118,195,172,21,193,69,176,160,105,46,93,170,25,139,139,252,144,190,200,241,160,117,243,35,47,155, - 77,253,34,183,115,1,188,164,110,0,22,90,81,171,84,241,195,16,105,155,248,42,100,37,191,130,171,26,190,76,180,192, - 72,217,108,219,187,157,3,233,20,109,157,93,100,90,90,183,155,182,73,16,58,72,195,215,150,180,69,163,40,137,5,40, - 67,19,52,41,122,31,240,240,21,56,110,72,165,88,164,146,91,160,90,206,227,187,10,157,247,244,232,249,113,49,49,114, - 142,147,199,143,121,198,153,243,181,158,98,173,218,129,206,103,96,33,10,75,22,76,73,120,54,132,103,255,35,44,29,132, - 48,250,61,174,247,215,182,55,60,224,155,175,108,41,26,97,35,42,119,85,94,58,96,66,10,178,17,131,187,191,205,219, - 254,12,130,43,4,51,30,28,238,172,232,125,39,191,114,120,240,237,191,253,177,88,109,121,153,51,103,207,178,105,203,38, - 164,33,47,122,107,80,154,64,4,104,209,152,112,137,1,170,113,44,107,173,80,4,104,12,124,105,147,72,116,99,41,1, - 190,75,71,199,26,148,89,37,12,29,172,84,148,231,30,61,198,11,231,103,249,149,223,252,117,182,238,185,154,165,241,73, - 142,126,253,97,238,190,121,35,235,46,91,203,200,209,17,138,133,69,178,227,22,189,107,215,178,121,93,31,207,156,62,127, - 209,235,92,119,234,196,205,24,50,116,73,183,37,41,4,30,166,105,96,26,18,203,50,65,90,136,64,99,73,197,210,242, - 10,21,97,161,71,243,245,54,152,212,48,62,15,149,71,155,91,217,123,153,137,245,74,43,233,99,192,251,33,150,135,141, - 6,220,92,135,91,206,174,25,56,184,247,47,255,168,231,250,183,223,10,202,71,5,117,144,117,148,233,131,136,53,202,180, - 106,141,32,4,35,68,8,137,194,126,9,67,114,193,84,185,148,152,109,240,34,26,201,37,164,180,190,100,94,181,190,120, - 137,11,36,117,131,211,126,209,12,187,152,34,34,4,241,116,146,88,50,70,168,124,164,212,116,172,29,64,88,241,134,163, - 1,205,139,81,57,170,121,139,0,180,198,178,98,104,146,194,215,160,117,163,252,170,8,21,130,16,101,149,16,161,137,192, - 192,68,145,136,106,82,177,22,68,79,95,19,156,2,180,46,136,203,220,27,81,126,137,165,229,37,123,124,100,218,158,56, - 53,217,50,115,242,201,190,167,78,205,110,159,159,153,11,47,203,174,100,175,242,130,62,95,136,26,90,63,245,52,84,204, - 239,129,19,186,250,181,4,160,6,248,152,104,241,202,196,77,96,10,204,64,173,130,80,115,172,12,192,52,37,248,138,223, - 249,219,211,0,252,39,224,237,47,91,232,33,176,9,24,211,212,29,193,112,20,14,103,14,79,110,63,241,232,195,155,111, - 189,245,38,150,28,147,233,249,60,107,6,50,8,25,34,60,139,128,128,80,106,164,54,208,1,152,90,96,8,133,47,2, - 66,83,161,5,72,101,96,198,90,32,29,33,20,1,194,20,72,93,69,134,10,204,8,94,16,97,105,185,204,175,253,246, - 255,197,208,230,54,116,101,30,63,63,131,95,25,103,236,120,129,84,170,131,45,155,182,50,54,55,66,169,94,34,162,53, - 45,157,173,20,164,75,155,25,69,184,146,80,155,248,202,71,138,16,229,42,44,173,209,134,79,77,185,216,97,28,195,53, - 208,194,2,17,103,108,101,12,153,233,192,158,95,40,70,97,44,132,57,19,188,193,151,141,71,4,248,228,43,152,94,31, - 3,254,45,68,231,96,83,4,238,40,192,93,243,219,55,236,184,227,31,254,170,109,211,222,3,40,85,110,212,163,110,210, - 169,66,73,180,16,141,252,57,104,166,138,54,204,167,70,113,29,129,18,242,165,4,242,37,218,80,35,133,228,165,38,21, - 82,188,196,116,19,205,247,93,228,122,208,223,212,148,243,2,191,36,45,11,129,141,41,227,23,175,161,155,238,251,134,229, - 118,137,215,243,130,141,215,44,183,34,132,110,130,84,67,147,19,6,141,239,170,26,190,46,37,53,161,50,26,26,93,104, - 225,185,43,56,37,7,191,80,196,113,243,132,74,161,101,0,66,178,113,168,159,221,59,118,224,127,232,78,113,244,244,130, - 248,252,23,191,36,191,241,207,159,235,219,148,203,109,237,210,97,183,130,72,47,84,206,164,187,56,157,238,194,250,46,58, - 28,191,102,0,244,175,129,207,139,32,36,127,168,65,72,235,198,26,141,26,130,34,48,50,87,102,231,207,220,207,169,137, - 70,193,203,141,52,90,198,116,188,194,68,41,80,207,106,22,44,120,161,187,194,222,209,175,30,233,155,218,190,33,217,223, - 189,150,176,179,11,45,42,24,161,196,23,17,164,12,145,218,65,41,19,141,68,73,3,36,72,97,98,162,145,26,234,42, - 70,164,109,29,218,72,17,18,109,20,118,11,125,192,68,135,54,74,187,188,237,157,183,99,10,141,90,153,99,250,201,71, - 153,57,245,12,111,223,218,66,107,68,50,90,158,103,161,146,96,253,198,253,28,25,27,195,72,182,146,74,119,17,53,50, - 248,218,197,51,66,2,45,64,248,16,106,44,71,18,145,113,194,208,165,90,211,84,188,16,171,37,192,54,5,185,170,207, - 249,108,133,93,137,20,125,149,106,46,132,169,40,172,168,102,224,97,178,185,198,50,205,177,41,188,108,108,126,17,248,101, - 136,102,97,115,12,238,152,129,119,46,222,124,213,238,187,255,231,31,37,215,110,217,76,232,151,144,82,54,188,84,13,134, - 254,130,241,132,190,36,81,245,34,81,252,175,122,59,5,82,128,80,47,227,116,154,38,154,104,106,57,23,201,231,75,212, - 163,23,95,19,40,173,26,102,156,108,0,141,210,186,17,30,213,52,238,68,211,101,166,185,96,214,93,2,110,23,59,125, - 53,126,139,230,231,27,32,212,128,35,37,18,8,17,34,133,66,234,8,110,177,68,41,55,131,235,44,162,194,70,235,116, - 221,76,71,141,68,50,8,105,48,59,151,227,216,225,167,56,250,196,115,228,15,31,14,183,100,151,10,183,132,225,84,43, - 234,217,16,166,5,184,115,210,224,233,76,47,75,118,20,227,187,220,203,230,171,15,62,226,59,2,159,183,44,8,105,144, - 82,96,197,76,172,240,251,44,80,105,75,44,41,248,171,165,58,127,12,224,134,23,193,135,75,52,158,11,114,164,233,74, - 94,75,163,0,205,54,168,77,195,25,19,158,106,63,182,188,254,248,163,231,246,246,191,175,95,202,176,68,104,24,16,74, - 180,89,65,134,38,82,69,81,210,71,75,8,80,205,69,220,168,19,44,125,144,169,86,204,206,126,132,180,48,0,77,72, - 104,40,12,173,144,8,108,161,17,202,3,41,240,234,30,231,78,62,207,80,74,146,136,36,168,135,2,179,189,141,84,95, - 39,83,243,179,172,219,119,57,164,251,41,151,42,196,81,132,36,208,162,134,208,149,198,169,110,219,84,106,5,236,84,26, - 180,198,112,53,1,18,199,171,147,74,38,89,56,63,227,222,136,161,188,92,33,154,168,57,57,96,97,9,106,91,175,238, - 230,137,159,218,2,213,0,210,22,249,71,231,248,155,191,31,249,38,205,231,23,4,177,5,205,198,40,220,62,13,119,79, - 255,216,123,15,252,212,255,250,147,72,71,50,142,242,29,164,97,18,170,0,169,5,82,24,232,70,78,250,75,72,226,11, - 224,163,255,213,67,228,82,80,225,18,142,232,69,13,233,155,61,100,47,242,68,23,249,34,241,210,251,138,151,93,227,69, - 222,232,165,69,244,245,75,72,111,31,173,26,209,214,186,25,230,173,208,72,83,54,25,251,16,130,16,175,190,76,117,165, - 68,173,84,68,251,145,134,6,108,6,104,43,133,105,25,56,78,192,209,199,159,231,248,253,79,233,236,227,207,184,169,165, - 197,202,94,29,228,214,192,76,2,206,134,112,50,128,19,81,56,87,131,250,54,33,249,188,48,176,3,255,187,46,217,250, - 170,1,144,18,160,132,73,104,200,239,186,4,235,91,9,132,44,75,82,174,133,124,249,177,57,180,254,254,34,33,226,17, - 131,191,252,202,20,255,114,50,247,29,189,255,15,128,231,155,38,199,85,64,23,168,17,88,72,192,179,173,138,109,35,15, - 28,91,179,124,251,21,29,3,177,40,53,203,192,51,92,162,4,160,147,40,34,23,205,12,68,67,77,215,90,19,72,192, - 22,68,187,251,17,102,10,2,129,209,12,156,107,228,41,53,242,201,132,50,192,148,84,189,18,86,58,65,203,250,181,100, - 23,134,9,170,33,45,109,45,12,14,12,16,90,25,18,91,214,147,216,178,155,186,87,229,212,240,9,132,165,17,210,199, - 10,67,162,50,141,210,49,20,1,142,237,81,244,202,72,25,65,38,45,180,97,161,2,143,186,23,232,245,231,167,117,183, - 143,253,180,239,122,17,205,18,176,92,4,239,100,87,140,93,215,246,64,45,96,97,161,198,244,179,217,151,228,120,125,12, - 248,37,136,102,53,155,162,112,251,18,220,189,252,145,247,31,248,217,143,255,69,36,99,27,232,192,105,144,202,8,164,52, - 27,0,163,245,75,65,231,82,96,121,249,38,255,22,135,234,203,65,72,55,181,157,11,17,208,23,92,246,226,18,144,186, - 8,52,151,120,194,94,84,142,244,55,1,20,90,55,211,60,94,10,112,23,238,117,33,250,186,81,73,160,25,151,45,27, - 166,152,20,33,161,239,226,87,203,148,86,86,168,87,138,232,192,66,26,62,210,118,49,173,22,16,113,150,23,151,57,249, - 216,51,122,226,95,190,236,196,142,159,92,217,164,84,238,58,88,176,97,76,193,48,48,225,55,126,230,4,20,43,141,96, - 126,173,208,24,250,66,100,208,119,169,1,133,230,171,83,130,61,16,223,95,144,206,91,1,132,76,195,32,84,1,127,250, - 233,251,57,55,49,254,186,223,63,74,163,92,194,245,192,205,192,127,111,188,230,8,24,213,112,168,115,108,101,231,225,199, - 143,180,245,127,232,46,105,251,80,55,163,104,21,160,241,209,70,216,136,105,1,12,45,65,105,148,33,168,98,17,105,111, - 67,180,182,17,202,176,113,34,53,131,25,181,8,9,180,198,212,141,2,21,210,84,60,248,229,71,57,176,251,74,174,120, - 207,207,224,44,157,34,168,186,152,210,196,136,8,140,88,43,178,109,51,136,56,95,248,235,191,101,252,228,56,41,195,66, - 227,16,183,163,120,142,34,12,11,152,102,140,152,145,198,11,138,88,145,58,166,78,17,170,8,102,44,193,252,217,97,125, - 101,177,110,22,34,166,209,234,82,54,149,88,240,208,57,27,252,142,71,231,248,210,135,30,192,2,126,63,231,242,239,231, - 107,23,83,47,126,190,201,249,204,195,230,8,220,145,131,187,202,63,251,35,251,127,228,47,254,75,52,35,3,180,47,26, - 109,254,154,192,162,155,224,160,105,132,41,188,28,92,132,248,230,141,46,148,254,166,224,195,11,57,237,66,235,151,106,42, - 223,230,122,92,226,134,191,232,194,215,47,94,77,41,133,144,47,166,105,232,151,152,117,77,83,238,2,184,73,9,234,66, - 90,136,213,236,117,214,76,111,65,131,87,167,88,204,81,45,21,209,117,69,160,52,194,210,216,73,3,100,7,229,130,199, - 248,179,99,156,252,250,87,66,241,248,179,229,182,133,133,236,229,48,18,131,51,26,198,53,204,186,48,29,194,130,130,82, - 28,234,62,4,223,0,222,71,163,204,201,247,181,167,180,120,243,116,171,184,0,66,198,155,22,124,66,254,247,23,190,240, - 134,128,207,75,198,9,184,31,184,6,248,91,96,3,228,115,112,188,21,142,156,249,210,161,141,35,55,95,213,185,185,179, - 27,25,104,124,67,99,74,15,41,20,74,54,226,130,100,8,82,24,248,158,137,209,210,65,180,123,35,202,202,160,49,27, - 166,25,141,124,178,6,51,18,130,82,72,21,131,64,176,105,176,131,99,135,238,199,176,174,165,181,117,39,86,107,2,31, - 23,63,212,232,64,50,127,122,156,39,238,125,152,67,247,63,74,90,138,70,175,119,51,66,32,162,104,211,196,240,52,182, - 229,163,85,21,233,196,176,68,12,175,150,35,18,143,82,168,197,25,152,92,168,119,67,165,40,85,116,200,146,185,0,61, - 159,132,210,147,160,254,40,239,145,202,123,204,240,98,35,116,23,248,8,240,107,16,93,130,205,86,3,124,238,142,255,230, - 175,238,187,245,255,253,141,120,4,80,126,163,220,169,104,166,168,92,64,16,45,154,197,183,4,8,169,95,22,11,252,82, - 142,231,229,4,179,184,84,59,121,41,17,211,244,84,125,11,210,79,136,70,116,243,203,194,8,26,227,254,82,79,219,75, - 52,160,230,139,2,113,193,94,123,17,188,46,128,83,216,224,134,132,14,9,61,135,122,169,68,113,101,137,192,119,209,161, - 143,25,49,136,91,3,120,161,102,230,204,48,211,15,254,189,95,123,228,201,146,30,158,91,94,239,185,11,29,48,35,96, - 84,193,49,13,231,12,200,22,161,166,193,217,6,193,68,147,236,183,105,212,20,50,249,254,115,1,222,116,113,64,129,217, - 200,97,122,121,176,177,16,224,171,111,50,165,95,23,17,134,65,94,133,124,234,11,95,96,250,117,6,31,69,35,144,46, - 70,163,44,232,102,26,233,25,208,232,125,53,3,236,2,47,7,227,10,14,245,143,230,183,63,245,215,247,93,179,230,247, - 126,206,138,6,117,234,129,129,86,54,134,80,4,194,71,107,129,106,146,158,166,105,16,73,165,27,190,36,175,142,33,156, - 198,30,242,66,68,224,161,107,101,66,191,134,87,201,33,162,109,196,122,183,177,125,251,126,122,51,41,102,39,158,161,112, - 206,35,32,206,163,79,78,48,63,179,132,196,163,180,180,140,80,62,137,164,69,72,140,74,13,100,110,89,235,90,41,52, - 106,126,32,67,165,137,72,115,70,154,150,159,106,161,175,175,149,195,195,139,236,223,179,155,244,153,17,239,186,154,55,18, - 192,233,152,169,83,25,211,204,107,130,19,75,80,218,14,252,51,141,158,84,191,220,228,198,42,192,30,16,183,65,44,11, - 27,5,220,177,40,197,187,210,127,240,127,31,184,241,215,255,157,109,170,58,218,23,40,67,130,244,154,113,80,13,243,228, - 98,154,213,5,66,247,21,192,231,82,205,67,136,70,106,197,203,65,225,165,154,211,139,92,207,43,154,109,151,182,108,121, - 217,53,190,245,53,95,38,82,54,92,250,151,106,79,82,54,146,97,195,128,192,173,83,40,229,169,22,11,232,48,68,106, - 136,153,49,140,68,27,185,21,143,227,79,62,194,210,253,159,173,89,79,189,176,216,86,114,38,58,27,241,85,35,192,68, - 8,115,10,22,53,100,79,64,165,27,194,103,129,187,155,196,127,132,239,188,27,170,6,2,33,47,86,87,12,223,42,0, - 4,141,196,148,80,188,20,105,76,169,185,98,107,137,123,15,183,163,20,223,115,251,157,239,158,219,146,180,6,1,43,95, - 254,34,91,38,198,217,247,58,220,83,2,75,128,182,164,204,133,58,122,94,233,164,103,10,243,46,41,195,119,5,42,20, - 13,247,6,18,168,131,154,6,95,75,81,87,112,44,173,244,99,181,47,62,211,250,229,142,142,109,215,255,236,221,118,79, - 74,53,74,154,41,129,173,3,66,35,68,94,112,211,74,129,242,11,184,5,141,33,163,16,4,44,229,114,84,10,121,234, - 217,101,130,252,50,125,109,49,90,50,146,32,221,65,208,222,142,21,73,144,236,105,103,125,122,27,102,118,25,137,226,176, - 59,195,202,228,36,137,100,138,54,43,202,178,142,113,106,122,130,182,153,69,255,250,124,57,59,224,7,11,113,33,22,163, - 176,108,8,173,2,33,187,39,165,222,248,181,232,194,154,229,32,176,215,72,35,156,93,92,52,110,155,95,206,103,224,89, - 15,238,71,136,168,237,135,69,109,136,99,29,154,202,101,77,239,212,85,52,114,194,135,128,110,144,46,180,120,176,85,195, - 205,5,203,184,115,224,79,254,223,3,7,127,241,151,237,80,23,9,67,11,41,45,132,40,53,245,198,104,195,236,121,169, - 114,211,124,77,55,184,147,151,113,65,151,186,217,47,104,27,175,8,16,23,52,155,75,226,122,94,66,66,211,136,5,122, - 185,105,166,47,189,230,183,57,92,47,130,84,211,92,212,77,206,220,144,141,64,2,167,84,196,205,47,83,169,148,1,133, - 105,128,29,143,17,10,155,217,185,44,195,79,62,64,238,159,254,177,212,121,98,106,122,72,233,51,86,131,72,62,235,195, - 152,104,244,124,47,246,129,51,6,126,28,244,87,163,49,18,157,221,120,90,83,93,156,67,124,71,13,59,53,90,52,146, - 159,109,173,25,170,23,41,211,104,42,208,253,45,64,232,45,19,9,29,40,193,238,161,42,2,248,234,115,237,160,244,235, - 2,66,129,109,33,142,156,228,87,199,199,95,183,78,1,178,169,234,206,24,50,86,86,225,86,83,176,91,6,186,37,36, - 244,116,179,157,184,209,212,142,44,8,60,40,10,88,70,32,3,152,239,134,115,185,191,190,39,253,249,167,158,239,237,184, - 251,230,72,98,221,58,145,140,42,210,26,173,48,133,111,134,184,161,135,225,88,218,43,141,170,108,181,196,204,236,10,142, - 17,149,55,92,153,22,29,122,137,184,15,201,168,141,45,91,9,172,110,66,105,160,52,120,118,10,203,52,48,34,73,252, - 232,0,166,91,162,119,211,54,156,51,179,36,13,155,66,96,48,63,124,42,188,241,252,228,242,21,138,145,36,28,11,225, - 180,175,245,148,7,203,74,163,109,84,255,166,144,3,63,175,195,131,103,142,157,221,184,54,157,202,220,95,25,201,108,243, - 194,115,30,60,99,192,161,182,254,164,173,114,94,205,174,135,185,205,126,35,15,242,62,224,134,102,120,194,143,131,84,208, - 41,225,50,1,111,91,138,152,215,117,253,241,239,238,184,252,23,127,222,86,170,130,129,68,75,5,194,71,72,187,225,48, - 208,47,166,79,188,4,129,180,108,242,42,250,197,236,214,75,114,192,47,132,254,93,40,167,193,203,226,12,47,18,196,23, - 254,205,203,210,45,46,209,166,46,37,182,95,9,232,46,60,128,66,94,124,14,217,4,64,133,68,233,16,83,138,6,177, - 236,186,84,107,53,202,165,50,65,181,78,52,128,84,50,130,138,155,20,29,201,169,211,211,76,220,123,79,24,60,240,245, - 98,215,88,118,118,87,168,207,72,120,193,131,163,65,35,177,55,107,65,117,26,252,253,52,226,203,114,141,67,141,13,169, - 12,195,137,164,80,82,234,149,74,25,163,176,194,203,113,59,108,174,85,129,192,23,18,87,154,36,125,135,117,229,69,226, - 245,18,31,240,29,30,66,211,10,220,250,86,210,128,190,149,56,190,100,215,80,35,224,254,245,0,33,37,4,237,142,195, - 214,231,15,115,150,215,183,102,74,40,132,136,43,221,166,67,125,205,68,103,199,135,229,64,111,111,91,189,86,243,157,122, - 232,170,0,63,187,18,132,245,64,73,8,19,80,76,42,157,141,66,77,66,84,64,123,23,120,45,167,231,157,249,211,255, - 32,103,26,113,159,165,184,166,12,212,155,165,233,49,192,182,33,101,64,107,31,68,134,219,82,97,251,13,63,101,173,73, - 116,136,208,55,49,77,129,157,105,67,68,18,248,178,145,48,170,149,9,97,163,57,158,145,178,32,30,101,112,219,110,110, - 215,81,148,107,114,239,95,126,42,120,207,240,228,249,205,240,148,3,79,213,225,152,11,211,157,141,234,124,110,69,32,52, - 156,117,53,195,118,160,94,216,11,91,188,98,105,207,59,90,205,206,104,160,190,161,224,249,0,22,91,93,41,242,131,105, - 181,101,155,17,164,29,197,194,209,101,206,185,33,155,27,156,151,72,65,139,223,72,173,120,239,25,219,184,105,211,159,252, - 222,154,235,62,246,75,82,133,85,208,18,100,179,96,24,97,83,49,49,26,69,249,95,209,181,45,154,193,123,92,244,40, - 137,87,40,179,113,177,20,199,43,104,63,23,189,102,23,180,156,151,113,5,175,164,53,105,253,114,127,241,37,247,19,23, - 32,175,17,115,45,180,194,192,71,5,62,181,178,131,91,171,18,184,46,6,146,184,105,163,91,82,20,203,14,211,35,243, - 156,121,246,176,94,254,198,131,161,56,123,182,178,109,185,54,218,14,39,128,19,202,146,39,156,64,141,36,52,75,75,80, - 63,11,250,61,52,42,116,206,211,136,171,26,107,237,224,241,84,11,37,41,177,131,64,187,166,201,5,191,182,201,133,72, - 250,6,248,164,128,127,0,126,58,244,185,166,48,203,110,223,229,164,87,165,30,54,180,37,131,75,139,137,252,0,0,208, - 235,13,66,17,219,230,75,95,249,50,255,146,91,126,93,137,241,58,240,81,173,217,233,135,241,10,172,217,248,177,119,110, - 221,253,159,126,51,173,242,53,60,215,197,247,2,242,75,57,10,75,89,150,167,23,244,194,233,179,106,244,204,176,151,31, - 159,13,168,212,84,111,161,236,183,57,129,104,7,107,109,131,52,116,149,38,231,193,148,110,180,127,154,145,141,212,163,245, - 6,236,209,144,142,128,25,89,41,135,75,167,199,213,134,43,182,26,90,134,152,137,52,210,238,110,198,13,129,161,84,163, - 22,22,70,115,163,74,2,12,182,237,223,71,199,166,237,156,56,57,74,223,216,112,105,3,60,235,192,191,120,112,164,31, - 86,218,193,171,209,136,95,42,104,248,61,40,222,13,213,101,152,78,195,17,17,114,40,150,87,41,87,235,113,11,198,239, - 7,255,151,198,10,180,188,127,29,173,255,237,26,62,254,63,78,210,255,236,34,9,160,3,100,26,90,3,216,39,225,142, - 115,173,137,155,7,254,231,31,174,189,233,71,62,140,14,43,47,70,36,95,0,11,117,129,39,17,77,160,145,223,12,16, - 77,240,81,77,19,234,149,57,152,198,86,18,151,16,216,47,183,192,190,213,78,123,49,243,253,165,87,187,96,71,189,36, - 53,227,194,103,84,216,12,60,84,16,134,4,245,26,94,181,138,235,120,184,174,143,235,120,148,138,21,38,39,102,57,113, - 242,44,249,145,145,124,109,108,216,88,51,189,16,235,207,215,228,53,224,90,48,229,55,0,253,89,97,136,83,102,204,156, - 147,213,32,31,13,149,235,210,200,20,27,107,2,201,87,104,116,202,8,34,49,38,146,25,153,9,3,21,85,10,91,11, - 30,235,236,71,6,138,71,42,69,190,4,124,148,70,221,165,5,224,243,13,109,148,27,74,139,244,53,189,180,21,190,243, - 180,140,183,100,50,234,5,16,18,2,238,57,244,218,128,144,101,154,204,205,207,243,240,217,179,175,122,47,164,239,68,110, - 0,246,104,68,8,102,44,217,47,147,244,161,50,85,132,104,20,62,239,93,115,177,129,138,0,109,184,97,57,182,148,155, - 167,84,46,48,55,57,195,212,145,243,250,240,225,243,186,120,110,152,182,220,124,108,112,41,223,209,227,40,47,2,217,16, - 106,33,152,6,164,198,132,104,31,110,105,137,22,93,47,92,87,171,230,90,243,229,20,200,132,52,162,200,148,133,107,229, - 81,50,142,150,233,70,65,117,45,64,70,16,82,52,220,189,97,163,240,86,119,119,130,175,252,253,255,98,125,205,91,84, - 112,220,133,227,253,176,176,17,152,4,18,23,52,187,38,121,158,131,224,48,20,63,0,101,11,22,203,161,50,214,128,251, - 36,184,127,0,252,12,240,92,214,225,127,254,151,163,252,233,159,159,228,243,192,26,176,108,232,146,112,64,195,237,165,76, - 250,166,171,254,254,207,7,118,220,245,126,130,160,210,228,182,196,69,23,117,131,179,109,186,219,149,122,17,124,94,142,28, - 77,32,144,151,124,238,229,222,39,248,102,207,214,69,254,134,11,37,68,248,166,207,139,75,180,35,165,94,212,172,94,130, - 87,47,139,148,110,120,220,26,122,170,239,57,84,74,121,220,74,25,252,128,149,149,60,181,186,71,173,238,49,49,51,207, - 226,66,14,17,181,105,235,235,19,189,169,184,144,221,163,82,31,63,175,231,22,171,34,13,177,8,12,152,224,25,161,110, - 11,74,94,86,66,182,0,139,253,144,107,129,66,20,106,43,224,183,130,142,0,134,231,97,132,74,186,161,86,82,8,162, - 129,230,72,189,194,223,185,245,139,49,87,203,52,34,244,79,241,98,70,154,126,153,17,201,15,50,0,93,0,161,157,107, - 27,154,208,107,1,66,134,97,240,216,225,231,8,85,248,134,124,191,11,147,106,130,206,215,124,237,19,34,195,26,72,147, - 80,55,203,104,200,11,252,132,194,32,66,95,215,122,6,187,12,118,108,184,18,110,54,133,86,174,88,204,206,49,50,113, - 46,58,118,236,68,244,208,163,79,182,183,221,247,116,251,246,149,122,175,9,98,12,54,157,123,207,245,131,215,255,226,7, - 101,101,201,229,228,253,79,166,75,237,129,29,218,26,17,79,224,218,81,180,138,96,5,22,58,149,68,199,163,4,42,96, - 121,110,129,165,133,121,226,153,86,58,186,218,105,207,100,240,171,121,206,61,244,164,190,22,202,33,20,53,184,6,141,34, - 97,247,2,31,2,62,69,163,72,124,51,187,9,23,216,10,234,75,80,253,29,224,12,240,80,243,111,21,224,43,143,206, - 243,196,163,243,252,52,208,11,177,42,12,41,184,90,195,45,243,107,123,174,61,248,169,143,15,108,184,246,122,17,6,43, - 32,12,228,203,0,230,37,32,112,233,198,208,47,117,155,95,52,161,46,252,214,23,198,95,95,108,22,248,45,61,99,188, - 88,84,76,124,139,200,233,134,199,170,1,112,250,146,32,67,33,68,3,24,47,137,235,185,16,6,129,144,132,161,71,62, - 151,35,240,235,24,82,98,196,98,116,13,38,72,181,180,17,73,164,185,222,176,65,92,48,140,68,139,2,74,78,145,133, - 233,49,157,31,57,23,45,28,25,94,59,251,220,217,94,255,220,240,101,198,212,120,49,94,243,243,169,70,137,141,89,5, - 147,9,56,239,194,68,2,22,175,129,146,15,117,242,75,238,79,212,202,193,94,26,93,68,222,171,53,89,183,254,138,222, - 217,239,62,236,240,7,8,128,46,130,208,80,21,165,5,95,123,174,237,85,3,33,211,182,25,93,92,228,216,185,179,111, - 216,119,107,244,73,64,27,160,23,166,39,148,210,10,67,217,205,8,87,209,108,164,217,104,54,168,181,143,212,38,194,139, - 162,133,73,64,136,22,43,72,233,209,211,221,70,79,247,219,184,238,138,183,227,124,244,39,204,111,124,250,203,107,206,252, - 218,239,180,110,207,86,253,197,107,14,36,223,251,27,255,70,182,36,44,18,125,49,214,118,246,198,23,142,62,128,29,109, - 69,71,99,120,120,216,118,20,75,219,84,133,205,137,211,195,148,11,62,137,136,69,75,58,73,173,94,225,216,209,89,186, - 210,105,34,169,52,231,102,43,92,15,105,19,54,25,176,105,14,130,105,40,181,53,171,233,253,241,255,199,222,123,199,217, - 117,149,247,222,223,181,214,46,167,77,239,51,234,93,150,229,38,119,227,130,11,54,166,183,64,2,132,155,158,155,155,114, - 19,82,222,220,36,55,164,151,123,19,146,144,16,72,66,239,197,16,192,96,3,198,5,92,112,151,44,201,234,189,204,140, - 166,207,169,187,172,181,222,63,214,62,103,70,178,76,53,224,228,230,240,25,70,26,143,102,206,217,251,236,103,63,207,239, - 249,21,224,143,178,77,214,141,89,255,166,178,59,234,126,154,70,17,112,67,54,134,126,20,7,94,212,32,156,115,185,92, - 183,104,184,249,208,170,193,243,174,250,196,191,244,173,190,248,50,108,163,138,240,36,66,52,64,228,78,103,17,47,46,26, - 103,217,64,157,214,117,180,68,157,139,185,62,207,212,129,137,197,27,119,78,103,55,115,150,85,186,109,117,98,205,85,187, - 61,189,131,82,226,244,231,213,114,57,51,72,207,167,167,175,223,5,22,26,139,242,218,16,129,223,250,54,99,156,10,222, - 10,39,129,80,214,208,233,123,116,174,217,36,88,123,129,224,86,29,164,54,9,166,166,231,75,227,71,78,244,207,239,219, - 97,15,222,247,96,90,127,124,71,173,180,125,247,100,123,61,62,90,114,145,205,135,44,28,247,225,96,193,218,221,126,163, - 54,125,14,152,19,60,83,103,247,92,63,254,195,251,1,53,98,201,121,43,29,31,211,21,33,103,96,255,61,111,189,124, - 159,32,142,89,121,223,189,252,182,214,92,147,157,4,153,93,32,63,140,77,152,118,107,102,155,56,70,66,67,237,60,80, - 179,141,90,135,80,113,166,55,148,160,20,88,135,232,42,171,176,82,96,165,118,30,54,217,165,97,17,104,93,67,232,58, - 200,54,124,227,113,205,45,151,240,15,95,190,176,112,223,3,59,226,107,126,243,141,254,72,103,137,100,190,1,185,10,51, - 149,105,82,145,71,149,58,192,179,104,35,25,159,52,140,87,38,136,139,9,253,171,206,103,243,134,165,132,62,64,140,65, - 161,141,71,101,106,146,131,251,15,226,13,15,138,79,31,216,191,244,245,85,115,99,55,248,17,220,187,28,182,141,192,88, - 12,177,202,58,155,187,178,99,122,3,11,102,242,100,119,220,45,56,119,248,128,22,7,74,53,96,73,0,55,106,120,217, - 193,229,131,231,110,249,216,187,187,214,95,124,9,54,106,32,68,30,43,34,231,111,36,220,138,221,102,184,138,92,188,137, - 18,153,233,232,25,51,130,104,205,79,246,244,177,107,113,135,100,237,130,153,252,162,175,137,197,223,243,108,139,233,140,213, - 236,192,158,133,21,250,130,127,116,214,79,88,155,165,124,45,220,130,132,144,168,112,33,167,212,0,198,198,11,99,165,176, - 88,171,179,151,102,73,12,72,235,35,72,49,105,5,147,54,208,73,66,187,47,9,150,119,18,45,191,90,172,185,230,26, - 191,62,55,221,49,182,107,95,199,232,35,79,174,60,252,213,175,111,233,220,115,96,186,189,90,31,247,45,143,214,225,54, - 11,143,126,18,170,159,226,59,231,253,252,63,91,128,206,94,132,196,247,84,132,82,223,167,119,98,130,45,247,222,195,174, - 195,135,152,1,150,224,200,127,202,1,160,4,217,65,251,65,110,196,4,206,136,126,171,243,216,58,37,199,71,203,211,83, - 167,134,134,151,12,187,145,208,58,252,71,202,44,87,70,100,74,105,107,17,86,58,155,11,235,185,39,41,37,86,73,18, - 98,60,17,208,102,122,88,114,254,11,213,93,245,32,247,115,231,93,32,210,106,131,88,37,132,94,142,106,165,138,232,132, - 178,178,28,62,28,19,37,154,160,179,159,254,245,231,50,176,124,21,158,95,192,164,41,90,71,8,83,67,11,69,34,243, - 116,116,117,112,225,149,23,242,190,15,255,35,159,255,244,237,197,79,191,231,195,23,108,126,244,233,158,75,97,169,117,24, - 196,3,157,176,255,167,160,246,199,217,177,123,20,199,126,187,57,27,201,200,186,162,235,129,159,202,10,212,195,160,82,232, - 15,224,242,20,110,28,95,59,180,241,198,79,125,168,115,249,249,91,72,245,60,248,46,10,71,154,28,66,164,153,227,181, - 124,198,150,203,97,48,98,225,224,46,234,86,22,182,87,11,38,241,52,71,163,179,21,163,51,199,59,151,205,243,237,55, - 170,198,208,36,97,187,95,223,36,19,102,4,199,69,40,182,3,184,155,223,172,48,24,176,38,243,139,150,217,18,64,160, - 172,113,186,54,112,185,243,88,210,164,65,92,171,81,47,59,255,104,173,19,4,41,90,167,40,83,68,161,232,44,104,250, - 46,185,128,117,87,94,46,143,191,233,21,237,247,127,230,193,246,79,189,243,125,43,94,54,118,212,95,6,79,106,216,94, - 128,234,237,223,170,176,62,71,215,192,127,26,71,196,102,17,146,194,102,152,208,119,94,132,172,16,164,185,28,35,59,119, - 114,197,237,159,39,111,12,59,23,241,28,118,186,98,192,239,3,219,112,36,65,47,187,59,152,31,80,1,74,220,239,174, - 181,195,100,114,252,196,220,177,29,187,24,94,178,2,97,107,24,145,58,118,136,113,184,135,64,96,108,130,69,35,133,135, - 161,233,13,227,184,47,210,10,148,104,160,100,66,234,41,214,174,91,71,185,81,19,161,215,78,213,215,20,138,37,198,199, - 171,60,250,200,54,150,173,232,98,235,145,58,221,93,195,44,239,31,164,179,167,15,47,223,129,53,18,25,71,46,132,79, - 133,24,225,82,30,148,17,164,24,76,221,163,88,232,226,205,191,240,38,110,120,213,203,212,39,223,253,158,21,159,251,135, - 247,118,95,51,57,63,220,3,125,83,112,199,107,97,215,32,84,150,227,12,229,107,14,219,225,15,178,215,189,59,27,207, - 60,32,132,92,5,134,115,112,89,12,47,217,183,105,213,197,183,124,234,125,189,203,55,158,143,73,107,40,17,100,57,242, - 58,235,48,228,66,202,232,226,35,185,128,49,187,85,251,34,1,167,104,229,179,55,11,9,88,163,51,32,219,91,52,107, - 89,7,190,159,229,60,181,198,182,197,74,245,69,242,136,5,89,70,246,217,52,123,41,133,200,182,139,194,58,206,143,22, - 230,180,78,205,117,112,205,140,52,50,251,16,72,77,154,157,119,103,169,130,177,52,42,53,26,51,83,212,27,53,210,56, - 205,70,190,172,177,242,2,194,66,1,63,240,137,26,121,118,238,59,202,190,109,247,219,209,199,183,210,216,179,71,148,199, - 102,204,202,122,163,220,41,196,169,196,218,186,2,17,130,250,63,60,211,236,77,103,55,229,114,230,201,182,234,12,44,168, - 105,88,47,255,95,43,64,205,34,116,238,138,197,192,244,183,47,66,34,8,16,81,196,11,254,253,179,12,236,219,235,132, - 125,103,153,249,39,178,207,255,148,97,22,167,50,238,196,0,11,190,116,207,21,6,158,100,39,249,173,160,173,160,33,181, - 173,31,221,185,219,94,118,203,75,132,53,166,101,116,229,248,42,10,147,70,40,21,128,244,1,141,182,137,243,162,17,46, - 201,3,44,82,231,193,8,140,156,101,112,164,141,75,131,13,164,73,157,242,92,204,67,15,60,206,252,220,36,151,95,122, - 62,107,215,174,160,88,204,161,60,176,182,65,121,126,10,85,169,208,72,52,86,10,148,231,161,2,31,63,204,17,230,66, - 2,223,119,215,140,116,214,15,73,18,51,208,211,193,255,252,131,63,226,241,23,223,218,254,133,223,249,211,75,214,221,253, - 245,226,114,80,83,160,207,133,167,87,66,35,204,198,175,147,184,248,223,197,111,240,216,53,154,171,10,130,27,107,150,155, - 14,111,94,125,233,77,183,189,191,127,197,218,205,232,180,214,26,65,164,179,248,194,74,147,169,192,207,94,206,133,56,109, - 249,125,246,49,11,50,31,30,177,136,202,99,159,85,22,33,207,32,26,182,186,38,33,206,218,21,181,48,166,69,187,34, - 41,213,105,207,72,234,133,231,99,23,255,47,43,68,210,40,119,3,144,174,240,234,184,65,163,86,163,92,158,163,62,63, - 143,72,98,60,95,225,135,62,202,247,177,210,39,137,148,173,156,154,177,213,99,227,118,238,233,189,118,247,3,247,137,104, - 199,94,81,152,170,138,245,64,55,152,130,107,56,119,199,176,59,21,2,13,107,67,107,163,203,120,166,101,154,0,82,208, - 101,168,21,161,252,135,144,196,160,79,66,50,13,137,2,221,6,38,255,29,222,156,255,211,121,66,127,55,69,200,203,229, - 56,176,115,39,87,126,227,235,44,159,157,33,250,22,109,101,115,58,239,203,62,6,112,182,24,17,240,24,112,14,206,169, - 59,120,142,230,102,237,126,118,26,90,102,187,96,122,108,235,211,141,196,146,23,214,115,70,85,66,225,171,144,79,127,228, - 195,28,63,122,132,13,235,55,177,124,217,10,186,250,122,232,25,232,195,207,133,88,12,198,166,104,147,58,189,144,1,191, - 212,206,192,224,48,189,253,3,84,171,49,255,244,143,239,226,154,23,188,136,91,94,116,51,158,151,144,196,17,82,64,210, - 136,153,155,47,115,226,228,65,198,198,78,33,60,203,224,72,63,249,124,193,21,0,1,158,242,8,124,159,182,182,54,134, - 134,151,81,104,239,67,36,33,210,88,140,173,177,229,194,11,89,253,185,127,13,222,243,91,127,112,65,250,174,79,38,171, - 225,88,12,199,191,2,141,52,27,189,62,176,8,232,92,1,188,26,100,10,3,70,112,117,108,121,229,244,85,151,92,116, - 235,135,255,185,99,100,197,26,76,82,119,29,139,177,45,60,70,32,78,207,16,62,91,9,18,11,89,94,205,172,180,103, - 22,22,113,186,176,243,180,53,252,25,197,230,204,175,53,173,53,178,175,25,173,91,106,246,211,192,232,214,182,75,62,19, - 44,183,32,116,54,216,72,225,230,193,38,25,81,10,231,243,147,26,226,90,157,70,173,74,220,168,18,69,53,226,70,21, - 33,44,129,239,33,60,159,52,150,156,56,94,225,232,193,99,181,249,221,187,27,237,247,63,24,200,125,135,130,100,182,66, - 1,228,250,236,61,42,28,198,72,12,102,206,245,92,5,13,107,141,181,253,205,198,167,154,221,84,253,236,254,146,45,69, - 80,78,174,49,13,156,178,80,141,33,50,48,61,15,83,109,48,215,11,115,33,148,143,66,61,5,109,255,95,42,64,139, - 139,144,177,130,59,31,239,122,198,2,68,10,65,152,207,115,106,231,14,158,254,226,23,184,241,12,117,242,183,43,12,205, - 105,189,169,217,122,12,120,41,46,155,106,34,239,49,178,166,235,116,123,134,239,226,97,149,32,56,50,79,105,54,98,210, - 221,85,102,67,152,50,7,142,214,211,68,231,67,233,33,50,165,110,84,171,114,226,232,81,174,191,250,42,2,9,141,202, - 56,251,198,14,178,107,187,160,167,127,128,222,193,97,186,122,251,200,23,218,177,36,36,38,226,158,59,238,99,207,83,123, - 152,153,153,97,116,116,140,185,185,42,71,70,15,49,246,249,67,228,11,1,70,67,181,82,229,232,209,227,212,235,17,155, - 207,219,68,119,119,55,185,208,163,16,180,57,230,109,62,143,239,7,24,109,41,22,74,72,161,152,157,158,34,74,43,180, - 151,150,99,180,101,98,242,40,137,31,19,180,181,211,104,31,100,20,186,215,67,91,3,188,82,246,198,155,4,30,204,94, - 247,18,224,93,32,135,160,119,26,46,73,45,55,206,94,188,121,243,245,31,127,111,71,223,146,37,152,196,209,219,164,148, - 216,166,230,234,180,49,122,225,236,61,147,193,252,29,30,123,219,12,116,124,38,194,97,207,98,217,193,153,22,28,205,247, - 208,34,43,141,38,222,228,222,51,178,21,143,241,12,177,170,112,124,42,137,0,149,73,59,146,212,97,110,81,76,163,86, - 165,209,40,147,36,26,147,106,172,181,40,165,176,169,100,102,102,134,19,199,71,57,118,98,130,157,59,247,114,236,248,41, - 100,117,126,230,188,82,33,90,221,211,57,220,86,216,32,68,222,103,170,187,67,38,94,81,200,70,106,195,80,217,106,181, - 74,106,36,22,221,102,73,54,8,21,172,71,41,26,141,72,128,37,73,18,102,102,102,169,149,231,173,72,82,163,163,216, - 138,114,205,20,162,52,237,168,39,245,30,99,230,219,161,81,66,197,37,204,84,17,59,46,96,34,133,19,243,78,228,186, - 215,131,19,29,110,169,249,255,78,1,106,22,161,11,86,85,104,196,146,59,31,239,166,16,58,62,143,167,20,115,105,202, - 216,191,127,134,23,239,221,203,23,207,4,27,191,71,204,166,11,167,163,249,236,242,118,126,227,95,110,194,143,191,55,254, - 144,95,244,121,234,111,31,231,182,143,238,226,34,80,121,8,44,228,166,106,243,42,142,171,228,242,33,214,24,148,242,136, - 116,76,127,95,39,157,165,28,82,198,116,248,37,122,123,139,68,81,66,35,174,113,108,207,78,142,239,243,105,111,239,101, - 104,213,8,119,221,253,21,118,60,250,4,235,86,173,97,205,218,53,116,118,94,68,71,103,27,158,132,66,49,159,69,5, - 123,104,35,8,253,128,98,161,8,194,210,136,106,84,231,202,196,181,6,243,229,121,230,102,102,80,126,192,232,248,20,113, - 108,41,182,117,209,223,219,195,240,210,110,10,109,167,8,75,121,196,84,157,180,10,239,254,147,191,182,249,247,125,226,212, - 229,240,120,4,251,5,84,101,118,23,254,100,134,3,45,1,254,5,100,27,244,77,194,229,192,203,107,27,214,92,114,213, - 135,255,173,187,119,201,8,54,169,158,54,224,74,41,91,163,137,88,148,225,105,91,91,36,123,58,59,78,52,61,155,23, - 157,51,217,244,87,126,54,85,250,162,31,112,230,205,228,204,181,254,217,100,23,207,144,99,100,120,212,153,52,128,214,118, - 13,164,48,196,113,76,60,87,67,232,148,180,214,32,169,55,144,218,162,109,138,13,5,129,167,176,74,50,51,61,203,238, - 221,123,8,253,60,70,67,24,22,216,180,105,13,23,110,217,72,177,148,35,95,12,71,132,204,140,254,241,92,51,37,53, - 18,31,161,82,129,172,57,199,196,36,15,86,97,68,226,104,29,89,113,183,214,217,177,196,73,76,181,82,197,88,75,221, - 24,170,149,6,149,153,121,102,78,78,48,119,114,106,228,196,169,25,166,143,157,196,142,159,74,194,153,217,122,119,165,86, - 95,153,234,153,165,82,236,193,232,47,47,133,59,103,224,232,39,224,25,254,161,175,195,5,184,252,72,30,70,255,224,227, - 149,235,117,56,103,73,153,3,39,67,142,76,228,201,5,146,84,107,222,251,185,207,114,233,225,195,180,63,199,219,44,211, - 4,144,51,159,25,15,136,98,227,188,130,191,83,80,206,64,116,235,74,62,253,209,93,92,14,129,130,254,41,24,106,44, - 27,46,204,140,30,163,99,213,114,148,114,152,64,26,55,144,104,164,72,157,21,110,172,113,114,83,75,41,148,116,149,186, - 136,19,131,177,53,190,246,185,207,177,103,207,62,126,241,45,111,194,164,53,151,248,160,4,82,248,120,34,64,42,167,239, - 202,229,10,72,225,183,214,199,113,212,160,32,61,74,61,93,84,243,21,74,29,1,8,129,151,11,185,236,186,23,160,241, - 57,126,226,20,251,159,62,200,216,214,61,120,187,83,134,7,214,177,97,213,18,238,254,250,109,76,124,232,19,245,159,129, - 253,117,248,186,133,237,13,168,188,22,248,52,240,53,96,56,43,62,157,158,232,139,12,87,10,99,95,145,174,91,121,245, - 21,159,124,207,72,223,250,245,50,142,43,120,50,231,138,135,52,45,213,248,66,195,35,154,104,24,167,105,181,206,204,8, - 196,182,188,128,108,139,107,179,240,181,211,199,46,187,160,56,111,226,58,103,99,80,115,58,217,145,179,224,66,103,122,8, - 61,243,214,229,176,186,184,94,35,154,153,164,94,111,96,180,37,244,3,16,6,63,244,73,227,6,105,146,50,51,17,51, - 63,55,75,165,90,38,142,35,250,250,122,233,239,239,115,189,149,108,254,44,139,177,22,157,38,88,19,101,214,35,210,165, - 117,24,133,145,21,164,148,24,43,49,198,98,237,188,3,186,149,36,206,250,17,37,133,99,109,43,133,47,125,58,218,58, - 0,232,22,2,213,43,241,215,120,8,225,48,56,163,45,245,70,131,185,114,217,223,123,120,212,63,188,255,88,251,103,31, - 120,108,32,124,242,233,85,255,173,82,169,97,205,182,1,56,177,226,89,70,49,239,71,149,74,111,127,8,198,62,218,66, - 62,208,108,89,51,207,209,169,54,82,157,240,222,207,222,198,232,145,35,167,241,79,158,75,78,195,216,193,57,102,254,247, - 253,116,221,58,194,145,216,176,118,67,59,81,79,248,109,38,225,69,88,83,209,227,158,247,238,227,45,110,19,212,158,194, - 114,17,120,189,47,122,221,203,212,196,137,35,116,119,22,104,235,233,70,8,73,16,248,228,11,69,180,214,40,229,147,106, - 23,195,172,178,14,193,96,16,158,160,179,189,13,165,36,183,222,114,11,161,95,64,11,133,205,6,122,223,243,201,249,65, - 43,149,52,8,3,80,1,214,24,76,220,192,15,2,226,70,29,109,36,90,120,24,98,44,134,90,101,150,198,241,132,161, - 165,171,89,181,118,41,171,86,172,70,235,6,163,19,163,28,218,55,198,87,239,126,136,7,31,222,77,106,50,127,245,108, - 115,155,89,136,240,23,25,173,225,223,64,118,74,87,124,48,246,21,102,227,218,107,206,255,204,7,151,245,110,216,168,76, - 92,193,19,57,119,36,68,218,210,120,157,185,144,90,40,62,226,204,170,115,218,96,109,23,173,226,77,179,81,90,228,241, - 35,190,53,144,116,218,182,235,204,247,114,147,213,124,214,81,254,76,230,245,25,203,108,173,53,243,115,179,152,114,25,139, - 98,126,174,78,185,50,1,194,80,173,206,81,174,76,18,71,17,129,234,164,171,171,157,129,254,126,218,218,138,72,153,117, - 70,38,33,77,45,36,29,8,153,96,101,156,193,82,11,59,41,119,191,55,40,105,48,40,172,245,17,158,1,34,103,134, - 111,3,60,147,45,44,172,192,147,18,155,166,136,108,27,39,132,192,170,4,29,107,76,170,144,66,160,13,72,233,33,164, - 164,191,167,151,21,195,195,228,110,189,149,187,174,189,150,143,253,228,47,10,83,54,162,238,249,202,19,66,182,37,241,217, - 237,56,188,192,249,57,252,103,125,24,235,66,248,82,173,249,192,23,110,99,255,145,35,63,80,254,78,45,214,200,175,28, - 101,223,87,142,242,49,224,87,87,149,88,213,29,224,125,135,5,8,37,184,254,64,5,11,109,17,108,0,46,232,186,233, - 170,193,145,139,207,147,113,35,98,114,124,140,84,8,186,186,7,200,181,117,208,214,222,197,216,232,56,35,75,70,72,227, - 6,81,20,145,234,148,142,174,110,242,97,59,237,165,46,230,171,53,62,247,229,111,208,221,185,151,180,222,160,94,143,64, - 74,130,66,30,229,41,194,48,164,45,151,167,179,179,157,68,167,228,139,5,218,74,69,138,249,60,197,66,145,238,174,46, - 60,9,90,71,72,153,18,228,44,197,98,14,52,76,143,141,211,63,146,107,165,57,12,14,141,176,100,201,74,116,3,54, - 156,191,137,47,118,22,115,15,190,243,67,171,207,171,214,174,242,224,104,8,179,95,132,185,50,240,49,129,236,245,101,255, - 116,106,175,16,198,190,162,177,105,205,117,151,125,252,253,75,187,55,92,40,83,51,139,240,3,164,86,32,26,88,97,90, - 68,189,103,52,55,77,173,150,149,173,228,136,133,235,126,209,72,181,88,166,145,117,54,38,43,26,226,140,17,204,158,225, - 233,179,184,8,157,205,60,236,89,73,140,103,233,150,78,251,183,214,221,48,186,251,250,72,219,114,164,137,100,223,177,157, - 124,226,195,159,68,199,13,222,252,230,215,177,106,233,74,2,31,60,63,135,16,160,83,141,78,235,88,233,54,124,86,11, - 39,94,85,83,46,128,205,10,44,10,139,2,180,43,58,210,2,1,22,15,99,99,132,108,128,245,17,228,240,164,205,190, - 22,46,104,213,178,96,75,99,12,82,72,180,53,72,17,34,164,235,55,53,218,33,211,153,191,184,240,45,211,26,190,242, - 129,79,113,232,95,62,208,120,203,169,169,173,5,120,172,34,228,169,113,163,245,209,179,148,246,245,128,55,113,4,122,151, - 130,209,63,26,183,193,31,104,151,5,4,158,59,9,239,255,236,103,56,114,226,200,15,252,119,202,69,7,58,0,142,29, - 172,112,240,96,139,215,243,29,109,191,2,240,115,176,92,193,181,243,249,240,226,117,63,251,230,110,161,192,39,193,183,30, - 181,83,167,40,4,57,114,237,29,108,222,178,133,251,238,189,135,250,241,83,248,74,224,133,62,29,221,61,116,13,47,161, - 212,214,131,151,239,225,227,255,248,143,124,241,142,123,92,23,147,36,8,33,9,115,1,133,66,1,129,32,159,203,19,248, - 10,172,161,82,174,210,213,221,73,62,95,160,171,171,135,174,174,46,70,70,70,104,47,21,9,67,143,36,137,72,211,136, - 92,33,199,208,224,32,29,157,93,172,169,230,88,190,102,53,42,231,131,174,97,162,8,43,37,235,54,46,97,253,95,255, - 145,188,239,134,235,134,143,252,247,223,186,98,213,161,227,187,18,216,185,18,230,254,28,100,81,138,254,138,229,10,105,236, - 203,103,214,175,188,238,202,207,125,100,121,247,234,117,152,120,14,165,50,110,143,48,217,152,37,159,209,172,159,222,9,101, - 209,128,173,137,71,156,177,164,18,103,124,77,46,98,173,216,22,31,200,46,96,194,173,49,236,76,133,215,217,138,82,211, - 235,199,88,123,58,23,168,201,206,166,153,122,154,21,176,22,43,209,25,138,161,36,126,177,11,207,192,11,110,186,150,203, - 175,125,1,79,111,219,202,201,163,71,153,173,86,88,190,116,8,33,12,70,155,140,116,154,249,159,73,137,149,25,243,219, - 164,46,138,71,8,82,157,96,173,197,243,36,58,115,4,240,60,39,136,85,66,161,173,197,26,131,20,22,41,36,18,31, - 35,220,88,230,150,112,205,110,83,162,17,88,233,82,86,180,141,64,198,40,233,226,180,149,108,35,159,239,230,169,253,199, - 248,216,187,255,129,238,47,126,117,242,102,109,158,204,195,93,26,238,233,78,162,99,69,72,54,61,219,212,240,197,127,50, - 108,185,85,112,254,13,130,164,241,159,167,8,89,32,231,43,106,145,225,215,254,246,171,28,57,49,246,67,127,14,205,4, - 207,37,192,123,61,201,197,61,57,60,251,173,187,181,82,78,209,85,142,131,198,108,180,188,2,91,218,126,230,245,171,122, - 47,63,223,75,102,38,65,130,18,18,171,83,230,167,38,9,11,5,122,6,7,121,205,143,191,17,226,136,204,113,222,141, - 24,70,32,85,129,147,71,143,241,158,127,125,31,249,92,1,109,44,54,116,54,238,97,24,80,200,135,180,149,74,228,195, - 28,190,239,49,95,158,99,249,242,141,116,119,119,211,104,68,88,11,245,122,141,253,251,247,209,211,211,203,208,208,32,109, - 109,109,116,116,245,99,45,76,76,213,153,156,170,113,240,192,9,252,251,190,201,170,117,43,216,180,105,21,253,131,195,96, - 12,169,174,33,76,204,181,55,191,146,167,254,199,193,254,147,191,249,123,75,3,232,172,64,110,8,122,99,195,21,70,155, - 151,77,175,92,118,205,165,183,125,100,217,192,234,13,232,164,150,225,25,11,70,239,54,51,18,179,226,153,91,46,123,26, - 5,206,62,203,46,115,113,78,215,194,184,214,210,128,101,69,200,62,99,228,90,92,184,236,194,38,236,89,116,95,205,63, - 159,46,209,176,103,248,155,137,69,100,200,38,118,212,44,122,210,209,38,210,24,233,9,206,187,228,82,54,108,58,135,71, - 30,124,136,173,59,246,48,52,208,198,178,101,75,65,27,140,78,81,153,190,204,100,111,30,65,224,2,8,108,83,162,225, - 88,214,70,91,135,235,89,147,21,70,137,18,62,40,87,40,181,209,174,32,10,139,20,214,141,240,38,205,206,65,22,92, - 153,141,245,158,113,131,180,47,115,228,138,93,236,59,122,138,79,125,226,227,76,124,246,206,198,117,19,83,135,54,195,55, - 35,196,189,6,30,182,216,99,159,132,250,215,112,132,211,51,81,223,59,1,207,11,225,241,47,89,172,129,11,110,250,207, - 81,132,154,197,39,74,52,175,253,253,251,185,235,209,177,31,217,115,17,56,191,149,39,82,195,223,157,170,125,219,39,190, - 186,232,241,33,95,73,1,5,81,104,235,92,245,154,151,21,66,155,160,149,79,67,164,88,235,238,70,42,244,93,116,142, - 54,8,153,137,112,173,6,227,236,163,132,244,104,212,26,252,217,31,255,9,211,83,243,25,224,232,86,183,74,42,10,197, - 2,237,165,18,197,66,129,48,8,176,6,242,185,18,82,122,36,137,97,217,178,229,244,244,244,162,148,34,77,19,164,10, - 8,130,144,66,62,143,151,145,15,131,48,68,74,137,167,20,137,182,236,223,115,152,93,79,109,103,205,154,117,92,117,237, - 53,20,59,219,73,227,42,96,56,122,236,168,144,224,75,40,25,88,171,225,82,99,237,205,135,206,93,125,237,77,183,125, - 164,127,233,186,115,176,105,109,209,78,235,116,132,199,32,90,23,108,243,179,64,60,163,112,60,91,186,197,89,87,235,54, - 235,128,132,57,115,239,213,234,100,68,115,164,177,218,145,15,197,162,228,138,179,128,211,207,64,144,172,104,241,121,206,70, - 108,180,103,254,173,89,192,44,152,180,129,31,6,188,224,198,27,168,204,76,179,111,223,14,14,31,31,37,80,138,37,67, - 131,46,5,181,105,105,111,116,134,217,184,191,43,33,49,194,18,71,177,11,160,12,36,198,24,148,82,173,231,178,160,204, - 23,72,97,220,22,12,135,43,45,144,61,101,11,196,51,50,165,224,231,105,203,117,113,104,106,142,79,127,232,147,236,252, - 228,109,233,198,99,167,38,95,1,219,242,240,64,3,30,76,176,59,45,76,142,65,250,55,217,43,219,250,108,29,144,16, - 224,133,240,196,157,238,80,252,71,47,66,139,139,207,171,255,215,55,184,251,241,241,231,197,115,138,128,53,22,46,195,185, - 200,61,235,8,86,77,169,147,226,131,208,190,146,182,171,72,152,43,161,181,34,17,18,41,36,133,82,27,197,174,46,12, - 2,161,156,233,150,149,2,76,118,113,74,15,33,139,252,223,191,250,99,190,246,213,123,41,22,219,169,79,79,35,84,118, - 199,204,238,132,82,74,10,133,2,82,72,76,106,89,187,102,57,3,3,3,228,11,121,164,20,164,105,74,20,53,0,40, - 22,115,88,43,72,82,237,18,208,133,179,44,73,18,67,181,218,32,200,21,40,22,187,8,59,187,56,114,248,4,135,143, - 126,140,235,111,186,142,53,27,86,115,228,232,97,182,125,233,75,141,107,161,145,192,144,148,226,74,140,189,113,199,138,161, - 11,174,251,224,59,123,151,174,91,139,73,235,136,51,182,86,139,35,142,229,194,226,170,213,251,156,214,113,156,134,241,156, - 93,169,116,186,233,87,51,53,116,17,6,100,79,239,169,16,34,43,68,153,145,153,213,167,249,61,139,51,87,237,167,133, - 197,219,103,84,25,113,166,6,77,136,211,10,174,177,22,217,180,4,201,248,78,214,106,48,150,82,103,59,23,94,122,21, - 229,185,89,158,124,236,17,158,124,106,39,171,151,47,167,187,179,205,69,47,25,247,111,77,86,52,173,176,167,61,133,36, - 77,241,148,122,70,113,182,214,180,70,86,105,2,172,0,109,53,40,137,49,41,82,8,164,20,228,253,128,92,208,203,225, - 137,25,62,246,217,207,240,244,71,63,155,172,218,119,96,236,23,96,127,39,60,213,128,135,53,60,81,128,19,171,161,250, - 105,119,180,190,163,197,13,255,89,138,208,243,177,248,156,129,237,240,30,224,167,127,250,28,254,249,68,133,79,127,249,232, - 179,118,77,18,40,207,207,113,108,114,138,145,13,27,8,81,228,186,186,240,61,31,161,20,86,184,145,196,98,91,156,22, - 132,194,104,139,231,151,184,255,158,123,249,220,103,110,167,175,119,144,169,233,153,86,212,142,177,6,41,37,249,124,158,70, - 212,160,92,46,211,213,217,201,242,85,43,25,26,30,65,41,133,214,6,79,73,180,214,88,4,129,31,16,167,41,129,167, - 72,180,211,34,133,65,224,198,34,9,243,149,57,162,169,41,124,21,16,4,138,193,193,62,180,213,124,254,115,183,115,197, - 216,69,28,63,126,136,244,224,177,134,15,121,3,91,164,177,151,110,239,41,157,123,225,251,254,161,103,243,133,87,97,226, - 8,35,125,20,49,173,128,10,177,136,216,144,137,106,91,113,196,44,26,139,22,37,139,158,141,168,124,118,236,198,44,152, - 248,44,170,23,130,166,188,99,49,190,100,91,106,249,211,126,214,179,36,92,156,253,132,202,236,215,125,235,228,139,211,210, - 80,155,5,106,145,135,144,177,150,182,246,78,174,185,225,197,156,56,124,128,29,79,62,70,173,86,101,96,176,15,169,124, - 172,78,156,187,163,116,157,139,196,137,117,141,160,101,51,219,244,36,58,19,104,151,82,160,132,201,18,83,156,216,213,243, - 218,200,231,138,196,218,112,224,224,17,30,189,253,54,115,244,246,59,162,129,227,99,227,111,128,61,109,240,84,140,216,170, - 177,187,12,28,59,9,51,47,1,93,248,46,232,45,222,226,19,246,31,185,8,89,32,23,40,162,248,249,87,124,22,23, - 161,16,184,126,77,7,87,252,220,70,110,89,219,193,7,255,113,123,139,85,157,224,108,75,11,2,147,130,198,218,116,207, - 99,123,184,234,134,155,17,74,33,132,114,162,200,236,205,216,244,45,151,44,164,58,120,97,59,123,119,238,224,207,255,244, - 47,73,34,77,20,149,169,71,141,76,81,237,70,135,56,142,137,26,17,197,66,158,217,217,89,134,6,7,89,189,122,53, - 141,200,225,7,82,9,132,114,129,119,66,42,16,130,124,24,56,193,100,26,187,205,145,213,132,228,240,60,143,158,238,110, - 166,166,103,104,52,34,246,238,61,200,206,157,154,205,231,111,102,233,210,21,60,245,212,46,190,126,199,109,220,34,17,90, - 179,66,193,154,93,133,112,237,198,127,249,63,93,47,184,238,70,97,235,17,66,129,146,198,189,182,197,235,110,177,144,154, - 213,74,156,104,74,48,90,235,47,113,70,247,97,22,9,65,57,109,252,18,139,198,161,179,93,33,11,0,180,131,36,68, - 51,135,203,90,215,41,44,170,116,14,12,62,163,152,136,51,54,110,167,81,240,237,183,125,255,58,185,140,125,134,98,191, - 181,224,104,254,44,157,50,178,98,53,3,67,67,236,222,241,20,7,143,29,99,184,127,128,66,224,101,231,72,103,218,56, - 155,253,59,183,26,73,146,52,27,197,221,77,168,249,209,122,89,158,70,201,128,92,88,66,19,80,158,139,120,242,129,135, - 217,245,239,95,76,204,35,143,151,71,102,231,38,46,132,189,121,216,26,193,182,58,98,143,192,158,28,133,242,11,32,249, - 213,246,46,78,116,13,210,35,37,187,231,103,88,89,153,65,68,141,51,209,181,179,23,160,211,138,208,151,93,21,61,255, - 122,65,18,61,255,139,80,171,243,137,29,230,243,124,44,62,139,31,73,61,197,11,37,111,186,164,159,6,112,17,206,119, - 163,153,52,80,21,66,251,82,76,247,167,230,216,206,219,190,56,63,251,203,63,219,222,81,116,209,58,153,41,51,11,216, - 165,27,208,173,1,233,121,76,141,141,242,119,255,247,239,153,24,159,33,151,203,51,53,51,77,106,82,87,160,76,243,46, - 168,80,158,66,42,247,230,27,24,24,68,41,73,16,40,146,36,117,108,0,169,8,139,33,90,55,215,213,58,99,201,186, - 255,102,141,197,106,139,198,141,114,189,61,221,204,206,206,49,56,56,192,142,157,219,184,247,190,123,88,182,108,13,155,206, - 217,64,190,161,77,91,66,65,194,186,157,146,96,201,219,255,184,235,186,87,191,65,17,213,48,126,8,178,140,178,153,6, - 158,179,103,168,59,178,176,205,152,68,89,1,70,184,162,156,145,17,207,228,215,44,12,84,153,207,134,205,112,35,97,207, - 88,179,139,69,225,128,205,95,103,22,105,195,154,155,173,133,84,141,69,102,138,11,237,203,25,124,159,211,177,44,193,89, - 85,206,139,190,195,216,102,176,32,173,32,196,133,232,101,50,239,203,108,28,212,110,175,122,238,150,203,232,29,26,100,235, - 163,143,210,219,86,160,187,187,27,116,236,54,174,210,224,206,16,45,240,185,169,133,107,210,15,22,176,49,197,252,124,72, - 181,86,101,108,239,54,83,126,106,135,174,60,242,68,213,223,181,127,236,2,99,143,117,192,9,224,64,2,59,234,206,184, - 96,172,13,91,126,0,244,23,195,2,83,195,107,197,230,193,1,117,56,78,210,131,198,144,235,236,229,64,154,176,244,200, - 211,36,90,63,171,168,215,59,27,223,202,11,224,241,59,50,96,250,198,231,119,17,122,62,143,93,223,242,121,27,203,124, - 93,179,29,24,233,207,51,244,91,231,19,76,69,148,254,113,7,179,149,36,78,60,113,40,128,71,151,60,250,228,250,237, - 159,252,218,5,87,255,212,155,149,17,211,8,225,2,121,164,112,111,71,163,53,202,186,214,186,50,59,207,7,223,251,126, - 118,237,216,69,28,69,8,145,32,36,36,105,236,52,142,40,60,207,157,242,40,138,16,88,186,187,58,25,25,25,161,17, - 213,17,66,226,251,30,105,170,73,146,132,102,250,152,203,145,119,22,31,82,186,11,192,24,67,163,17,83,44,134,24,13, - 82,105,122,186,187,9,131,60,66,88,246,31,218,203,232,201,113,102,166,102,233,152,153,211,61,16,110,131,92,254,207,126, - 39,184,229,231,127,73,88,61,143,246,173,179,165,208,165,140,163,96,22,21,133,179,24,132,53,49,27,187,80,114,172,93, - 232,140,22,219,170,158,54,102,137,38,85,81,180,144,102,113,154,48,93,156,54,146,185,159,233,10,123,26,55,176,70,163, - 60,31,225,133,153,98,158,211,114,220,23,35,207,86,44,162,1,180,86,238,238,247,138,111,119,13,157,153,174,209,98,124, - 187,215,43,132,187,38,13,22,132,143,240,21,198,90,6,135,151,115,221,139,122,120,236,129,251,56,120,232,48,43,150,47, - 67,90,131,78,154,192,57,24,235,50,227,23,119,108,98,17,160,142,128,219,190,248,37,238,255,200,199,245,155,70,103,234, - 75,97,34,132,109,30,60,154,192,46,13,39,4,76,24,152,150,80,233,117,170,119,198,128,13,61,35,28,237,25,22,210, - 198,166,45,204,228,170,64,136,207,79,159,119,233,183,165,173,240,108,69,232,137,47,91,182,222,101,241,195,111,107,252,246, - 95,197,231,251,120,148,218,124,46,188,117,41,23,254,252,6,30,186,114,128,183,129,169,106,59,38,148,120,172,31,182,237, - 254,195,63,153,62,180,103,39,82,228,49,153,49,149,37,197,24,231,88,100,165,162,49,55,199,71,223,243,30,226,90,68, - 169,212,65,165,214,32,54,134,84,27,124,207,71,41,15,164,32,213,174,147,73,163,132,98,190,68,79,103,47,7,247,31, - 68,9,69,224,5,8,43,240,164,162,144,203,103,120,129,115,220,83,158,36,181,9,81,26,97,208,104,171,209,104,82,82, - 240,140,243,32,178,146,92,46,164,191,127,128,165,35,203,81,184,0,196,113,66,241,69,48,252,194,235,188,55,252,206,111, - 8,146,170,243,50,178,30,210,26,164,204,66,126,229,226,150,66,186,213,176,84,8,225,33,240,129,16,107,189,150,105,152, - 108,117,42,58,139,220,177,153,69,109,19,59,106,154,218,122,24,60,180,144,24,164,91,231,11,201,233,213,40,179,226,192, - 229,198,91,33,17,82,144,70,117,202,19,167,152,31,27,165,50,126,146,104,242,20,233,236,12,186,86,197,54,195,250,172, - 205,46,186,208,197,22,101,161,197,86,200,5,172,78,200,236,87,44,40,231,91,133,192,178,224,55,36,178,96,78,43,90, - 126,207,2,167,231,50,210,71,120,190,27,155,76,132,213,117,210,198,28,141,218,4,158,109,112,197,37,151,81,204,151,120, - 252,209,173,212,27,41,126,88,112,63,35,43,232,74,137,236,6,34,90,36,204,230,50,194,26,205,155,127,242,21,252,194, - 255,252,25,188,82,206,134,16,9,24,77,224,113,3,247,43,120,226,48,28,30,132,185,17,208,62,139,12,233,173,37,112, - 218,170,103,232,171,82,99,158,245,227,172,29,208,217,138,16,60,255,58,161,255,44,197,71,2,149,147,85,118,254,212,189, - 116,92,220,199,69,219,166,248,6,144,51,214,8,37,231,45,118,98,201,177,195,51,31,253,173,183,182,255,247,15,189,55, - 236,110,47,98,90,35,8,40,1,149,249,89,190,248,233,219,104,43,150,8,194,144,125,251,15,80,40,148,90,249,214,190, - 23,16,37,49,82,10,124,207,167,45,95,96,227,134,141,220,244,162,155,40,21,139,28,58,112,144,167,119,238,98,104,104, - 152,222,222,94,226,36,65,74,141,82,210,249,14,103,23,180,84,206,129,49,73,157,57,173,82,30,86,24,18,163,9,189, - 0,99,52,74,41,58,58,58,73,211,148,106,165,202,204,244,36,199,144,94,233,77,175,84,191,247,215,127,156,217,136,153, - 204,144,75,101,0,111,102,237,102,4,167,231,172,187,24,229,197,227,202,226,116,27,219,180,171,48,77,252,102,241,154,91, - 60,99,196,113,205,136,229,76,97,168,205,112,35,97,89,180,165,202,222,99,133,54,124,47,164,49,63,79,189,58,75,195, - 90,60,207,119,5,48,12,145,126,128,244,60,60,47,64,249,185,204,175,91,101,171,109,88,112,247,182,78,203,150,61,167, - 166,62,94,176,32,1,81,205,239,21,22,132,6,145,96,77,226,182,97,90,211,168,167,36,141,8,157,38,160,83,116,154, - 160,20,40,225,196,201,198,8,206,219,188,153,142,82,59,15,62,248,16,23,92,176,153,174,238,78,82,157,58,75,143,172, - 35,115,55,22,78,103,61,91,139,77,234,92,243,202,91,213,238,37,75,75,91,255,226,29,35,107,118,236,223,220,1,7, - 19,56,30,194,252,17,72,255,12,231,16,250,19,56,83,57,128,224,251,232,78,188,111,211,17,62,47,139,208,127,4,192, - 249,91,22,157,156,135,40,249,168,188,231,200,138,117,205,204,35,19,236,124,100,66,108,132,224,103,160,24,91,150,234,212, - 92,154,131,181,39,160,120,255,254,125,234,186,167,119,112,213,21,87,161,117,234,140,57,37,212,231,102,121,232,222,123,200, - 133,1,231,157,119,9,191,244,171,191,157,141,88,13,18,157,32,4,164,169,118,126,49,64,71,169,141,43,175,188,138,203, - 47,191,12,33,36,213,106,157,161,145,37,244,246,246,243,212,182,167,16,66,48,60,50,66,154,166,232,38,111,196,146,233, - 205,92,247,97,140,193,247,125,247,166,213,6,229,123,153,133,105,198,164,149,130,92,46,207,192,96,63,213,234,44,155,54, - 175,229,111,222,241,215,162,173,61,143,77,51,210,27,11,192,110,19,225,104,25,58,103,238,132,153,68,124,209,90,62,89, - 4,183,152,86,113,49,42,115,17,68,182,210,39,220,159,23,214,241,130,133,173,90,211,155,199,102,27,42,87,188,52,146, - 5,162,162,200,254,134,12,80,133,28,197,48,135,95,244,153,154,156,194,88,67,33,204,19,71,17,38,106,184,130,128,2, - 2,60,79,162,60,137,242,37,158,167,50,16,223,98,140,64,72,31,229,185,104,63,33,165,219,236,53,253,160,141,37,19, - 108,145,38,17,113,28,147,164,13,162,168,130,213,105,182,197,116,60,48,79,228,8,252,2,161,151,35,110,104,166,166,102, - 152,157,155,102,174,54,65,84,143,178,85,190,102,199,142,237,92,121,213,21,173,232,105,41,188,214,117,189,32,204,93,136, - 10,50,22,26,213,26,231,92,124,161,232,123,207,219,219,238,251,179,183,95,60,242,249,187,109,31,80,131,59,95,10,251, - 246,67,244,1,92,142,88,9,231,2,177,49,137,184,81,72,106,194,146,96,159,219,88,158,197,69,200,26,184,240,69,63, - 218,34,212,44,62,245,72,243,218,223,123,254,23,159,179,105,254,199,222,191,139,173,119,28,166,109,46,230,10,231,129,227, - 165,144,31,128,238,105,24,206,195,106,15,206,155,131,139,239,246,212,57,201,27,95,218,253,143,127,244,251,106,245,178,149, - 24,147,56,113,32,150,168,90,225,169,199,30,69,38,49,47,184,230,26,62,245,233,59,56,114,228,56,202,47,160,211,20, - 165,36,105,154,98,173,37,77,52,109,197,60,151,92,114,49,87,94,121,5,214,66,154,26,108,38,84,244,130,128,11,183, - 92,196,222,189,123,57,124,248,48,43,86,174,196,36,177,3,174,165,192,195,203,88,183,238,46,154,166,105,182,69,81,206, - 151,90,138,140,105,11,105,10,81,20,227,123,138,246,206,18,191,246,214,95,163,163,179,3,155,214,79,67,102,69,203,112, - 43,251,63,35,51,112,52,91,23,55,85,18,139,41,130,217,158,222,54,67,129,155,104,188,144,8,171,78,147,97,156,222, - 1,217,204,59,121,193,176,127,161,11,50,89,244,241,98,31,48,231,182,108,179,11,19,25,16,148,250,233,180,121,30,248, - 198,215,137,170,53,206,219,120,14,165,66,158,188,23,146,154,132,88,87,73,106,154,200,90,132,84,153,255,15,72,169,48, - 169,118,91,69,213,202,115,59,29,196,182,26,157,197,30,88,107,49,198,253,59,87,44,148,243,254,17,1,141,40,98,174, - 58,195,244,244,33,198,70,79,186,227,236,251,116,119,119,209,213,217,73,208,231,152,238,107,215,175,33,77,83,234,245,26, - 129,159,253,62,165,178,209,107,1,220,151,82,34,68,182,17,203,10,118,163,94,161,191,163,141,151,255,213,219,114,183,231, - 131,75,249,196,157,178,31,152,150,66,189,205,216,189,1,212,255,21,23,48,80,1,142,77,28,197,122,62,151,44,93,70, - 49,151,107,117,231,205,71,156,234,239,189,0,45,46,66,79,126,197,109,199,126,84,43,122,55,118,73,162,72,243,154,255, - 245,13,238,121,226,249,91,124,154,50,12,223,157,36,241,83,174,169,102,7,200,198,190,89,191,109,223,172,15,228,87,65, - 167,134,190,192,37,63,172,50,176,110,10,86,31,47,230,151,151,175,187,112,96,203,127,251,153,224,69,47,127,25,97,32, - 51,191,98,139,20,6,29,215,217,189,253,41,26,213,42,231,158,179,129,201,137,105,62,251,185,59,220,77,52,78,29,153, - 76,90,180,78,17,66,225,41,197,198,13,27,185,225,134,27,72,146,20,157,9,13,201,124,117,76,166,13,218,176,97,3, - 39,78,156,96,122,122,138,246,142,14,146,36,193,243,188,86,209,81,74,225,123,62,22,75,24,230,78,187,147,42,41,73, - 83,157,17,24,107,76,207,76,240,147,111,121,35,107,214,175,194,196,53,7,160,47,6,123,79,91,90,57,194,159,148,106, - 1,111,22,103,168,220,173,92,100,163,145,97,44,52,173,80,23,143,89,139,137,118,180,182,88,66,184,49,47,91,136,45, - 116,69,214,100,79,193,169,188,155,58,168,38,171,24,229,64,92,99,60,194,98,39,87,95,247,34,62,127,219,109,188,227, - 159,222,197,213,87,92,134,77,18,74,109,5,186,251,122,233,236,234,34,151,207,101,5,195,98,181,198,88,75,16,8,68, - 170,177,54,117,4,71,99,92,184,99,166,162,183,139,214,248,70,184,174,211,104,65,212,72,152,153,157,97,98,124,130,180, - 150,16,199,117,188,64,82,106,47,177,116,168,159,174,238,118,194,156,27,249,82,29,56,177,170,214,164,105,140,64,100,57, - 242,142,211,149,218,20,223,247,179,162,227,116,97,14,71,116,12,121,79,10,82,99,80,158,79,172,99,66,47,228,250,223, - 249,149,240,35,19,99,151,108,185,123,43,61,198,114,80,96,126,205,178,175,2,141,71,112,38,124,6,248,234,232,1,182, - 206,141,211,155,47,160,179,194,96,172,37,244,20,47,60,127,133,99,219,159,165,96,124,199,134,100,63,106,158,80,171,248, - 196,134,87,61,143,139,143,205,10,207,16,112,37,120,69,232,152,128,174,45,16,10,144,167,32,167,160,87,66,183,20,244, - 24,203,176,133,37,51,176,108,174,32,135,14,175,236,239,111,187,225,230,210,85,175,127,179,220,124,233,133,4,94,1,155, - 156,194,164,22,43,2,84,230,5,124,96,247,110,162,74,153,101,75,151,225,249,57,30,120,232,235,28,63,57,138,31,230, - 136,35,131,49,154,36,137,81,217,93,111,201,146,165,188,228,37,47,67,8,137,214,6,41,21,82,42,226,56,113,155,21, - 107,144,74,18,197,17,253,3,253,76,76,78,50,57,57,73,119,119,55,58,91,163,54,127,22,214,226,7,65,246,51,220, - 155,27,4,105,170,1,131,54,49,213,250,60,55,220,124,61,151,92,117,25,38,174,184,81,71,102,106,245,236,130,63,29, - 58,56,195,102,35,179,134,16,173,113,141,108,3,40,22,81,110,154,32,242,217,155,254,211,229,23,217,103,105,155,200,146, - 163,52,160,145,210,100,18,23,223,121,130,139,69,72,141,176,173,142,200,8,141,176,150,32,231,243,186,183,188,145,77,155, - 214,50,126,242,56,133,192,99,226,212,56,99,123,198,17,66,146,207,23,80,50,160,84,106,163,171,187,7,41,37,81,84, - 35,12,36,133,98,17,233,41,167,50,207,70,48,79,9,7,196,167,138,153,185,89,198,199,199,49,22,38,38,198,25,27, - 27,5,97,89,58,50,204,234,21,195,20,139,75,16,170,9,44,187,206,197,24,137,181,6,99,146,214,177,116,161,149,174, - 139,107,18,16,83,215,250,180,58,85,215,1,137,204,192,222,44,12,79,214,245,237,81,220,160,51,95,224,53,127,250,7, - 193,39,254,215,219,46,185,252,222,237,116,91,24,21,232,255,105,217,63,0,241,57,110,60,3,96,162,86,97,162,86,57, - 237,28,228,124,197,21,254,48,42,239,60,134,190,231,2,244,163,44,66,22,200,7,146,70,244,252,46,62,38,43,60,123, - 64,14,66,113,37,44,77,224,252,60,108,106,64,151,113,240,100,62,133,190,26,116,54,160,189,177,172,191,39,89,190,188, - 45,190,96,93,225,220,87,190,70,94,125,238,58,70,250,7,92,102,130,174,145,234,4,41,2,16,26,33,52,73,189,194, - 145,189,187,153,61,53,78,127,223,0,105,106,40,215,98,238,252,202,61,68,137,110,145,118,149,244,48,104,164,112,42,242, - 107,174,185,150,158,238,62,170,213,42,74,121,45,224,209,243,92,17,106,94,228,72,137,54,134,158,158,30,198,198,198,208, - 90,227,251,62,113,28,103,186,176,212,141,6,8,148,148,142,187,34,5,214,100,133,201,151,204,204,205,115,209,197,231,113, - 243,173,55,162,147,154,219,250,100,119,221,103,51,142,63,19,57,88,144,88,44,30,85,78,231,250,180,92,126,196,194,144, - 181,96,193,209,140,10,48,173,177,102,1,164,182,8,227,10,101,101,118,154,156,47,241,252,16,25,128,80,138,211,242,115, - 178,223,34,113,199,95,120,25,39,74,39,156,179,229,2,84,8,147,227,99,108,188,96,51,36,142,115,19,71,41,213,106, - 149,249,249,10,251,247,63,77,181,86,165,86,109,96,109,64,106,52,65,62,231,214,212,97,64,62,23,162,68,70,50,52, - 144,36,17,66,64,177,173,64,161,144,99,227,57,107,232,235,235,166,88,204,163,141,161,158,38,78,63,5,72,233,35,164, - 69,72,183,217,84,173,132,215,172,208,24,155,141,113,162,213,145,25,52,86,187,142,71,74,153,121,253,100,99,104,182,62, - 151,6,12,26,172,32,214,13,250,187,186,120,205,159,254,126,112,199,111,191,109,203,197,15,238,138,11,150,114,44,168,236, - 183,28,95,147,221,42,158,205,95,171,22,120,217,120,44,206,74,67,248,174,45,89,127,216,69,168,89,124,106,13,205,107, - 126,239,254,231,101,241,105,190,244,113,16,47,133,48,129,193,58,156,155,131,203,27,112,201,231,61,54,219,13,203,58,54, - 109,88,139,10,115,178,109,176,223,43,14,244,169,225,213,43,68,247,134,245,44,93,185,134,82,190,23,80,36,204,128,174, - 96,117,136,81,138,84,54,240,76,17,37,60,180,46,51,57,54,74,84,157,163,167,173,136,137,99,194,98,23,59,118,238, - 99,215,222,131,72,233,99,18,231,100,40,148,69,38,144,232,148,11,46,184,136,145,165,203,152,171,84,156,130,218,44,208, - 242,141,113,178,11,132,112,64,179,204,86,199,214,50,56,56,232,248,66,66,180,64,103,165,36,113,156,16,248,97,166,145, - 106,70,12,91,2,63,68,155,26,221,189,93,188,248,101,183,32,133,37,205,182,46,205,78,166,181,133,130,69,110,132,11, - 43,240,197,199,244,116,165,148,93,64,212,178,191,54,234,13,140,73,241,2,133,239,231,51,69,183,201,138,141,62,61,4, - 80,184,146,37,22,17,21,149,144,8,147,80,158,42,35,165,68,169,60,97,91,9,145,203,163,194,124,11,204,118,227,161, - 68,216,180,213,137,89,107,209,169,97,253,230,75,240,194,93,140,31,59,196,146,158,54,71,233,203,41,242,249,78,250,250, - 186,193,46,37,77,99,210,52,65,199,16,197,17,73,154,146,36,49,198,106,226,56,194,87,110,52,245,51,87,130,32,116, - 254,74,190,231,57,145,177,49,164,73,138,167,4,158,231,103,128,52,40,105,157,32,213,64,170,117,70,207,200,172,52,76, - 179,112,103,93,163,176,142,74,145,166,89,23,156,58,199,4,41,51,247,129,12,7,202,60,177,155,61,160,198,16,39,49, - 3,125,3,220,248,231,127,152,123,248,87,254,191,139,46,216,126,120,202,90,38,58,160,254,183,48,121,5,216,194,179,92, - 27,255,62,210,205,231,66,159,103,51,5,253,158,60,161,23,23,33,107,224,194,155,127,48,69,104,113,241,121,229,239,126, - 131,175,111,61,245,188,235,120,74,56,141,215,227,16,52,160,91,194,234,28,92,106,224,170,195,176,121,199,133,231,46,217, - 244,171,63,81,120,217,173,47,99,160,103,192,129,182,162,105,146,41,1,141,38,198,152,121,140,54,72,5,82,134,46,251, - 93,128,103,4,216,8,140,97,110,252,56,181,242,20,109,197,54,172,129,212,104,144,130,47,221,249,32,243,243,49,97,62, - 135,240,193,232,4,147,26,148,231,81,44,229,185,224,188,243,169,55,234,20,138,153,37,71,118,199,109,105,159,132,116,171, - 253,51,174,119,41,37,97,16,158,230,141,99,12,4,65,136,177,169,75,35,213,22,79,42,180,244,48,66,18,155,136,87, - 191,246,37,132,161,64,235,4,37,189,76,104,9,70,8,148,16,11,155,31,107,29,231,166,85,22,100,6,248,106,36,41, - 88,207,221,91,69,132,65,96,200,35,172,65,89,3,196,68,213,41,170,115,83,180,229,115,232,32,68,230,219,80,65,9, - 229,23,90,64,175,21,26,105,23,118,97,182,137,237,88,199,142,46,22,59,137,171,13,60,37,49,58,166,58,125,202,17, - 23,189,128,32,215,70,144,43,160,2,31,25,184,115,34,132,116,204,243,102,183,104,45,171,214,109,34,138,99,78,156,58, - 202,96,95,31,113,220,192,87,162,101,221,33,149,64,90,137,10,45,126,46,0,2,132,40,44,216,189,102,224,126,146,141, - 178,198,58,207,30,112,96,180,209,238,247,89,109,80,74,162,164,66,42,55,198,217,236,123,108,230,138,208,202,32,147,14, - 103,210,58,93,24,149,141,205,70,63,145,173,227,197,34,19,126,131,176,25,193,85,100,185,101,86,58,59,14,43,208,81, - 194,210,229,67,164,127,246,191,58,182,254,244,111,93,113,254,228,220,108,21,230,45,60,60,47,68,185,240,44,23,255,233, - 29,233,115,84,128,22,23,161,31,20,48,221,196,124,234,177,225,53,191,119,255,243,174,248,88,96,30,104,3,245,50,104, - 159,129,85,121,184,72,192,165,71,225,162,3,195,35,171,54,254,218,207,181,253,198,207,191,89,245,118,14,0,25,167,195, - 58,203,4,157,1,192,50,107,79,221,159,5,18,149,113,80,82,48,6,105,5,66,106,102,39,198,168,204,76,161,178,107, - 39,49,134,48,95,224,233,93,251,120,224,193,71,200,229,242,88,44,73,154,96,113,188,144,56,142,185,250,234,107,241,125, - 143,70,189,142,167,20,86,186,213,185,53,6,43,37,202,115,227,88,148,38,40,207,195,164,89,14,185,82,173,55,107,189, - 94,207,214,199,153,12,32,3,173,211,36,109,201,50,130,192,99,124,106,156,235,111,186,156,190,254,126,146,184,134,151,141, - 122,205,206,71,102,12,240,150,162,92,186,55,190,182,180,156,139,17,6,105,125,192,50,63,55,138,141,35,2,191,157,160, - 208,129,10,18,231,101,44,36,214,8,138,109,29,232,218,60,42,53,216,184,70,101,118,30,153,243,9,219,58,200,21,123, - 16,94,9,33,60,76,22,33,217,12,2,180,100,90,55,173,81,133,18,181,40,225,11,183,223,197,45,55,191,136,182,66, - 142,52,170,161,107,117,170,229,6,101,41,240,194,0,21,4,120,190,115,144,244,131,0,233,41,132,82,110,181,109,13,27, - 54,110,100,91,181,204,212,116,153,238,142,34,164,177,99,107,219,5,203,179,56,141,241,60,229,36,31,89,81,55,214,102, - 76,118,213,234,38,69,86,224,148,146,11,86,105,86,32,133,211,229,185,163,230,176,42,87,180,28,165,192,99,193,122,196, - 66,75,231,101,140,235,142,132,114,91,75,99,22,114,140,28,30,232,192,112,163,227,172,19,202,18,102,149,200,126,183,163, - 78,164,115,49,235,55,108,98,230,143,127,123,100,255,255,252,131,235,214,197,102,84,195,216,209,192,219,51,16,167,137,176, - 150,249,124,192,124,16,32,173,37,159,106,202,129,231,98,204,4,207,109,1,250,65,142,99,205,226,211,72,12,175,254,221, - 231,23,230,211,180,214,120,41,136,9,40,120,48,226,193,230,18,92,53,1,151,62,220,217,190,33,247,250,91,187,223,240, - 255,253,154,88,179,226,28,208,13,108,60,237,66,3,133,204,138,131,68,102,109,252,2,101,159,214,197,189,248,0,74,9, - 213,185,57,42,51,83,232,196,96,53,248,94,182,209,193,227,158,123,31,100,106,118,146,124,169,3,107,154,124,29,73,18, - 199,44,95,177,156,222,222,30,26,141,6,237,165,118,124,169,136,162,24,47,155,255,91,9,161,82,18,134,33,66,72,82, - 145,144,36,77,162,161,211,139,197,218,16,71,13,167,128,111,42,240,133,68,102,172,92,97,161,92,153,165,171,43,207,5, - 231,159,139,77,19,60,233,157,238,134,218,234,58,50,37,185,200,36,180,214,145,41,143,31,62,142,50,150,145,165,125,104, - 13,74,5,120,70,83,173,205,145,154,6,186,86,165,216,149,71,133,237,164,4,24,169,240,130,54,74,93,35,124,234,67, - 31,228,130,13,231,176,97,205,106,106,233,12,245,233,57,226,234,28,42,232,33,87,234,70,5,42,187,168,220,69,107,16, - 104,44,66,73,148,181,116,13,143,48,93,174,240,206,119,253,43,151,95,186,133,75,46,56,159,48,40,96,51,191,101,157, - 52,72,226,42,66,204,99,90,84,33,129,31,230,200,23,10,228,11,69,84,24,112,222,69,91,216,250,205,7,169,213,26, - 116,20,242,206,61,50,203,100,107,130,189,89,127,114,122,240,97,38,18,150,25,174,70,147,40,152,241,157,68,43,46,58, - 219,46,105,183,73,211,214,249,73,35,101,86,220,105,173,192,23,19,12,23,127,246,60,119,99,106,110,24,157,175,145,114, - 231,196,72,76,10,73,146,18,132,57,114,249,60,190,239,147,234,20,164,64,153,2,74,5,92,255,250,215,243,213,195,71, - 87,86,254,250,221,87,23,96,255,140,16,147,123,124,239,212,80,156,152,59,215,47,231,238,117,75,200,197,9,22,75,212, - 168,146,79,52,4,242,185,47,64,63,168,34,20,20,125,230,107,9,111,120,30,21,159,230,203,57,23,72,193,239,131,158, - 58,108,204,193,149,21,184,242,126,212,102,251,202,155,6,95,243,135,111,245,207,187,224,82,55,92,153,26,146,4,45,93, - 210,128,27,50,196,34,81,35,139,20,214,42,187,91,101,122,40,233,220,232,116,163,78,101,106,18,27,215,51,149,182,227, - 199,4,97,64,173,150,240,248,227,187,16,82,16,69,13,103,189,137,91,151,231,243,121,150,142,44,101,118,102,22,63,8, - 24,236,31,68,167,14,227,105,110,179,172,181,153,118,201,117,94,105,156,128,117,56,131,49,6,99,45,137,54,148,218,219, - 153,58,213,112,220,34,207,207,108,64,4,198,186,87,161,4,204,205,159,226,101,215,223,154,113,12,229,66,113,21,153,118, - 201,90,164,205,46,46,148,147,38,52,191,142,199,212,196,36,127,253,39,127,206,235,127,236,101,220,250,146,27,48,8,114, - 126,129,163,99,71,232,234,76,41,132,41,181,169,57,188,182,24,194,118,68,152,39,5,130,246,94,242,157,3,252,201,95, - 189,157,151,191,244,22,174,190,246,114,122,250,186,104,68,85,210,250,113,210,234,4,190,151,35,95,106,71,22,243,8,207, - 203,52,87,142,123,172,177,228,10,69,174,190,230,106,226,242,44,91,183,110,101,223,211,59,89,187,118,29,171,87,174,166, - 189,171,45,243,172,209,200,236,60,10,161,48,198,146,212,42,36,181,26,85,53,67,174,80,32,44,182,177,97,253,6,118, - 110,125,146,80,121,174,131,177,110,205,110,108,243,220,36,173,237,94,83,24,108,22,5,38,234,212,180,228,18,45,81,109, - 230,223,212,204,184,215,153,38,183,169,225,18,194,97,84,74,41,7,174,167,174,232,45,246,187,118,92,48,147,177,225,131, - 214,249,215,70,131,117,227,153,39,20,82,250,156,56,118,146,71,30,125,146,217,217,10,197,82,7,113,234,92,17,139,82, - 153,216,243,101,174,163,157,74,190,83,153,82,238,220,155,42,141,11,114,198,110,219,106,236,212,61,74,154,163,3,221,20, - 147,52,27,83,93,167,103,197,247,65,68,252,110,139,144,49,112,209,247,138,9,41,1,165,0,121,231,33,222,254,190,29, - 220,115,100,254,121,131,243,120,192,86,8,87,65,135,129,145,8,46,12,224,5,79,192,101,135,46,58,103,213,213,111,251, - 205,220,77,183,190,132,130,10,177,73,12,194,67,202,16,43,3,55,70,145,102,155,6,90,2,70,219,132,69,133,61,205, - 200,202,98,192,164,96,83,230,167,166,209,81,132,176,6,147,106,164,200,129,48,4,65,158,199,30,223,197,209,99,163,89, - 158,151,165,16,134,164,58,37,142,35,86,173,88,65,224,5,196,141,4,129,108,17,7,155,250,159,230,22,68,91,227,120, - 27,25,15,136,76,221,78,147,109,108,28,95,168,84,44,146,38,49,158,39,50,31,99,31,163,13,185,32,96,98,242,36, - 55,223,122,61,155,206,63,7,19,71,144,173,248,23,2,134,229,34,43,13,15,211,50,252,113,24,152,37,101,195,166,245, - 188,229,167,222,204,206,173,59,248,192,191,126,136,55,188,233,21,148,43,227,124,237,158,187,217,180,97,21,43,87,44,161, - 183,111,144,242,244,12,86,149,233,232,233,197,43,228,177,218,240,226,87,190,10,21,132,116,182,133,220,113,215,55,24,30, - 232,101,203,69,231,208,81,10,49,105,132,174,55,168,68,117,100,181,64,190,173,132,44,228,241,51,233,8,128,82,30,58, - 142,232,40,42,94,250,226,23,50,55,51,207,209,35,199,217,190,107,27,198,26,114,69,159,66,49,79,160,60,172,5,223, - 15,41,149,218,41,22,10,228,194,34,86,8,226,122,131,36,113,30,203,75,70,150,114,96,255,62,150,44,29,65,74,157, - 101,185,11,172,116,36,64,99,178,77,85,54,146,138,150,232,55,163,14,88,209,74,181,16,66,100,227,58,45,110,77,166, - 241,200,192,125,215,197,164,38,201,156,10,36,210,247,22,156,32,141,113,124,41,211,84,214,139,133,200,33,75,107,75,38, - 1,99,171,88,227,179,100,89,63,93,189,215,179,103,247,33,238,190,231,126,238,184,235,94,150,159,154,173,188,30,100,5, - 194,57,72,61,33,170,195,74,140,165,16,201,56,49,43,192,218,165,253,28,236,235,66,87,170,174,248,26,251,109,141,129, - 212,203,87,108,226,185,42,66,82,193,137,189,238,239,3,155,3,103,215,9,103,221,255,63,131,148,228,75,84,106,137,62, - 127,128,169,191,122,132,187,102,35,30,255,1,22,150,115,28,79,135,47,0,215,1,131,208,138,13,241,128,163,184,236,247, - 141,64,63,168,97,232,172,194,6,9,215,9,184,101,14,110,250,90,33,127,149,255,214,95,89,241,75,255,242,14,111,203, - 249,151,184,187,154,6,33,83,172,172,162,69,138,176,2,165,113,130,165,22,249,77,52,47,203,150,36,193,178,192,203,16, - 214,32,173,161,60,53,73,101,118,26,29,71,88,171,29,160,168,20,169,177,120,65,145,143,124,228,223,217,181,239,32,66, - 185,55,162,146,146,70,163,193,242,101,203,24,26,26,162,81,143,72,226,24,223,243,25,25,30,161,163,163,163,181,209,106, - 90,115,10,225,124,166,155,212,27,99,109,230,247,99,81,205,55,167,148,8,4,73,28,81,40,228,220,29,93,187,72,159, - 74,121,150,21,43,135,185,238,69,87,67,90,205,236,49,112,41,7,210,100,177,55,205,77,140,187,176,164,16,206,12,29, - 119,193,10,64,73,159,153,201,41,94,112,229,69,212,171,101,142,30,59,65,169,163,141,70,82,101,205,138,213,236,221,123, - 132,147,227,19,44,93,178,20,133,161,94,153,67,160,221,230,40,215,70,163,81,65,165,13,174,190,250,18,166,167,78,241, - 228,227,219,104,52,160,189,171,159,160,24,184,245,115,98,168,215,42,164,141,134,203,140,80,14,232,23,82,49,123,106,20, - 91,155,65,40,139,239,91,6,135,135,24,26,30,166,212,222,70,88,200,17,132,1,18,231,201,164,181,102,126,126,158,217, - 217,121,198,199,79,49,57,57,73,189,94,35,142,234,40,41,41,22,157,217,255,216,216,40,93,93,93,24,92,87,226,232, - 0,166,101,231,138,16,142,46,161,53,82,73,247,125,198,32,61,183,20,176,89,247,104,23,235,227,50,230,183,109,158,39, - 200,86,236,11,139,3,22,165,125,216,211,178,202,68,171,104,181,206,107,147,243,36,5,210,115,14,11,82,66,152,83,44, - 95,57,204,13,55,92,201,245,55,94,137,215,91,244,106,115,243,114,249,212,60,23,91,42,235,96,95,175,177,15,105,120, - 200,8,246,140,64,121,87,185,202,147,161,207,234,66,64,109,182,66,96,53,117,105,241,148,68,158,225,198,8,240,226,55, - 252,236,115,87,128,90,69,200,19,156,218,111,216,244,181,71,73,139,48,94,8,232,233,201,35,197,233,133,200,97,15,224, - 121,64,168,136,235,154,131,255,223,55,136,63,187,143,156,117,145,189,143,253,8,10,80,115,217,171,128,30,240,11,78,30, - 177,202,131,75,5,188,164,10,183,30,201,5,87,140,190,244,166,245,55,252,243,223,119,188,254,167,222,76,33,144,152,36, - 1,27,33,189,196,109,147,132,231,114,233,49,8,210,86,139,221,60,80,34,147,83,52,137,59,198,106,87,72,140,70,232, - 148,70,121,142,249,217,105,116,26,97,172,70,91,199,225,72,77,138,16,1,115,229,132,127,123,223,71,168,214,27,24,43, - 104,107,111,7,99,220,232,181,108,153,3,142,149,135,239,135,128,96,96,104,136,190,254,62,7,122,74,143,32,112,1,131, - 152,172,0,9,209,42,100,162,73,39,206,86,232,82,56,223,231,35,71,14,35,149,32,137,99,138,133,18,38,49,204,205, - 157,226,197,47,190,14,105,106,84,102,167,168,205,206,81,47,207,81,153,159,162,94,157,195,152,212,109,210,50,81,169,176, - 26,27,87,136,203,179,196,181,121,132,73,128,20,233,183,51,63,51,71,18,31,103,213,138,33,226,196,99,247,222,131,116, - 118,118,210,217,81,164,127,160,135,83,167,198,121,240,129,135,24,30,90,66,87,103,23,229,242,60,198,166,40,31,6,6, - 6,216,187,243,105,186,58,66,134,6,186,233,235,237,101,108,108,150,221,251,14,82,141,27,228,242,57,242,94,232,88,193, - 113,76,163,82,6,163,81,158,68,6,62,243,83,147,212,231,103,200,229,115,8,105,209,58,198,104,75,144,11,201,5,1, - 133,92,142,66,230,137,93,42,21,233,104,111,163,152,47,208,214,94,194,243,157,128,180,86,175,49,61,53,205,228,169,9, - 124,223,167,82,169,80,107,212,41,149,10,24,173,23,121,240,100,55,58,165,88,236,53,100,164,235,58,117,147,37,173,84, - 171,224,104,171,91,27,43,247,217,197,229,144,69,243,8,68,102,60,118,250,67,46,26,197,154,221,206,153,141,192,2,77, - 34,4,235,186,87,173,13,105,26,145,36,13,58,219,10,92,124,249,37,98,228,165,47,149,135,86,13,201,3,135,14,89, - 127,186,220,200,195,148,128,83,169,16,83,5,168,30,135,180,227,212,12,175,59,118,138,251,246,159,224,156,64,114,168,191, - 131,208,242,172,5,232,185,143,102,22,160,60,75,254,155,39,217,122,223,1,62,210,87,224,231,94,187,158,210,149,195,12, - 175,232,32,150,2,153,24,172,208,164,13,152,154,134,162,136,40,253,221,67,76,111,61,197,200,143,24,231,105,184,15,5, - 20,151,195,146,8,46,16,112,241,60,156,51,26,248,107,219,111,189,161,239,210,183,254,98,113,253,149,87,73,95,42,116, - 50,143,80,2,37,52,86,65,34,20,2,137,167,21,34,177,88,37,137,125,80,26,148,21,167,3,74,66,96,141,118,46, - 131,25,200,40,17,36,245,58,243,83,51,217,70,202,160,141,118,88,2,96,137,41,20,123,121,228,177,237,76,78,78,227, - 135,62,104,133,231,249,164,113,196,234,213,171,29,142,22,248,20,10,5,199,245,16,34,219,130,168,12,60,150,72,37,145, - 218,44,128,224,144,37,97,58,44,161,121,193,232,196,141,15,66,74,230,231,231,105,107,203,83,106,43,33,165,228,228,169, - 19,68,141,121,172,142,168,204,78,162,27,13,140,105,218,196,106,188,208,163,26,85,9,148,71,80,232,68,8,69,125,110, - 154,250,236,56,202,104,12,150,56,200,97,165,194,47,212,8,114,134,250,20,68,94,68,255,96,129,199,182,143,17,230,125, - 36,18,29,87,56,119,211,42,60,47,228,67,31,191,141,203,46,187,140,203,175,188,136,180,94,167,82,63,76,231,224,74, - 150,175,63,159,253,71,118,178,102,249,32,158,74,57,111,211,48,147,83,115,28,62,60,198,212,232,36,3,3,61,244,247, - 116,211,221,213,78,206,247,169,207,205,209,72,26,116,122,18,235,73,234,177,162,77,248,142,252,137,113,196,195,84,18,40, - 15,79,41,180,72,29,142,150,73,83,124,169,72,109,138,231,229,51,128,55,68,73,143,52,49,204,205,205,83,175,71,204, - 150,231,24,24,236,115,199,189,25,211,179,136,155,36,90,148,240,108,21,46,29,46,36,69,115,92,166,101,38,223,148,84, - 156,206,161,114,93,171,181,214,1,255,176,40,117,195,182,64,108,33,84,166,219,91,48,34,91,176,4,177,153,7,146,251, - 253,22,227,10,28,18,171,33,78,12,105,84,163,83,5,188,236,149,183,50,122,197,150,194,214,79,126,97,237,161,15,255, - 123,199,154,153,202,64,151,181,253,99,240,192,74,216,117,94,170,167,147,84,39,41,208,54,58,67,223,138,126,234,249,80, - 72,125,118,38,208,115,218,1,53,47,42,105,45,231,31,223,199,184,78,121,186,150,80,121,108,140,187,62,187,143,158,221, - 211,4,93,33,141,130,79,41,12,184,243,253,17,223,252,178,34,248,210,33,214,238,220,207,97,183,214,38,0,238,255,33, - 117,64,159,7,174,117,99,22,243,160,166,161,93,194,50,31,46,77,224,230,10,188,100,2,174,180,47,185,97,253,133,239, - 254,219,254,23,252,214,175,230,6,151,175,20,202,196,96,211,214,93,199,10,133,144,62,194,42,164,49,72,147,186,187,91, - 203,250,32,91,129,90,155,201,1,12,214,68,164,81,13,145,52,16,94,136,231,121,152,70,141,217,137,113,210,168,6,164, - 104,147,130,132,52,50,40,44,97,33,135,80,37,62,240,193,127,103,223,129,195,248,97,128,49,78,159,21,4,30,203,150, - 45,167,90,169,129,21,52,26,17,181,90,13,63,240,233,233,235,101,96,112,8,132,179,147,80,202,61,23,231,51,166,50, - 8,78,46,152,97,129,19,152,10,65,144,11,73,117,194,216,232,40,131,195,67,248,126,224,240,159,48,196,90,216,191,255, - 8,86,75,134,135,187,48,196,120,120,40,27,184,215,232,105,194,246,62,60,47,71,90,47,51,59,121,138,70,45,97,199, - 246,221,28,63,54,202,190,61,71,169,206,59,182,116,154,166,212,203,243,148,242,10,27,25,6,122,122,40,21,139,200,64, - 129,74,209,113,66,79,95,39,171,86,175,224,115,159,189,131,123,239,254,38,231,172,63,151,174,174,18,213,202,44,131,67, - 75,216,187,247,0,158,167,241,130,132,52,54,20,115,221,244,247,119,225,231,19,198,167,78,113,228,240,40,163,99,115,212, - 106,154,82,123,39,57,63,196,214,34,230,39,103,152,175,84,233,236,40,33,209,120,153,191,182,219,248,25,60,101,240,173, - 1,5,49,17,49,113,43,93,85,10,141,18,174,75,77,211,24,41,161,173,84,164,183,183,155,174,206,118,210,36,201,116, - 95,114,193,161,17,50,108,48,91,193,227,54,163,10,133,146,178,21,61,237,198,68,167,217,50,34,3,168,165,200,70,173, - 108,89,209,106,172,79,143,153,118,133,200,129,230,82,40,100,214,237,168,236,239,74,122,40,169,50,204,73,128,72,51,135, - 2,145,25,215,137,22,93,66,102,22,33,113,163,74,177,144,99,221,11,46,147,225,181,151,183,237,139,107,75,226,61,135, - 134,59,45,189,30,132,17,164,101,79,69,126,46,72,87,87,26,102,122,178,204,236,112,15,86,10,34,99,8,172,165,106, - 29,65,245,229,63,241,243,63,216,2,52,166,83,118,102,23,247,36,208,126,188,76,238,206,67,188,225,222,195,236,220,41, - 40,141,119,65,94,49,88,158,102,197,244,24,135,126,136,5,104,67,86,120,78,2,151,128,151,64,123,2,43,115,112,137, - 132,155,107,112,235,168,20,215,153,27,174,89,119,193,223,253,69,207,101,191,251,214,252,208,234,213,194,166,113,203,50,162, - 57,199,187,109,146,104,193,170,34,235,40,76,198,217,240,154,35,142,196,89,74,152,6,113,163,76,220,168,33,133,192,15, - 243,72,229,99,146,152,185,233,9,162,90,5,97,82,140,118,65,115,113,154,34,45,46,19,94,73,70,199,230,249,208,71, - 254,157,36,117,93,68,154,26,210,56,102,227,198,13,36,73,194,220,220,92,166,160,150,45,196,105,96,104,136,225,37,195, - 173,77,138,88,36,136,212,214,224,121,30,94,118,135,116,44,95,71,114,84,153,131,98,189,81,103,122,106,138,129,129,193, - 108,125,235,188,127,218,218,59,177,214,227,240,161,19,84,171,101,86,172,90,138,78,12,74,248,72,101,192,131,124,251,48, - 158,42,18,85,167,137,27,117,254,230,255,188,147,201,169,83,12,14,247,80,43,215,153,155,158,228,196,241,221,236,218,177, - 139,137,137,73,150,45,31,33,213,41,97,40,8,60,223,17,0,173,67,231,140,142,200,229,60,182,92,180,133,35,135,143, - 240,165,47,222,65,190,208,198,224,96,15,194,54,200,229,122,216,182,237,73,86,172,26,68,39,9,214,72,18,211,160,88, - 240,24,234,233,163,187,179,11,107,53,71,78,28,100,239,129,157,104,19,145,247,3,146,56,101,122,126,150,206,142,130,27, - 19,173,117,219,46,43,16,190,202,64,122,72,172,192,88,31,172,135,20,22,107,98,140,9,176,54,196,52,77,245,173,117, - 198,111,153,20,36,73,19,140,209,100,203,242,86,209,144,139,198,34,145,37,158,52,61,168,149,116,93,167,20,77,157,150, - 69,121,94,203,199,89,8,199,106,106,222,48,220,8,230,131,53,25,21,99,209,184,101,221,54,78,54,59,46,139,35,58, - 54,237,177,141,197,247,252,12,163,84,25,83,218,117,106,142,24,155,153,193,42,247,164,141,53,164,141,152,161,129,62,214, - 222,112,173,55,187,102,121,223,190,125,251,151,250,211,229,145,18,116,91,99,101,155,239,55,172,49,245,168,30,235,246,241, - 89,202,147,243,92,121,98,154,59,78,206,240,115,39,103,88,118,114,134,77,191,249,59,63,128,17,236,91,60,252,172,184, - 236,29,173,131,158,228,226,245,43,137,236,217,55,79,5,96,89,86,144,158,227,9,145,41,160,221,253,124,239,167,160,211, - 194,18,13,235,125,56,127,10,46,60,226,123,235,195,235,175,237,191,240,87,126,62,127,238,141,215,202,48,12,177,105,140, - 142,235,25,203,212,158,150,180,41,165,2,19,103,231,218,57,20,54,205,38,69,179,213,198,96,211,24,147,212,72,163,138, - 107,171,189,16,47,95,34,149,57,60,19,83,157,155,165,58,95,70,24,157,141,102,218,109,169,210,166,5,171,32,244,11, - 60,245,212,195,76,77,207,160,188,144,212,52,28,5,223,88,114,185,28,214,66,169,216,70,24,134,173,118,61,8,67,226, - 40,33,110,36,142,222,47,100,118,103,204,146,47,140,88,72,121,200,116,67,198,51,196,73,130,242,90,217,20,244,246,244, - 44,240,75,178,21,176,214,41,74,9,122,123,135,120,234,169,253,168,32,224,133,87,93,76,117,126,194,129,233,132,120,66, - 96,26,53,66,36,183,221,241,21,250,123,114,188,254,199,94,73,154,70,136,53,110,75,103,116,157,19,199,39,57,116,236, - 20,245,40,69,121,30,154,58,164,26,79,231,28,48,171,4,136,0,173,45,82,214,120,227,155,95,194,19,79,236,228,206, - 47,221,201,241,99,199,120,193,213,151,177,254,220,45,60,112,191,230,248,145,41,134,6,122,137,117,140,23,186,142,207,75, - 99,58,218,36,29,237,221,12,175,232,160,161,83,230,230,170,108,219,181,155,217,233,121,82,93,103,229,202,129,204,195,56, - 243,104,150,62,130,16,85,112,145,53,182,150,162,210,4,207,52,0,67,148,122,238,70,35,82,20,34,19,238,186,68,82, - 99,156,83,163,144,153,53,171,36,27,129,132,235,60,180,3,124,129,214,185,114,203,129,102,188,82,214,233,224,196,170,22, - 78,147,74,180,70,173,166,45,73,22,163,172,252,108,3,37,23,162,119,50,115,163,172,163,163,21,71,100,172,93,228,104, - 32,90,9,25,206,184,126,65,38,35,51,246,126,115,175,105,5,212,107,117,132,240,184,244,214,23,137,213,87,94,214,247, - 240,251,62,118,229,248,251,63,189,124,117,181,177,170,163,214,184,39,129,251,47,132,3,59,231,107,181,234,124,205,46,113, - 114,37,214,3,179,207,229,26,254,185,126,212,129,45,192,255,206,10,197,115,253,56,4,28,6,127,47,140,0,151,249,112, - 249,20,156,183,211,87,107,210,27,175,27,188,234,127,252,66,112,249,139,110,32,231,123,24,93,67,235,90,70,18,92,164, - 79,60,51,241,160,229,18,191,144,224,233,128,66,199,227,48,81,133,56,170,101,197,37,193,15,11,168,176,128,80,62,218, - 122,212,202,83,212,102,167,145,214,162,211,20,147,17,204,146,40,118,73,150,190,203,137,210,90,241,232,227,219,72,98,77, - 16,122,104,60,164,108,160,132,79,28,167,132,97,136,181,150,40,138,92,8,97,38,32,77,146,36,139,219,1,109,221,22, - 38,77,93,145,243,148,202,182,52,11,236,89,4,156,56,126,2,207,247,233,31,26,0,11,61,189,189,45,127,161,133,196, - 5,129,84,146,36,53,12,141,172,225,209,71,118,179,100,112,136,53,171,123,73,162,42,194,72,68,90,3,155,176,111,247, - 110,234,243,243,188,225,13,47,162,94,157,65,144,67,83,201,216,185,57,134,87,140,48,180,124,136,36,169,64,154,3,36, - 158,116,121,33,90,104,231,25,40,66,23,29,100,83,26,81,149,139,46,218,196,154,213,171,184,227,75,95,229,95,255,245, - 189,92,180,101,23,107,86,159,203,158,29,219,25,236,27,6,17,115,226,228,60,163,51,101,218,58,67,218,243,237,116,149, - 138,180,151,138,4,34,33,239,215,25,238,210,76,79,205,80,141,34,210,52,6,225,186,8,41,221,152,114,114,116,156,79, - 127,230,118,110,121,237,107,57,127,195,16,186,92,37,170,186,124,52,165,12,130,26,70,72,132,8,50,198,53,248,74,144, - 26,237,28,2,172,113,221,135,176,173,209,215,100,95,211,90,59,135,69,156,48,24,32,77,12,94,224,57,6,181,21,40, - 229,116,120,58,43,140,142,62,101,23,34,118,140,105,221,240,36,194,17,21,155,140,104,235,70,54,151,31,183,128,31,25, - 187,40,245,3,131,54,73,214,253,56,125,153,151,101,192,11,156,31,146,64,57,83,53,33,50,61,95,147,34,144,82,155, - 159,165,61,23,240,162,223,249,101,127,255,77,55,173,120,234,79,255,166,123,217,99,79,13,116,67,127,29,238,91,3,79, - 143,192,84,29,210,31,8,15,232,7,241,240,128,227,192,19,56,215,181,231,74,102,150,41,119,69,8,221,22,174,138,225, - 199,238,246,197,101,83,87,93,212,251,226,223,248,53,117,253,139,111,33,244,60,76,218,192,234,104,65,108,105,113,41,18, - 139,131,229,22,100,218,88,161,178,194,211,76,182,52,78,65,173,35,162,242,28,166,81,113,216,143,159,71,228,219,32,44, - 97,132,135,50,160,27,101,202,83,167,28,215,71,39,217,29,70,56,47,31,41,145,194,195,24,167,171,154,158,169,179,227, - 233,189,248,185,208,17,5,147,20,129,197,247,20,133,124,17,173,83,188,76,94,209,244,239,177,205,162,150,69,242,72,41, - 241,60,143,70,189,209,98,222,106,227,86,193,173,13,77,150,47,222,136,234,244,233,94,4,206,200,94,107,221,42,64,158, - 231,161,124,223,69,189,56,110,49,131,35,203,185,253,43,95,231,205,111,120,9,61,29,69,44,9,73,109,26,99,12,79, - 62,177,141,205,155,55,146,36,77,95,194,8,95,228,92,241,147,130,122,162,241,101,72,177,80,36,170,215,81,162,136,69, - 160,213,52,158,103,65,75,140,141,81,184,149,184,53,146,168,214,160,152,151,188,238,199,110,229,208,161,81,190,252,149,175, - 115,247,93,15,18,122,138,11,183,172,162,171,167,200,71,63,248,97,187,245,51,95,73,214,244,150,76,111,88,50,229,190, - 222,176,184,126,141,58,247,210,243,185,240,130,117,12,245,20,24,26,30,160,222,112,91,31,33,36,202,83,153,154,220,210, - 222,86,98,207,206,221,236,255,242,111,38,151,222,112,149,186,241,77,175,147,203,70,122,168,85,230,193,72,148,113,26,183, - 200,102,242,153,76,49,239,216,201,105,54,138,201,214,104,212,196,120,76,162,209,166,105,117,226,198,42,173,93,103,105,180, - 113,239,169,44,245,212,117,56,246,180,104,103,215,58,45,176,233,155,93,145,75,69,37,115,175,116,203,4,169,156,59,163, - 181,26,147,69,48,139,204,123,201,104,235,54,182,210,69,55,233,108,116,84,202,91,40,106,198,56,220,72,169,140,63,229, - 192,109,149,17,34,211,52,193,206,204,112,206,133,107,89,254,137,119,182,63,242,79,31,184,236,224,59,63,208,179,162,17, - 47,1,238,11,225,225,126,56,122,171,11,167,108,93,207,63,20,12,168,55,27,123,150,3,221,192,191,2,61,197,14,46, - 237,29,33,18,226,25,24,16,192,41,160,19,23,228,183,18,231,177,211,200,100,16,223,207,71,195,49,153,101,27,44,53, - 112,235,126,120,113,254,247,126,123,240,173,239,123,167,60,103,195,58,72,106,24,19,211,116,201,19,50,19,141,46,10,150, - 91,28,24,215,76,62,48,25,2,36,5,72,171,177,105,132,169,149,137,42,179,68,213,50,146,132,32,8,81,249,118,200, - 119,160,113,6,240,202,104,170,83,99,36,213,10,214,56,51,47,164,92,224,142,180,230,118,67,24,150,216,246,212,65,62, - 119,251,151,209,8,226,212,117,50,82,24,148,244,24,28,28,162,90,173,146,36,73,166,94,135,52,141,105,111,47,81,106, - 239,96,112,112,8,47,195,17,140,214,204,77,207,16,6,65,203,106,85,52,59,59,107,241,149,211,143,149,43,101,186,187, - 187,168,84,202,140,143,143,83,42,149,220,27,46,73,48,64,172,83,154,214,23,82,57,142,75,163,30,115,96,223,97,46, - 187,228,18,226,164,138,16,154,3,123,199,248,240,135,190,192,181,215,189,16,223,115,223,175,132,139,148,110,254,222,32,200, - 243,192,3,223,228,228,196,52,203,55,174,198,16,97,76,13,79,88,20,37,192,199,11,156,53,171,181,26,37,125,172,17, - 238,98,53,150,246,206,18,151,92,118,46,43,87,13,211,168,205,179,122,213,114,188,98,158,169,39,118,233,155,31,223,62, - 126,109,165,177,115,253,220,252,211,203,79,142,77,136,237,79,199,251,238,190,87,124,253,129,111,122,135,15,159,82,34,223, - 70,190,187,141,192,47,96,82,71,53,182,56,147,181,158,222,62,214,12,173,48,171,62,250,133,164,99,219,46,238,186,239, - 126,83,238,108,147,203,54,110,20,18,141,212,25,195,93,57,156,78,96,178,205,149,204,54,84,11,162,204,214,184,147,145, - 244,154,197,164,89,128,90,235,115,165,144,202,59,205,92,77,74,47,219,106,57,224,218,102,226,81,129,43,46,82,218,108, - 11,237,181,164,46,94,107,228,118,62,220,82,101,110,147,25,77,180,233,229,228,249,62,65,224,103,108,124,215,121,57,44, - 203,100,210,25,215,77,53,77,236,90,64,186,84,25,171,27,164,53,52,226,10,202,19,172,186,241,133,42,58,127,67,223, - 222,71,30,29,41,205,213,122,67,80,101,152,223,12,101,1,73,4,44,125,219,219,158,191,5,104,60,251,119,219,128,23, - 3,251,129,92,86,68,244,247,241,145,56,182,131,232,114,78,132,235,36,172,46,231,219,59,123,175,186,74,245,118,117,183, - 14,238,66,116,174,204,76,157,108,139,7,198,162,216,149,197,198,222,2,11,38,193,52,230,73,107,243,196,245,42,58,137, - 241,124,69,144,43,161,114,29,200,92,59,86,6,174,179,209,154,168,60,77,52,63,135,53,41,137,78,91,119,134,36,137, - 51,31,95,137,18,78,45,237,7,37,62,253,153,47,179,99,247,94,132,39,73,83,227,46,62,157,98,181,165,183,183,159, - 32,240,93,17,3,226,36,194,247,61,148,39,201,23,139,12,12,12,18,134,1,74,10,226,70,131,153,217,25,74,109,165, - 204,145,207,1,210,2,119,65,75,41,169,215,234,76,79,79,211,209,222,65,20,69,84,170,21,242,249,60,73,146,32,148, - 114,14,50,217,103,173,181,83,170,251,146,131,7,142,114,244,240,9,70,134,251,24,25,233,167,222,136,249,236,109,247,242, - 133,219,239,181,227,147,147,246,170,107,46,22,70,39,89,132,112,132,16,62,18,69,41,95,96,106,42,226,111,255,224,239, - 141,61,62,97,251,87,111,20,29,221,157,40,13,54,13,156,207,178,202,116,75,77,2,103,6,176,198,113,138,242,5,73, - 18,209,222,86,224,188,205,235,81,50,65,134,30,39,31,221,101,58,30,223,177,43,116,180,175,47,21,224,169,101,112,112, - 147,182,199,214,77,206,141,182,109,219,53,123,242,142,187,204,211,79,110,15,170,94,222,107,95,177,78,180,183,119,96,83, - 221,186,80,251,134,134,197,209,71,182,177,98,116,44,218,56,95,157,62,118,239,55,27,219,43,149,220,240,69,151,200,246, - 146,71,156,206,131,240,90,248,152,204,58,3,107,51,183,1,227,120,60,77,140,167,233,119,36,165,204,162,178,29,251,76, - 41,185,16,13,155,45,10,164,204,198,160,236,66,111,74,6,29,107,221,165,152,98,44,86,184,116,18,229,57,221,97,115, - 141,191,248,103,54,109,81,140,209,25,55,75,162,148,199,212,212,12,199,142,31,39,73,52,93,93,189,20,10,237,88,235, - 225,41,191,165,49,107,254,91,23,86,96,22,109,218,50,66,43,26,169,242,206,21,179,49,199,242,13,171,233,186,233,166, - 210,131,79,63,61,28,30,31,239,233,0,149,56,190,208,124,47,196,67,111,123,219,243,119,4,107,221,9,50,240,250,1, - 96,45,240,170,53,43,145,97,232,248,41,223,75,125,148,146,122,185,98,211,19,39,79,73,184,175,23,66,190,124,199,245, - 255,120,205,182,115,47,253,139,63,41,189,241,205,63,142,34,70,39,213,150,8,112,97,173,105,221,217,207,236,11,108,54, - 79,59,115,246,24,29,85,208,245,26,186,81,93,24,159,188,128,48,95,64,132,29,224,231,29,144,104,65,144,146,68,21, - 170,243,115,45,221,148,144,2,171,29,17,77,103,134,237,205,45,135,20,130,70,148,178,119,239,33,151,78,33,83,144,10, - 147,56,64,51,142,99,170,149,50,29,157,157,24,107,168,204,149,209,58,37,232,238,106,49,97,141,209,132,97,128,213,134, - 122,189,230,180,77,74,182,212,211,58,251,221,178,201,164,21,144,36,9,149,74,133,122,189,78,177,88,92,192,30,22,105, - 102,141,78,177,169,135,111,37,229,104,134,35,39,142,114,238,218,77,220,123,223,253,172,95,183,132,253,123,70,57,116,100, - 154,141,107,86,26,241,137,207,148,111,31,110,235,120,249,79,189,74,216,250,52,146,46,172,6,45,171,36,54,101,100,100, - 41,175,8,84,188,241,35,95,168,238,253,242,131,118,246,103,222,216,177,226,199,110,240,11,237,17,34,138,177,186,13,76, - 1,107,99,16,117,132,72,200,231,139,236,217,125,152,157,187,246,242,19,111,122,5,181,250,28,113,84,7,163,240,108,129, - 40,74,45,48,7,236,177,240,144,15,186,14,29,30,116,23,160,167,4,35,75,27,233,186,232,225,167,55,158,124,108,247, - 198,219,207,253,226,138,252,141,47,40,92,116,227,229,172,94,210,139,213,41,65,201,67,191,248,74,255,240,227,91,103,214, - 192,225,203,82,91,63,252,193,207,45,253,244,99,59,151,109,250,213,159,204,95,126,213,5,248,141,50,73,156,100,9,166, - 54,99,60,123,25,197,126,193,186,214,247,61,148,148,36,81,228,248,62,86,144,232,20,79,153,150,32,217,225,52,167,167, - 184,182,44,245,237,98,91,219,76,47,47,133,147,50,89,73,20,167,25,111,200,203,206,143,110,42,104,157,5,136,92,196, - 1,178,78,30,210,209,217,133,69,242,205,111,62,198,39,15,221,206,154,213,235,184,224,130,243,105,235,110,39,95,244,40, - 20,10,248,210,221,112,146,216,121,133,59,174,216,130,127,139,38,64,89,75,206,226,88,231,147,83,12,15,247,240,186,143, - 189,179,248,201,63,252,203,203,226,15,124,161,125,9,20,186,193,36,176,29,168,63,247,5,200,146,9,13,5,207,85,148, - 152,201,112,160,49,224,43,253,125,204,108,62,151,174,158,30,12,180,192,211,239,92,233,26,144,236,217,107,87,125,234,179, - 243,231,192,19,85,152,235,133,137,87,157,56,57,245,165,159,253,239,151,60,246,181,123,251,127,230,183,127,157,243,206,57, - 7,72,177,182,138,209,73,214,146,11,240,146,108,26,203,185,243,29,213,137,230,231,169,215,103,93,38,148,21,110,87,32, - 12,129,231,225,23,125,100,62,135,48,29,238,46,164,18,231,110,152,132,232,234,44,38,213,104,75,118,23,116,109,182,214, - 137,203,231,82,77,63,22,141,31,230,217,179,239,48,7,15,31,192,147,57,103,195,160,117,6,110,250,104,171,105,36,41, - 189,65,72,17,231,37,236,251,33,190,23,18,4,5,164,80,212,171,53,68,175,3,64,157,209,216,194,69,161,117,38,139, - 200,18,19,92,70,188,3,45,171,149,10,213,122,149,238,30,103,47,234,186,51,55,22,26,1,158,239,17,39,154,36,181, - 28,63,58,74,95,119,23,202,179,76,207,215,185,239,193,157,204,205,84,233,94,210,77,116,106,55,47,129,220,248,59,62, - 24,223,221,217,21,220,242,186,91,69,50,119,10,148,135,79,9,105,37,29,29,17,43,194,180,214,3,79,119,79,78,29, - 159,249,171,127,24,217,122,207,215,206,89,250,43,111,236,93,118,233,133,120,34,135,174,213,92,232,30,10,67,74,148,148, - 89,189,98,132,191,248,155,247,50,173,125,126,230,45,47,67,86,29,238,148,164,30,179,115,53,177,44,75,203,243,33,250, - 123,168,253,24,204,215,225,100,59,120,62,20,2,231,203,189,114,185,54,23,13,111,219,121,201,161,109,59,55,125,249,179, - 159,95,90,184,229,134,252,245,175,125,57,27,58,218,88,127,227,53,60,254,206,15,229,245,116,57,74,225,209,165,240,68, - 207,211,251,207,219,241,43,127,188,233,99,111,120,197,240,205,191,240,122,213,91,8,73,234,21,148,13,157,75,161,15,202, - 198,32,36,146,16,223,151,236,216,190,23,223,111,99,243,133,231,17,37,51,152,40,65,105,133,39,116,230,9,21,128,20, - 232,36,109,185,73,186,162,147,96,154,182,45,74,181,240,31,33,157,231,135,77,45,86,57,5,190,78,242,116,246,14,80, - 77,43,40,147,34,18,75,98,157,24,217,36,206,176,77,91,183,1,13,124,144,194,167,191,119,128,87,189,252,165,236,220, - 181,155,183,191,227,159,249,219,183,255,189,61,167,123,64,247,118,180,201,225,85,171,200,47,25,22,157,157,29,98,253,198, - 245,116,46,233,161,20,122,4,197,144,124,144,119,72,145,1,235,187,27,87,65,135,40,235,209,16,208,217,83,228,13,239, - 248,43,245,129,246,190,115,27,239,254,104,178,58,110,28,10,225,72,179,0,137,231,16,227,117,107,232,36,114,219,158,231, - 120,125,46,129,39,30,124,132,244,193,71,184,165,179,147,183,175,90,197,202,222,94,82,192,51,250,59,250,57,218,83,20, - 199,79,177,6,236,131,80,94,15,187,125,40,123,48,254,234,56,62,245,228,7,62,116,229,223,125,249,171,203,250,94,245, - 178,252,117,175,125,37,215,93,117,57,249,176,132,181,115,78,179,147,6,88,34,226,122,149,202,220,20,245,202,73,108,195, - 93,176,94,16,226,169,28,72,139,23,128,231,229,240,189,65,87,144,189,6,72,141,16,121,182,62,190,27,79,39,172,94, - 94,114,153,88,102,33,165,50,77,210,204,103,199,3,163,157,225,148,181,72,229,243,212,246,167,169,215,27,72,175,13,171, - 117,102,239,96,49,110,209,66,189,81,71,72,153,97,64,30,185,92,142,32,8,73,226,196,197,23,27,67,26,39,196,73, - 66,20,69,132,97,216,178,90,245,148,215,242,126,110,102,72,181,214,237,88,226,56,162,80,200,19,199,206,211,198,233,151, - 60,71,48,139,99,132,176,196,137,165,90,174,51,50,52,76,20,53,40,181,117,113,223,55,30,165,222,104,112,222,249,231, - 50,174,149,72,160,182,57,181,243,143,253,245,187,218,30,235,42,117,95,114,203,229,34,173,52,32,81,24,25,227,21,75, - 200,124,71,156,50,179,195,74,238,106,183,116,151,30,217,121,249,232,127,251,189,45,135,174,190,116,101,215,155,94,221,177, - 250,178,245,180,11,73,28,91,82,91,192,143,35,6,7,218,184,238,234,139,237,29,127,255,47,186,61,158,151,175,253,201, - 215,72,223,143,105,152,148,106,181,134,128,192,56,83,8,249,112,198,1,219,3,122,35,232,21,16,245,194,220,78,56,209, - 7,251,125,216,190,14,182,172,62,56,122,209,158,119,126,120,237,55,110,255,218,240,137,87,190,164,125,203,207,254,184,232, - 127,221,43,75,179,239,254,80,169,13,142,196,240,100,14,30,187,34,73,175,222,247,161,219,94,240,222,39,182,158,115,245, - 111,252,82,120,229,69,235,208,209,156,179,242,208,30,66,120,248,138,140,119,229,156,12,254,252,143,255,214,252,196,229,87, - 214,174,121,229,11,67,127,197,144,111,83,13,73,197,157,79,98,132,245,91,145,211,218,58,111,33,79,132,46,11,77,8, - 140,145,11,221,144,112,238,142,214,6,36,86,211,222,222,197,195,95,127,154,233,250,94,70,54,44,165,171,179,68,87,80, - 164,80,242,240,177,232,68,99,116,66,170,147,44,214,59,193,10,227,168,4,82,113,225,249,235,249,231,119,253,61,31,248, - 192,199,236,204,59,62,208,120,113,66,88,127,124,167,152,130,186,133,153,3,158,31,197,189,237,121,57,212,87,202,15,244, - 250,221,93,189,150,124,65,106,15,225,231,124,26,113,34,210,68,136,40,182,162,166,181,80,57,161,148,178,178,160,125,142, - 118,150,250,151,159,106,116,10,199,200,193,211,139,52,42,223,119,167,34,21,65,146,176,121,231,3,168,36,250,129,140,100, - 194,97,56,44,153,157,101,199,19,79,224,175,92,201,165,235,215,49,154,47,226,39,201,183,237,186,140,231,225,123,62,5, - 224,239,129,235,161,241,135,112,100,43,84,27,48,113,17,28,222,52,54,118,241,142,127,254,215,141,31,253,200,39,134,63, - 245,194,23,22,110,250,137,31,231,250,155,46,101,160,171,155,164,82,229,212,177,253,68,245,58,58,173,97,68,10,66,226, - 217,60,8,65,24,8,148,50,120,42,36,8,123,17,170,4,54,198,120,21,148,232,228,201,39,182,242,207,127,247,65,254, - 247,31,253,12,86,85,80,34,135,162,66,108,155,137,74,11,138,116,99,28,111,68,10,73,146,194,182,167,158,206,146,33, - 88,72,86,0,140,73,65,26,146,164,129,53,9,81,92,199,247,21,160,49,54,205,70,170,148,122,189,158,229,77,185,181, - 124,144,249,251,52,199,5,167,144,23,45,207,104,128,192,119,49,47,190,231,103,29,83,102,33,225,172,11,221,198,204,243, - 65,107,142,30,58,72,169,173,216,2,84,133,16,116,116,180,211,209,217,65,26,43,84,216,41,82,24,53,240,196,249,213, - 70,238,208,31,252,237,69,79,21,255,96,213,249,215,93,33,146,169,57,18,157,71,22,3,212,208,128,210,219,15,207,43, - 196,30,35,152,53,214,238,29,210,118,71,116,239,195,23,159,120,232,209,243,199,206,95,183,180,235,229,47,111,95,253,162, - 43,68,79,41,79,82,241,41,91,201,171,111,125,161,221,248,190,79,234,218,63,124,216,124,106,223,17,239,210,95,253,111, - 114,229,186,62,130,66,160,44,120,10,100,10,66,122,138,255,91,12,185,38,78,145,245,152,62,87,140,204,19,80,253,125, - 56,180,31,78,85,97,175,128,39,206,133,245,201,209,209,115,103,254,225,223,206,125,236,190,251,87,207,14,247,23,151,64, - 93,193,116,10,251,82,56,96,224,248,42,24,239,222,121,160,250,185,95,255,223,23,236,251,169,215,151,222,240,166,91,241, - 61,75,28,37,120,228,144,120,136,32,161,30,85,217,176,121,35,231,93,112,142,173,124,240,227,250,196,231,190,24,249,55, - 191,48,237,252,137,87,230,58,214,12,8,17,105,116,212,128,36,1,153,102,17,105,46,225,213,26,144,66,97,132,108,197, - 221,139,204,122,54,53,26,105,37,82,248,8,242,12,140,172,225,61,63,253,139,201,13,105,61,153,238,235,150,141,174,110, - 149,95,187,214,27,220,184,94,244,175,24,97,201,146,126,58,219,114,132,129,165,16,148,48,217,150,20,43,136,26,41,190, - 87,224,23,126,225,151,229,189,203,55,22,239,251,179,191,49,151,159,154,176,23,65,57,130,167,72,147,29,140,77,233,116, - 108,170,207,64,91,234,80,133,86,146,116,152,33,88,6,2,235,188,208,187,50,71,160,74,30,182,106,41,247,42,225,188, - 236,213,139,151,174,19,205,20,200,239,235,67,41,66,157,226,237,124,128,115,230,38,233,200,212,228,223,207,22,172,23,120, - 20,184,52,91,199,55,181,90,2,56,31,248,48,176,105,118,150,63,59,118,156,253,198,80,238,237,117,140,228,111,225,3, - 98,165,196,171,84,216,116,242,36,95,7,206,3,86,128,249,18,212,150,194,120,10,71,20,28,29,129,83,23,71,81,165, - 125,207,30,253,224,231,110,247,63,249,149,123,195,121,191,32,214,174,94,74,163,122,16,17,73,156,223,118,128,17,78,135, - 19,248,142,206,46,101,72,174,212,133,42,118,160,101,10,94,29,37,251,184,247,158,199,245,47,191,241,231,163,11,182,108, - 244,94,250,170,43,132,49,57,68,90,192,36,51,36,38,33,73,13,198,56,98,159,109,234,115,16,72,79,50,51,23,241, - 177,143,127,142,249,114,29,169,194,150,126,168,169,138,22,210,97,11,195,35,195,84,202,101,146,36,33,78,92,183,146,203, - 231,40,20,74,228,139,37,250,250,250,91,152,78,46,151,35,151,203,157,230,78,208,36,162,57,16,186,70,163,222,192,90, - 71,74,108,235,232,68,8,209,50,44,203,96,119,60,47,192,232,148,167,182,61,201,146,165,75,90,155,65,169,20,129,23, - 226,41,143,48,204,49,55,53,46,250,247,238,58,220,109,184,67,195,99,157,81,194,145,7,30,239,143,54,109,236,24,94, - 61,76,18,205,33,61,143,234,227,59,35,182,239,123,82,89,30,46,88,142,90,24,175,101,231,165,215,216,147,157,39,38, - 231,167,238,126,64,60,177,125,87,219,76,247,176,223,183,118,25,129,151,208,222,214,43,78,126,253,97,214,142,77,84,139, - 251,143,206,222,245,245,251,189,249,225,165,126,189,28,137,182,199,183,141,118,194,55,107,176,111,255,210,222,248,134,151,92, - 140,89,210,203,138,147,211,244,68,9,51,64,21,208,171,151,216,125,133,48,233,105,196,179,210,152,227,53,56,32,224,64, - 9,78,20,199,39,199,242,251,143,28,42,193,99,10,30,213,112,34,7,101,13,211,26,38,11,80,63,55,74,228,177,71, - 159,108,187,251,192,201,226,208,5,231,139,190,238,18,58,78,193,170,44,119,76,18,248,121,180,240,101,253,174,251,88,87, - 139,166,234,59,247,28,63,126,215,125,241,201,169,185,92,95,111,191,144,253,93,210,10,139,48,54,211,214,57,50,163,208, - 110,60,246,164,135,20,94,198,168,118,157,144,242,220,6,214,74,103,96,56,48,178,18,253,196,86,125,209,238,253,51,107, - 103,202,187,87,158,60,245,116,251,142,93,19,115,247,220,95,59,246,149,187,211,167,190,118,31,15,60,252,184,183,239,216, - 184,56,49,17,83,77,61,252,124,158,66,123,59,126,222,177,216,173,110,176,225,220,13,162,235,186,203,229,103,246,238,146, - 246,196,68,60,12,71,19,120,60,133,135,44,60,98,224,9,31,30,43,192,163,1,60,18,102,31,121,120,196,135,199,61, - 216,25,194,174,188,235,22,191,33,224,94,223,218,237,135,172,157,217,244,182,183,25,245,146,21,231,56,127,145,239,241,67, - 72,1,65,192,188,73,97,251,253,12,206,79,209,151,97,54,63,140,2,180,18,120,181,214,148,38,39,41,38,9,7,187, - 58,91,6,234,223,174,0,125,3,216,12,228,129,29,96,127,22,226,131,48,171,225,164,128,131,22,14,247,192,177,243,77, - 58,179,124,116,212,124,253,11,119,228,239,124,234,80,126,217,69,235,24,236,107,39,137,28,211,85,18,226,7,41,82,20, - 193,20,201,183,43,194,206,14,180,42,146,98,240,85,192,189,119,61,200,87,222,244,179,213,181,227,39,167,110,253,223,191, - 218,182,124,245,106,169,100,55,245,250,52,81,189,74,28,107,180,112,185,230,82,169,69,32,166,196,247,124,246,29,28,227, - 246,59,238,67,27,151,81,165,141,201,120,59,182,101,222,174,60,197,64,127,63,73,146,16,134,97,139,88,88,200,231,105, - 107,239,192,243,3,6,7,7,169,84,42,204,205,205,209,222,222,222,250,190,166,61,135,148,110,11,150,38,9,245,122,157, - 90,173,70,28,199,88,225,128,74,99,140,219,130,9,129,54,218,89,148,134,1,7,15,236,227,228,137,227,12,15,15,83, - 40,20,1,137,209,6,147,26,124,207,35,159,11,153,26,61,70,207,238,221,227,253,134,251,45,60,2,204,245,214,27,109, - 187,190,241,80,95,99,243,154,210,200,234,97,172,81,212,183,29,142,147,199,182,61,225,195,19,59,96,186,0,105,23,148, - 171,48,30,9,14,43,193,145,94,152,30,56,62,158,238,190,243,238,226,131,251,15,149,114,131,35,98,120,195,57,76,157, - 154,162,246,224,35,199,122,96,219,218,249,250,232,182,187,31,236,248,242,216,104,225,220,70,116,178,95,235,7,124,216,183, - 175,171,20,7,107,6,201,21,67,70,67,159,205,135,79,49,3,204,0,135,54,44,231,67,29,121,57,210,209,97,143,143, - 79,197,1,148,115,112,202,194,97,96,79,0,79,120,240,100,93,136,163,58,80,245,131,66,216,47,26,155,92,15,179,21, - 24,19,48,177,222,82,111,63,116,212,191,247,193,199,59,146,145,149,254,202,117,43,193,68,24,237,52,88,88,75,123,87, - 7,163,247,127,179,209,55,53,191,61,128,123,219,106,141,253,114,235,174,74,245,174,175,219,164,26,133,114,100,73,40,59, - 219,178,248,69,7,40,123,74,183,54,175,205,121,64,168,166,215,143,51,169,55,194,45,37,242,249,2,39,103,102,100,124, - 223,67,39,74,136,175,74,248,98,9,158,88,1,79,175,77,210,189,235,102,203,199,87,30,25,157,146,143,110,175,142,223, - 253,141,248,208,61,247,153,167,190,122,143,61,240,228,14,230,199,103,68,106,60,225,229,138,104,1,75,150,143,112,201,43, - 95,204,214,208,43,28,222,177,163,115,56,210,70,194,9,3,79,3,251,103,225,216,1,56,49,14,39,230,225,196,180,251, - 56,94,132,99,2,14,249,176,199,135,157,13,120,58,129,35,67,48,247,215,160,223,248,182,183,225,9,249,125,64,197,82, - 210,240,2,134,70,15,145,28,218,201,88,117,158,149,63,34,211,176,26,112,245,161,67,220,118,242,36,226,242,203,88,210, - 209,65,242,221,2,212,192,0,104,237,214,132,149,125,48,154,194,118,3,143,117,193,133,111,49,233,165,7,238,252,220,249, - 31,219,241,224,234,235,255,248,55,11,215,94,117,1,113,89,59,169,187,9,176,214,195,47,6,228,218,219,209,170,13,132, - 36,39,75,124,225,75,119,114,255,79,255,82,114,235,248,132,255,200,138,165,253,43,55,111,86,66,150,72,210,136,90,99, - 14,99,5,214,74,200,172,54,155,160,176,187,187,73,60,21,114,114,116,130,212,56,150,181,209,169,115,198,75,77,166,60, - 119,164,182,52,77,169,214,106,52,50,15,231,92,46,68,8,168,55,26,89,102,151,243,140,158,154,158,98,110,110,142,129, - 129,129,5,155,212,108,164,211,70,163,50,207,155,52,117,164,198,106,181,130,231,251,36,113,130,206,120,63,90,107,242,249, - 60,169,209,68,81,196,83,219,183,227,73,65,165,90,161,84,106,39,8,66,26,245,26,105,154,96,140,231,112,138,92,136, - 17,228,51,130,123,213,131,71,19,40,108,158,156,11,182,255,250,159,95,227,255,253,255,238,63,247,134,23,210,144,70,130, - 75,201,121,8,196,91,193,222,13,118,9,212,102,45,117,96,178,33,196,49,15,14,92,147,166,7,199,239,184,247,138,39, - 239,121,96,237,209,87,221,218,21,172,88,45,165,146,149,78,109,190,14,204,223,92,111,28,89,115,108,236,188,46,216,149, - 194,148,5,253,226,137,57,246,221,189,29,5,36,229,6,201,162,243,159,79,13,129,48,70,9,56,1,244,129,93,14,141, - 163,48,30,193,196,90,144,135,193,204,251,210,188,125,197,32,7,106,49,155,142,79,48,15,209,52,28,233,132,57,5,199, - 151,193,161,225,67,199,175,121,236,55,254,232,162,175,253,226,79,12,190,224,167,94,169,2,79,19,55,98,132,214,116,117, - 21,232,190,228,60,191,190,247,120,84,128,29,177,146,7,75,218,12,218,153,249,205,245,127,251,216,150,185,207,127,229,156, - 220,143,191,108,73,223,107,94,150,207,181,21,33,174,97,50,224,88,217,108,3,108,29,7,72,169,192,57,88,26,231,221, - 108,132,32,169,85,24,222,114,190,216,147,15,252,161,70,50,223,64,108,75,5,147,214,216,64,64,187,133,158,60,12,110, - 132,193,77,38,237,53,19,211,131,241,196,116,87,125,247,225,82,237,243,95,27,56,224,121,67,71,6,7,11,233,178,193, - 112,186,183,35,23,172,90,233,47,61,247,60,30,127,237,107,6,30,250,208,39,94,116,101,172,27,10,198,139,48,243,105, - 136,62,212,215,205,96,123,27,7,14,30,109,221,252,127,215,65,28,81,46,107,36,174,200,232,53,197,214,240,254,253,48, - 161,133,36,108,212,8,14,63,206,227,227,71,88,251,28,225,72,223,239,163,22,69,60,241,205,135,185,229,242,203,232,250, - 30,139,144,7,12,131,57,8,213,21,80,59,8,147,9,28,154,23,114,247,10,107,47,93,118,124,226,202,135,126,227,109, - 91,202,191,242,203,3,183,254,216,11,105,164,117,148,113,166,233,165,206,78,164,215,71,66,153,128,28,159,249,216,167,120, - 232,215,126,179,114,203,196,116,53,133,98,254,130,11,242,189,67,75,49,186,76,101,126,28,27,57,5,181,54,41,70,91, - 252,64,185,13,136,118,43,82,109,44,105,170,217,127,240,176,75,193,96,193,71,88,32,72,181,65,41,71,92,75,226,20, - 107,156,245,66,18,167,248,126,64,177,88,36,31,58,249,130,231,121,142,207,83,169,180,186,35,173,77,198,204,21,89,2, - 170,201,220,236,154,210,15,141,214,154,98,91,137,40,170,103,250,38,183,190,215,58,37,151,207,241,248,147,79,114,248,208, - 97,150,45,91,74,165,82,71,14,73,192,9,92,141,78,73,211,8,131,34,150,109,52,82,81,144,216,206,216,193,242,39, - 21,124,221,3,177,121,114,142,253,191,246,167,215,242,119,165,190,153,184,33,187,93,60,149,120,11,240,242,204,175,169,238, - 220,41,237,16,212,235,214,30,30,133,153,72,136,163,157,214,238,185,161,145,108,153,253,216,231,54,77,75,217,222,5,219, - 53,108,87,176,47,129,61,171,140,89,38,92,103,187,207,135,248,162,106,196,37,7,198,91,55,175,33,224,224,34,166,188, - 56,203,242,35,155,108,116,7,232,70,246,30,241,172,68,90,129,201,58,247,127,129,244,245,48,85,133,39,187,221,181,118, - 228,170,36,57,122,236,29,31,184,242,246,3,251,55,92,249,91,191,144,31,233,233,163,81,157,69,10,205,210,27,94,16, - 158,250,212,87,250,243,113,154,151,150,195,8,177,211,90,187,35,132,39,194,83,83,23,215,254,254,253,151,237,251,210,125, - 155,251,222,242,250,129,190,235,174,240,115,93,3,136,70,13,97,83,36,22,147,166,238,153,25,157,73,187,36,224,12,225, - 172,110,48,178,106,5,187,54,172,239,74,158,220,62,4,20,123,44,7,31,2,221,11,19,75,224,112,23,132,51,144,143, - 17,5,129,237,244,160,216,14,133,18,44,85,105,122,142,62,126,124,40,61,126,220,31,0,111,30,218,27,208,115,89,46, - 223,145,211,4,13,33,86,230,172,93,86,129,29,63,37,68,237,215,63,245,46,214,94,123,13,47,125,201,143,243,197,47, - 221,115,26,141,166,150,25,252,93,189,232,152,126,207,82,140,102,247,55,170,35,186,142,236,100,213,232,17,118,192,115,182, - 114,127,46,120,67,68,17,247,126,243,97,174,187,252,50,58,59,58,90,196,188,239,5,240,14,192,182,67,180,27,78,46, - 179,102,182,140,56,26,192,209,107,103,235,149,187,255,234,237,47,188,179,144,239,187,233,213,215,17,71,51,20,114,125,248, - 133,54,12,49,129,24,224,99,239,127,55,123,126,229,183,199,95,90,105,60,29,184,147,176,118,217,11,175,42,42,124,234, - 177,38,169,205,227,153,186,179,68,85,202,217,36,32,72,18,237,232,241,64,16,228,72,146,148,39,183,62,69,35,74,240, - 61,129,177,41,24,213,98,164,57,129,161,19,192,234,212,129,195,133,66,129,48,8,72,19,195,124,92,163,119,64,58,14, - 84,163,65,173,90,35,23,132,217,136,119,198,5,39,197,105,120,16,64,18,199,36,73,12,130,76,107,102,90,65,127,179, - 179,179,220,127,255,55,72,210,148,249,185,121,226,40,198,247,67,146,36,38,142,99,226,36,194,226,145,198,101,148,138,137, - 124,169,68,172,125,235,8,9,169,239,64,233,123,37,232,181,147,51,122,247,175,252,246,213,39,7,10,225,53,80,21,160, - 119,0,247,1,31,3,126,43,3,56,243,110,148,215,255,2,211,55,88,91,85,112,60,22,98,91,27,118,77,187,49,69, - 11,199,37,236,170,194,120,23,140,213,97,123,10,166,46,101,237,27,195,189,122,133,239,157,150,95,158,19,130,227,99,83, - 20,234,17,241,183,120,47,136,51,254,44,206,120,223,231,28,152,109,39,160,254,98,56,44,97,38,129,227,35,48,154,255, - 210,3,47,186,227,196,196,69,235,127,253,87,74,87,93,184,14,157,206,227,15,245,49,223,221,217,63,56,54,57,130,49, - 185,57,24,87,80,109,131,113,33,196,254,146,181,187,114,251,14,93,89,253,253,191,188,120,124,211,186,181,226,101,47,238, - 94,243,226,27,188,222,193,110,68,92,65,103,90,178,38,107,217,136,24,35,20,34,219,156,182,21,187,105,223,114,65,169, - 241,228,246,21,121,88,90,135,253,151,64,101,22,204,16,152,149,144,252,37,84,126,222,90,49,5,199,43,32,102,92,154, - 111,41,129,135,45,116,20,192,203,131,44,66,73,66,31,141,122,95,10,131,218,109,196,70,243,136,184,108,45,203,239,126, - 16,174,125,5,27,54,110,56,173,0,125,39,55,251,239,234,130,180,22,166,106,85,198,100,76,199,98,178,220,243,236,209, - 136,34,190,254,205,135,121,225,229,151,225,117,118,226,125,7,27,178,179,233,198,196,130,67,162,189,20,170,59,176,251,231, - 161,170,133,240,175,141,211,206,47,252,237,187,175,28,216,60,84,218,114,241,58,114,94,63,34,168,33,100,59,31,124,199, - 59,25,251,173,223,61,126,83,212,248,134,134,29,22,86,207,230,139,107,87,95,122,190,80,212,209,181,50,164,150,84,7, - 88,45,209,52,220,109,86,40,84,38,85,208,169,65,169,54,118,239,61,194,201,147,167,92,168,96,22,146,103,50,55,69, - 175,233,189,108,93,56,93,189,94,199,247,61,230,203,179,228,146,156,219,194,120,30,214,172,68,24,67,212,168,97,172,118, - 235,220,38,246,211,202,102,207,248,24,89,122,130,1,231,49,29,69,206,134,213,104,116,154,102,221,86,66,24,6,60,249, - 196,99,148,231,102,41,21,243,36,105,76,35,106,100,99,90,246,243,165,159,177,101,53,185,80,226,11,105,45,90,148,64, - 252,155,235,28,244,159,194,216,46,248,134,133,198,218,153,185,67,29,149,249,110,43,217,17,26,202,87,184,84,52,74,25, - 126,88,207,126,178,6,118,3,111,133,72,193,216,46,107,167,27,176,39,20,194,171,75,17,89,109,170,239,242,189,244,173, - 198,38,161,214,141,195,64,163,187,131,111,44,25,224,65,125,58,101,67,41,201,73,33,248,229,131,39,158,181,0,125,55, - 239,153,28,240,9,208,183,194,76,55,108,77,161,218,13,241,181,219,246,218,79,253,202,111,111,25,253,221,95,45,189,230, - 213,55,83,236,21,212,134,58,58,205,216,228,50,31,250,234,112,98,24,146,97,40,111,149,226,64,155,182,147,33,28,44, - 193,246,252,206,189,151,204,236,220,123,254,163,159,248,236,170,244,69,215,247,174,127,205,139,228,218,149,61,4,113,13,83, - 49,52,82,1,94,128,210,9,74,164,104,37,17,166,74,215,85,23,4,99,239,249,208,170,53,150,115,12,60,5,84,125, - 176,126,118,179,62,226,206,129,109,128,126,218,9,181,211,155,161,113,24,102,134,64,238,2,209,6,98,0,60,1,97,234, - 146,96,58,178,17,234,212,56,182,118,29,80,124,247,135,225,143,222,10,66,127,247,13,195,119,116,96,133,196,0,115,149, - 154,243,167,201,188,75,44,207,223,71,45,138,56,255,155,15,115,217,196,4,137,82,24,241,253,149,74,15,184,0,116,55, - 140,167,214,62,0,124,249,134,137,241,39,119,254,233,59,235,185,96,53,109,61,189,88,217,205,71,255,242,159,152,252,141, - 223,60,246,130,168,113,183,134,219,45,236,139,161,48,191,102,99,199,138,181,27,193,84,80,113,29,163,45,41,22,45,42, - 24,17,103,33,115,26,99,82,164,213,40,233,168,246,123,246,29,165,92,174,226,43,233,66,246,204,226,188,115,219,18,204, - 98,33,77,83,2,223,35,151,11,240,125,137,177,41,65,224,19,6,62,2,75,163,94,39,201,212,210,14,247,113,96,119, - 83,41,45,113,98,198,32,8,9,124,31,107,13,141,70,131,184,17,145,100,192,116,212,104,224,7,62,211,211,211,60,245, - 212,54,2,223,233,146,242,249,128,56,142,136,227,40,187,176,61,60,149,209,249,133,64,6,62,210,247,91,117,206,7,113, - 151,235,50,181,128,49,11,95,71,240,193,37,154,119,74,195,253,101,152,237,7,126,26,120,109,214,253,248,139,72,107,217, - 104,68,135,139,48,140,34,152,94,109,237,169,138,54,115,13,41,210,137,149,35,252,159,229,67,220,213,81,34,1,62,219, - 221,142,106,196,200,40,125,198,71,162,159,219,119,114,0,236,3,251,110,168,247,193,222,58,220,81,144,226,246,31,47,215, - 31,158,250,139,127,152,189,235,182,187,40,118,15,209,253,194,171,75,115,176,82,192,112,55,132,99,192,161,165,195,220,38, - 68,218,6,211,35,240,84,10,183,11,120,111,63,188,103,195,161,163,159,233,123,247,251,31,249,230,27,127,105,226,115,255, - 252,49,115,232,100,3,89,232,193,107,11,65,214,145,194,195,218,34,58,205,147,214,35,86,92,184,145,227,171,151,142,36, - 112,142,129,37,101,8,206,119,16,3,53,22,34,149,197,233,98,109,0,29,67,242,147,16,255,6,68,18,170,19,48,189, - 27,78,204,57,238,220,110,11,147,135,65,231,0,101,191,143,137,229,219,147,11,21,158,209,84,230,43,46,127,92,8,254, - 163,60,186,162,136,223,125,240,33,126,126,199,14,26,158,71,34,229,247,84,54,69,182,153,59,8,108,133,164,29,142,104, - 248,106,27,124,101,237,55,183,239,251,210,255,125,39,141,134,229,206,95,255,221,200,254,238,31,61,125,121,170,191,20,195, - 103,44,60,233,9,81,152,130,165,237,55,95,87,234,236,25,164,17,107,146,52,197,88,13,162,225,140,226,61,7,24,75, - 233,10,137,182,77,27,77,143,67,135,142,208,204,55,183,100,248,79,214,13,37,73,66,146,164,45,169,72,163,81,207,100, - 68,34,35,34,6,180,181,181,99,45,52,26,13,106,149,106,150,7,238,182,93,77,75,6,33,197,130,129,89,22,84,87, - 44,21,169,215,235,206,80,107,33,34,47,243,149,150,60,244,208,131,212,170,85,4,130,192,15,72,181,161,209,168,19,69, - 81,246,124,220,129,51,198,32,172,34,159,47,34,60,217,58,250,33,112,0,248,128,251,179,46,193,244,180,101,207,148,177, - 59,13,140,190,11,226,165,89,231,211,147,73,113,78,102,255,238,91,61,20,48,213,222,70,90,40,112,220,83,226,51,253, - 221,76,251,222,247,124,145,124,175,227,123,30,120,63,240,215,208,232,130,253,210,218,47,74,33,62,241,242,114,253,75,242, - 247,255,252,208,151,254,244,29,182,227,156,243,68,226,201,162,128,124,0,42,41,20,184,125,203,38,246,158,187,156,82,33, - 180,195,16,23,224,148,132,173,53,248,130,17,226,125,67,240,111,215,78,204,222,214,255,183,239,127,228,209,31,255,31,227, - 95,123,251,187,147,137,163,167,80,165,30,76,24,144,40,67,138,65,164,138,174,66,55,118,195,186,194,60,172,148,176,172, - 13,242,191,8,172,206,54,201,143,103,29,219,183,42,12,205,73,96,30,56,1,118,214,221,48,180,1,27,60,7,174,23, - 223,242,225,123,1,113,220,224,166,237,15,242,249,193,181,212,242,37,22,242,35,254,227,60,94,114,232,48,162,82,225,223, - 55,111,102,214,247,191,43,29,153,205,222,76,63,9,124,57,251,218,79,64,227,23,225,64,10,247,244,65,223,145,119,254, - 115,225,75,95,249,106,91,241,177,39,183,173,132,111,212,225,126,31,118,10,65,155,176,118,233,177,32,24,217,252,162,23, - 10,73,149,212,206,97,109,140,180,206,30,65,10,133,209,100,118,12,174,250,184,20,76,69,20,165,28,61,54,234,128,229, - 36,93,176,118,205,56,64,77,187,141,166,104,49,73,19,210,196,145,202,42,213,170,91,183,183,181,163,148,200,54,37,134, - 66,46,143,144,146,56,137,1,129,31,248,24,227,152,177,2,233,214,238,153,71,241,244,244,36,113,220,64,27,77,163,209, - 192,247,125,60,223,103,247,238,61,236,221,179,151,92,232,236,52,172,181,78,31,100,52,229,242,28,185,92,216,26,197,154, - 26,51,63,231,163,23,4,222,173,187,238,59,112,38,85,43,129,74,22,206,209,140,188,94,36,133,250,158,186,109,63,155, - 79,127,20,157,122,243,245,189,23,184,1,26,67,150,253,158,176,243,137,224,248,185,150,35,39,223,247,241,43,230,191,122, - 95,223,160,231,111,51,105,116,18,72,162,98,158,40,244,68,161,183,221,70,199,39,17,181,136,28,216,54,136,231,96,188, - 108,237,108,4,71,66,33,182,143,88,54,143,76,78,159,55,255,222,143,174,63,249,233,47,172,60,122,243,245,35,93,175, - 127,121,113,233,166,85,120,73,21,146,136,156,77,233,187,226,82,111,223,237,95,27,190,18,150,166,80,186,9,102,207,201, - 158,91,31,80,254,46,143,173,92,4,206,243,131,44,64,57,47,96,235,216,17,46,57,180,131,142,90,5,59,178,241,91, - 197,60,63,175,31,22,88,61,49,201,173,15,63,204,23,151,46,37,254,14,95,134,5,84,232,81,236,43,210,103,45,61, - 217,129,175,10,193,234,40,173,111,159,168,238,202,195,23,150,206,150,39,244,99,79,134,30,236,52,176,53,132,99,57,104, - 84,45,189,18,122,231,151,246,119,174,88,51,140,52,9,126,45,160,62,171,72,26,9,90,217,204,46,193,137,65,37,158, - 243,151,22,128,244,40,87,235,204,204,149,93,146,106,83,95,151,233,181,50,143,52,164,116,185,95,22,50,37,123,22,131, - 99,45,149,114,153,84,59,100,67,107,87,68,38,167,166,24,28,26,66,27,227,236,53,117,150,25,134,6,147,105,172,180, - 38,78,98,166,166,167,41,228,29,97,177,214,136,90,69,236,145,71,31,161,88,44,58,83,45,207,195,88,67,181,90,165, - 167,187,135,70,189,65,146,56,47,37,151,129,5,58,241,72,101,129,138,81,207,32,126,236,3,30,2,54,101,221,139,121, - 142,222,220,103,43,6,63,170,71,4,204,66,114,200,114,242,133,80,158,23,156,28,18,98,155,57,62,90,170,11,113,164, - 164,228,158,57,109,26,43,227,152,251,26,117,139,49,46,162,121,209,207,104,119,31,81,25,198,231,173,157,17,66,28,70, - 200,199,74,66,172,108,159,47,159,87,253,212,231,46,57,244,229,187,207,219,127,203,13,131,171,95,249,226,96,205,121,107, - 177,74,177,246,178,45,124,165,191,171,199,156,154,89,146,66,231,18,24,237,118,93,12,41,240,89,92,224,230,143,66,153, - 254,172,191,179,232,7,220,115,226,32,159,223,245,8,55,103,99,216,127,228,135,197,121,10,13,87,107,60,182,123,15,243, - 89,31,247,237,94,149,1,122,54,13,176,230,61,175,227,252,70,210,122,67,4,161,199,145,253,19,54,120,203,39,103,195, - 122,250,88,13,14,27,183,217,153,42,192,108,9,210,237,32,87,128,104,128,39,134,151,132,125,67,75,64,38,164,182,76, - 156,206,145,16,147,106,237,178,211,180,51,244,210,194,173,197,141,209,4,126,200,190,253,123,153,154,158,35,8,115,89,170, - 230,162,43,202,100,209,127,214,233,194,76,150,233,222,244,152,9,130,160,149,243,21,199,49,24,75,173,90,229,216,209,163, - 244,245,15,144,102,244,123,41,165,43,70,153,69,131,84,46,158,55,141,83,78,157,154,96,233,210,17,170,181,90,203,14, - 116,219,142,29,140,79,76,48,60,56,224,114,231,27,53,230,230,202,88,107,153,157,157,161,90,173,96,76,63,158,231,161, - 73,51,103,65,73,42,13,54,244,229,217,238,182,31,199,197,35,249,217,197,250,159,237,225,3,211,238,195,62,12,243,203, - 44,187,114,214,30,77,65,21,125,191,241,84,28,215,255,16,204,137,185,50,183,140,79,225,183,121,207,90,68,219,220,71, - 60,111,237,68,206,218,233,26,28,138,29,227,120,247,134,249,242,11,231,63,249,239,91,14,124,241,43,75,182,95,123,69, - 207,218,55,252,88,176,246,242,43,232,219,120,78,208,56,245,64,78,65,104,23,185,202,248,217,53,48,138,243,109,87,207, - 135,2,84,244,3,238,61,126,128,247,239,126,148,206,31,192,221,232,71,253,40,0,159,92,24,165,190,109,225,66,128,240, - 37,42,149,173,55,129,39,5,81,123,142,193,246,208,60,89,79,103,111,128,249,0,120,59,216,139,221,156,204,52,216,21, - 78,241,59,90,124,122,207,169,143,188,237,15,150,47,191,98,11,253,131,253,12,181,15,225,217,105,114,170,141,184,58,141, - 64,99,108,232,50,161,132,15,66,16,4,121,142,30,61,73,28,155,86,212,110,147,249,108,157,149,139,43,26,210,81,252, - 109,43,194,215,109,183,234,181,58,245,122,157,48,12,241,148,34,214,9,167,38,38,168,84,42,207,72,220,212,38,235,156, - 204,194,10,190,94,143,40,151,43,204,205,151,201,231,10,132,97,200,212,204,12,199,30,127,188,209,38,165,138,226,216,239, - 234,233,116,73,17,137,38,137,28,151,105,102,118,150,254,106,149,66,62,159,153,162,25,148,210,120,42,38,202,73,121,182, - 134,100,183,227,209,240,42,254,115,63,60,96,7,176,20,226,99,16,231,129,210,77,87,146,91,49,200,137,127,250,184,123, - 207,125,155,72,225,69,155,103,91,130,180,8,243,7,160,218,14,51,41,140,182,193,246,77,213,218,218,202,151,190,182,246, - 216,157,247,174,20,155,206,41,92,52,57,121,12,216,173,96,38,6,83,57,227,186,142,29,190,195,16,252,80,199,85,239, - 217,138,207,251,118,63,250,221,173,201,254,131,62,222,149,97,59,133,111,83,133,172,113,24,71,11,143,48,22,180,107,147, - 143,2,189,142,153,195,49,224,66,224,114,96,5,216,105,167,66,121,248,146,169,153,158,177,191,122,215,229,251,61,57,242, - 228,210,161,206,210,133,23,22,251,183,44,83,165,117,151,176,118,237,106,74,254,12,245,90,68,16,228,29,94,163,53,66, - 10,142,30,61,74,162,173,75,218,104,122,49,11,167,126,55,194,100,91,48,183,138,39,179,224,108,90,105,68,113,140,78, - 83,252,192,39,8,3,202,243,21,102,166,167,221,184,102,108,43,230,87,9,73,98,210,140,5,237,108,65,165,116,88,144, - 167,60,242,249,2,113,148,224,43,159,189,251,246,243,170,169,169,169,109,61,221,249,131,97,208,45,148,114,91,81,79,97, - 234,49,198,58,32,60,142,35,114,97,136,20,206,49,47,77,53,167,166,230,145,58,80,153,171,18,157,96,123,178,21,187, - 197,241,125,150,0,23,253,144,47,130,31,5,54,180,248,186,210,75,6,24,122,221,141,144,21,160,239,118,172,44,0,79, - 128,190,2,166,82,167,191,218,39,161,175,0,203,55,26,189,212,108,223,30,26,152,180,82,238,212,198,140,111,2,179,129, - 103,26,52,75,135,193,177,251,71,85,128,206,44,62,207,199,49,202,126,171,78,229,123,120,236,199,153,223,255,222,115,244, - 28,115,192,71,129,123,178,150,251,106,168,156,11,79,104,152,29,134,39,71,82,179,70,31,58,177,180,118,232,68,127,249, - 51,12,29,232,40,141,60,116,238,218,174,53,175,185,53,184,238,166,11,32,73,49,54,64,72,69,189,150,242,244,206,253, - 68,105,130,239,41,23,5,148,113,126,180,113,186,32,165,188,214,129,145,66,97,172,35,11,166,105,74,20,69,72,169,240, - 85,72,146,164,212,234,53,202,213,50,169,78,152,153,157,164,189,171,141,36,73,145,210,169,223,61,33,208,169,198,42,231, - 114,23,248,30,74,73,106,229,50,126,143,199,241,153,9,186,79,30,169,94,232,137,233,199,69,184,52,78,34,82,29,19, - 120,121,106,166,1,194,144,36,49,141,70,204,220,220,60,133,124,17,37,4,66,26,142,29,29,101,223,137,99,108,136,202, - 210,66,177,12,185,95,3,249,151,89,94,195,226,115,248,24,206,61,204,240,255,200,35,77,73,171,245,239,235,71,152,108, - 34,159,131,218,90,168,165,48,49,9,135,114,144,87,66,72,35,101,162,181,174,134,16,165,223,98,252,249,97,99,101,222, - 243,181,248,216,179,108,63,100,118,119,236,18,66,230,133,224,45,198,216,243,129,186,227,129,144,126,31,7,240,95,221,29, - 153,151,63,7,179,254,195,89,39,4,112,23,152,79,193,140,15,79,213,224,160,231,172,96,123,124,232,25,128,21,75,231, - 42,91,230,31,120,242,226,175,76,79,175,191,232,218,75,242,29,57,139,173,67,222,11,24,155,172,48,54,117,18,223,115, - 62,65,206,22,214,37,17,52,237,51,28,33,217,189,106,99,156,249,124,24,6,132,97,64,20,53,16,66,81,42,181,161, - 148,199,204,236,44,81,163,129,84,146,233,233,41,150,44,91,146,117,47,26,161,157,19,162,148,210,129,210,198,1,219,243, - 115,51,4,74,146,6,146,147,199,14,218,159,47,151,119,14,167,246,120,151,79,71,156,212,58,203,179,51,148,74,61,228, - 194,128,164,94,195,90,147,217,126,164,40,207,167,90,174,112,252,248,113,70,79,142,146,120,130,137,134,9,82,23,21,215, - 61,233,204,192,158,193,253,91,130,147,94,180,159,229,61,225,101,56,133,230,191,30,103,219,78,153,236,184,41,208,71,161, - 50,0,21,191,144,231,112,103,59,246,196,216,183,223,60,253,40,10,80,201,15,184,231,135,92,124,100,230,222,159,1,14, - 167,223,16,178,55,153,196,41,225,113,40,189,88,46,68,174,96,109,151,18,162,77,11,33,127,25,140,6,61,6,113,27, - 204,231,96,190,243,123,188,113,158,194,81,253,159,2,126,253,57,124,157,198,117,69,86,64,60,235,136,101,51,195,112,244, - 8,248,41,108,5,118,151,96,118,243,190,35,165,135,62,243,232,154,87,252,220,139,136,235,179,228,148,199,145,147,135,152, - 169,214,9,50,202,157,102,33,218,89,156,102,21,75,43,194,215,121,240,116,48,54,54,70,181,90,109,121,243,52,85,237, - 113,146,64,98,153,158,158,166,86,173,17,71,17,190,239,172,52,13,206,228,160,201,51,82,74,209,219,211,231,120,64,149, - 10,29,149,114,125,189,101,42,134,184,88,176,169,177,41,81,37,38,31,54,144,38,193,24,75,45,170,227,123,1,149,74, - 5,157,166,204,204,204,112,252,248,9,82,29,225,135,57,142,7,65,190,2,61,237,208,86,1,249,123,110,59,116,26,248, - 41,178,177,108,219,25,199,50,1,254,12,120,159,27,121,255,235,241,109,138,145,93,116,60,237,162,209,239,249,52,222,122, - 29,65,142,175,30,219,199,251,127,136,197,71,0,181,52,161,166,19,33,114,69,100,154,218,102,225,153,119,237,119,216,13, - 109,83,80,58,7,228,28,36,155,17,73,44,212,176,181,233,197,21,99,214,104,240,27,144,134,142,137,57,147,192,142,10, - 60,249,155,48,62,233,138,18,179,223,67,27,255,33,215,181,112,103,118,17,60,87,175,183,201,48,77,192,46,117,192,97, - 122,24,234,26,234,17,20,86,165,44,253,234,63,189,179,247,241,115,251,58,95,112,233,38,76,108,216,189,247,8,105,234, - 17,72,141,16,6,107,85,43,21,193,117,60,38,51,46,115,0,178,51,47,183,248,190,79,189,94,119,172,232,32,32,159, - 119,78,134,113,28,19,71,49,22,195,252,220,28,113,20,97,180,195,125,48,6,154,60,164,204,116,44,8,67,250,251,7, - 24,30,25,228,224,241,147,204,167,135,180,208,182,77,66,187,110,196,62,97,145,52,85,232,84,210,214,214,78,146,66,165, - 92,161,90,173,50,49,49,65,28,39,116,117,117,209,221,221,197,201,209,19,144,164,32,172,48,66,120,202,90,85,5,241, - 101,156,213,174,127,150,110,39,231,192,218,211,58,225,175,3,247,2,111,248,175,26,243,159,3,148,255,231,29,15,242,240, - 248,177,31,218,88,5,153,255,206,212,73,222,246,228,221,246,47,58,251,81,167,142,52,145,120,175,12,61,33,172,246,96, - 163,116,221,120,232,65,69,99,103,165,213,195,147,112,237,216,11,175,61,239,188,23,92,42,102,39,39,244,215,239,123,208, - 118,60,189,119,242,74,120,56,114,222,190,247,127,22,198,151,131,249,48,176,231,123,120,158,163,192,205,25,56,253,214,231, - 104,46,22,103,220,153,194,236,2,27,135,121,207,25,116,223,127,237,236,204,242,175,188,245,207,207,143,254,244,119,243,183, - 190,248,6,14,29,61,134,109,8,116,62,71,98,26,88,76,11,136,110,146,16,91,157,86,182,189,114,49,44,130,70,163, - 225,142,117,62,79,24,134,204,206,206,82,46,87,156,197,134,175,72,146,132,90,181,138,213,198,113,90,105,70,234,209,202, - 187,87,202,3,41,41,150,74,188,232,133,55,178,173,187,163,248,205,219,62,222,251,210,24,211,83,179,70,229,114,4,185, - 60,169,182,120,40,124,223,39,159,207,145,38,186,37,219,104,111,107,99,249,178,229,204,151,231,169,233,24,109,61,18,161, - 66,109,211,188,15,222,83,124,119,225,147,54,187,81,213,255,235,218,253,207,81,128,238,31,61,252,67,41,60,249,69,179, - 251,91,64,204,3,249,218,60,203,106,243,210,130,122,28,194,14,24,66,136,203,140,181,87,31,18,226,130,253,109,249,145, - 178,231,7,75,202,149,202,154,68,79,117,89,27,142,14,14,44,187,244,207,254,160,125,96,73,55,131,186,206,242,95,253, - 73,238,248,200,167,186,238,251,235,127,41,93,19,107,171,161,190,23,238,15,97,214,251,62,218,205,49,224,175,113,174,89, - 127,225,73,46,15,60,102,107,9,223,143,10,165,153,240,33,113,196,187,221,174,48,217,115,96,70,193,145,18,76,174,28, - 157,136,126,251,247,254,62,191,231,104,196,145,99,147,248,158,33,53,202,229,145,147,182,58,158,230,248,181,240,57,91,163, - 91,75,28,199,148,203,142,151,211,214,214,70,163,209,200,64,233,6,82,58,161,105,28,199,212,106,245,108,156,115,193,132, - 126,150,57,238,140,254,21,65,16,16,197,17,59,158,126,26,99,44,231,93,118,177,124,104,244,196,242,13,247,126,99,180, - 61,49,137,78,35,27,9,45,146,58,200,176,68,154,56,158,82,169,88,68,72,183,137,51,198,80,106,43,177,102,205,90, - 158,220,177,29,163,13,13,107,187,36,44,139,160,227,56,84,58,157,24,242,59,46,244,2,199,222,205,204,40,254,235,241, - 31,185,0,61,151,128,113,83,165,108,179,121,61,7,108,2,177,20,188,13,142,89,95,24,135,194,171,193,111,146,160,170, - 80,208,208,51,15,189,1,172,173,90,123,213,232,186,85,151,180,255,204,27,251,46,95,191,138,64,133,236,123,236,137,222, - 59,191,124,207,210,104,215,238,116,175,151,250,235,38,142,146,51,147,40,105,200,123,138,159,124,243,171,248,55,196,208,67, - 127,250,206,23,92,13,83,198,137,230,182,11,168,174,201,166,176,239,181,110,220,11,188,124,207,4,159,127,242,4,151,159, - 55,196,108,57,250,174,139,80,179,8,158,4,190,8,252,21,142,108,55,147,225,77,109,144,171,67,239,140,16,61,95,90, - 186,169,237,156,45,215,51,58,238,115,228,248,52,50,144,36,137,70,170,44,86,165,25,137,44,23,46,189,166,129,188,51, - 17,211,84,170,85,26,141,70,22,1,227,183,204,198,92,18,134,32,8,2,146,56,166,50,63,15,38,75,212,108,30,33, - 65,43,39,94,74,69,177,80,32,73,19,142,28,57,194,255,207,222,123,135,89,118,149,87,222,191,189,247,57,231,158,155, - 43,231,234,234,156,179,164,86,4,101,129,4,152,12,6,27,99,123,28,39,224,48,51,30,143,103,252,217,51,223,140,199, - 51,159,51,99,112,24,27,27,147,49,89,36,33,161,156,67,119,171,115,206,149,211,205,39,237,189,191,63,206,173,150,192, - 2,36,1,99,140,123,63,79,61,221,93,93,85,125,251,222,123,214,121,223,245,174,119,173,92,87,137,242,186,205,217,227, - 247,63,86,144,214,46,34,173,49,132,202,104,75,28,57,248,217,44,149,197,69,234,141,6,158,151,161,217,108,210,221,213, - 69,24,134,148,203,101,214,172,88,193,179,179,115,76,98,187,87,192,166,12,140,30,131,233,127,15,145,126,137,96,146,144, - 50,217,241,165,107,248,159,33,0,9,65,44,101,123,177,51,253,33,101,96,29,136,60,56,11,224,204,129,19,67,126,53, - 20,5,116,91,232,7,134,60,232,79,192,79,131,121,83,190,81,66,191,130,238,105,232,173,92,187,107,100,231,127,255,181, - 114,247,64,39,34,104,130,54,108,126,211,141,220,116,251,13,234,196,185,115,234,200,193,189,228,85,128,20,14,73,98,112, - 157,2,245,133,38,175,121,253,107,249,235,135,158,90,118,252,190,39,110,90,13,81,11,58,250,224,184,7,51,7,161,54, - 10,201,203,29,235,206,84,2,94,243,11,159,230,139,127,246,166,139,32,244,82,72,104,128,101,109,0,218,0,44,127,222, - 196,194,1,21,66,191,7,27,191,226,23,87,230,111,255,247,106,108,104,45,141,153,67,84,195,6,70,105,156,184,157,217, - 69,202,249,44,129,207,82,37,180,196,9,201,118,96,95,179,209,32,12,67,114,217,108,170,70,214,154,102,179,73,171,213, - 66,42,117,209,86,181,213,10,8,162,224,185,239,109,47,168,218,118,210,156,239,251,228,242,121,42,149,69,130,8,206,158, - 159,167,114,104,143,185,206,198,250,110,225,150,26,137,80,69,55,139,17,128,150,72,55,213,251,88,99,218,85,86,10,214, - 75,153,230,35,3,3,84,54,175,227,161,39,22,203,151,53,163,181,192,198,60,156,252,63,48,189,30,108,242,50,110,124, - 230,210,53,252,207,3,128,44,16,73,7,227,120,104,27,176,97,102,130,53,243,51,116,130,188,17,252,50,228,37,116,132, - 208,211,132,78,153,182,246,125,10,6,99,24,170,194,80,5,122,106,80,182,2,133,227,96,188,140,66,73,101,141,206,156, - 23,248,135,6,250,51,183,189,241,181,114,239,209,147,100,78,9,58,203,37,138,133,28,88,75,214,81,172,28,234,99,253, - 138,59,72,116,148,142,138,157,212,3,39,209,134,188,178,188,253,63,190,71,125,248,220,111,174,115,79,156,114,135,211,229, - 233,131,26,246,77,193,161,41,184,224,164,147,178,248,229,84,67,243,149,128,87,255,226,167,249,244,255,126,3,215,108,30, - 120,158,37,198,55,30,221,110,55,151,196,117,189,164,226,174,9,96,61,233,206,205,210,81,192,60,120,53,24,108,193,234, - 249,141,151,117,6,54,161,85,15,9,235,53,226,200,160,156,28,56,96,147,22,178,221,34,89,1,86,183,163,163,121,46, - 129,2,1,81,146,80,111,181,240,252,44,70,107,114,185,60,214,10,170,213,26,113,162,201,250,25,172,77,201,230,74,165, - 70,171,217,34,49,49,74,40,208,34,13,202,75,119,60,48,218,162,163,4,29,197,100,253,12,243,19,83,120,135,142,55, - 71,33,156,87,73,167,107,98,154,129,69,43,131,175,138,40,55,3,38,117,89,108,182,34,206,157,187,64,177,80,166,187, - 171,139,32,9,81,142,195,134,21,107,216,31,132,254,215,159,222,187,250,85,113,184,83,192,222,22,44,220,7,209,203,105, - 167,18,224,230,239,182,148,183,160,228,243,242,183,196,37,96,248,129,2,32,11,120,214,112,213,133,195,220,239,120,220,214, - 90,20,73,109,65,90,40,36,48,80,134,49,9,43,37,140,58,48,92,135,190,42,20,103,161,107,54,235,117,68,35,195, - 133,100,100,89,174,184,98,76,245,173,24,19,163,171,150,211,209,211,73,177,163,156,110,118,43,69,44,211,55,127,80,171, - 80,175,213,240,179,89,28,165,40,148,10,196,81,8,113,72,61,142,9,230,170,104,29,35,73,205,206,93,79,146,245,179, - 40,2,86,12,117,241,150,255,249,91,153,191,253,221,63,94,151,28,56,56,182,51,8,119,108,183,28,205,167,142,120,187, - 45,236,86,82,158,190,222,218,230,110,107,41,191,68,18,121,113,49,224,15,126,247,62,94,241,177,119,18,235,23,190,247, - 246,1,159,108,19,171,246,121,109,133,126,129,159,23,164,0,228,100,160,179,9,93,131,151,191,194,25,218,182,138,147,143, - 29,34,168,158,163,101,23,241,113,113,18,137,176,41,73,108,141,109,175,107,136,212,74,213,202,52,5,68,164,235,20,73, - 162,169,213,27,216,118,75,230,186,94,234,19,100,210,118,76,107,147,110,180,43,39,213,22,181,35,132,93,215,35,245,210, - 75,227,168,181,182,88,163,201,250,89,226,176,133,178,10,226,128,150,76,172,128,74,54,54,121,153,56,196,194,224,185,14, - 65,16,210,108,77,161,209,41,178,10,67,179,213,96,247,238,221,172,92,177,130,209,177,101,88,107,112,81,108,216,118,25, - 7,102,23,123,174,57,126,116,121,6,122,59,64,173,120,153,213,140,37,157,156,46,126,19,217,255,82,142,54,154,225,142, - 110,166,87,172,164,162,155,200,122,149,75,40,244,3,6,64,202,90,118,206,95,96,38,181,103,204,207,195,72,6,54,40, - 216,94,133,45,23,96,197,184,82,189,141,145,193,162,90,191,42,59,118,197,78,53,184,102,149,216,177,106,37,203,87,173, - 160,220,217,133,239,101,83,155,137,139,44,81,59,18,24,131,115,113,15,250,249,102,151,75,69,118,59,128,205,88,116,28, - 161,117,66,216,74,91,138,11,231,207,113,106,124,130,78,87,210,211,231,179,126,243,10,126,249,189,255,69,158,56,125,54, - 119,244,177,167,151,127,233,222,71,7,157,131,199,183,94,153,36,59,6,225,158,121,99,191,250,6,56,124,3,52,110,125, - 57,207,216,254,73,248,127,239,193,253,47,183,242,66,100,208,111,189,132,31,213,72,43,35,87,164,22,152,57,153,93,38, - 122,251,55,99,215,133,124,241,83,159,194,209,22,87,5,88,225,160,141,66,182,125,127,165,109,87,60,8,172,208,88,76, - 154,220,106,185,216,110,93,140,207,53,134,40,142,72,146,24,33,5,197,124,30,37,37,58,73,40,149,74,72,36,58,49, - 224,166,62,63,214,154,139,217,235,162,45,76,76,55,229,45,157,61,157,136,87,222,80,248,203,187,238,46,28,17,210,179, - 73,154,202,42,132,161,165,107,132,24,60,199,75,109,67,144,88,145,134,234,157,60,125,28,99,34,86,44,91,145,166,104, - 184,14,174,163,158,167,106,74,95,237,151,187,8,41,72,69,164,241,203,2,49,139,35,125,20,14,227,157,101,60,213,65, - 62,10,33,142,46,161,195,15,10,0,233,118,27,49,3,110,63,244,87,97,179,15,87,87,96,215,177,172,191,97,230,242, - 237,131,125,215,93,235,93,253,202,235,88,179,125,19,165,222,18,121,229,165,218,14,27,164,235,5,82,131,105,160,69,234, - 25,147,218,73,60,103,7,170,137,46,10,234,150,198,192,105,252,111,123,103,201,182,121,138,182,185,186,231,103,41,118,66, - 223,208,8,213,90,149,35,135,14,179,231,248,41,134,122,106,140,246,117,50,188,105,140,91,119,109,161,246,75,191,152,121, - 246,196,185,129,3,127,254,119,221,225,223,127,182,60,134,21,85,8,71,225,200,239,66,252,44,223,217,224,234,155,193,56, - 248,248,94,54,150,125,222,252,238,157,200,246,243,243,219,164,102,101,153,23,57,121,11,128,159,3,114,105,21,217,63,239, - 137,78,205,180,208,45,67,247,186,173,92,119,227,235,169,125,240,12,149,112,150,192,81,184,194,34,76,106,84,33,105,71, - 177,96,211,88,222,246,126,185,92,210,9,33,176,58,173,94,178,217,44,66,8,162,40,192,152,152,108,214,79,213,208,82, - 48,60,60,140,239,103,73,146,246,247,88,211,190,37,200,118,224,161,105,71,28,65,43,174,99,61,75,95,247,144,152,188, - 234,186,85,231,158,120,128,188,83,67,40,7,99,4,113,4,202,203,33,133,139,53,1,88,75,179,25,144,241,28,60,207, - 97,106,106,18,41,29,150,141,44,163,49,62,201,166,179,231,230,242,112,38,129,217,41,72,142,72,69,67,170,151,93,119, - 44,73,27,50,128,76,162,23,105,58,103,113,165,143,148,169,243,163,74,82,7,130,53,203,86,177,80,173,50,117,242,2, - 59,234,141,75,40,241,143,9,64,121,160,7,196,30,200,59,66,172,114,225,106,107,237,43,15,185,206,229,181,31,185,125, - 108,215,123,126,193,219,186,107,7,5,191,128,192,96,147,8,155,36,216,168,73,34,65,40,16,142,66,90,209,78,249,20, - 40,218,126,53,230,121,250,76,153,82,182,22,241,92,27,110,211,59,190,18,2,164,109,103,102,181,69,120,23,91,32,65, - 169,84,230,138,171,175,98,205,154,21,60,249,232,67,156,58,91,101,168,167,27,217,10,105,105,135,141,203,70,184,233,35, - 31,112,255,71,125,126,107,246,43,15,84,122,225,228,28,92,16,176,176,234,101,220,121,35,96,213,103,246,19,172,237,166, - 33,37,203,129,199,218,119,225,23,123,1,185,41,160,203,101,208,33,96,232,116,71,87,231,53,87,46,48,53,115,23,83, - 93,87,176,241,21,111,166,59,83,230,207,63,240,159,136,131,121,144,18,35,44,74,184,23,239,250,75,155,239,75,207,162, - 227,40,116,98,46,198,246,64,170,11,106,54,91,212,42,21,178,126,6,199,145,200,172,79,146,36,244,245,245,165,213,81, - 28,167,49,64,24,172,144,88,253,156,235,165,235,58,105,61,106,28,148,113,168,53,102,216,177,109,61,6,205,179,135,246, - 34,164,33,137,13,198,10,84,152,96,12,56,34,133,101,171,53,137,134,90,35,198,74,69,237,236,41,180,84,12,156,31, - 215,87,52,235,39,13,236,137,224,194,70,72,30,24,93,205,254,114,23,222,119,145,174,98,73,165,13,253,115,51,116,36, - 213,54,24,127,103,240,249,134,91,134,181,184,214,50,222,217,73,112,227,181,76,30,60,130,57,113,230,82,67,246,253,2, - 160,63,250,54,101,109,51,189,67,11,23,58,178,176,85,89,123,243,20,220,120,124,211,218,45,215,253,222,255,40,239,188, - 245,6,124,105,208,113,128,14,43,41,123,96,69,138,37,66,98,101,59,66,214,166,246,17,72,137,177,23,67,61,219,9, - 195,233,189,74,182,163,126,133,32,229,52,172,120,222,202,65,59,232,181,237,153,188,68,188,166,111,24,147,2,89,28,209, - 81,46,243,202,91,110,227,240,190,189,84,90,13,114,210,165,228,251,140,31,59,66,169,220,201,141,255,254,87,220,103,238, - 126,112,77,127,98,183,52,97,207,29,80,217,242,50,7,41,122,166,193,51,255,225,43,84,141,97,61,105,192,225,75,109, - 27,22,193,13,211,232,218,254,227,221,203,243,242,217,73,222,117,29,60,112,230,28,11,250,77,12,94,254,42,222,229,6, - 252,221,95,252,54,173,160,138,235,186,36,137,198,145,41,249,156,130,143,196,74,133,213,105,76,139,213,150,48,8,113,93, - 23,207,243,176,214,82,171,86,218,57,94,57,28,199,161,218,168,224,185,46,25,207,107,155,216,123,116,150,59,218,160,37, - 16,74,181,127,103,211,169,24,128,208,68,205,6,25,167,196,236,220,60,55,221,112,3,29,221,163,196,145,226,216,241,227, - 204,205,156,64,234,10,88,7,209,158,214,117,117,119,131,116,168,44,214,169,53,3,2,3,207,30,216,207,234,74,189,89, - 134,227,45,56,148,129,133,86,177,195,30,236,234,19,57,99,172,80,223,157,178,199,2,83,3,35,156,211,33,5,179,72, - 189,29,120,253,162,192,231,121,63,67,36,9,189,133,28,135,175,186,12,175,191,151,209,125,135,113,106,245,75,64,244,189, - 6,160,95,250,54,127,89,1,246,65,190,2,91,115,240,198,211,112,243,145,219,111,89,247,142,63,255,3,119,221,232,114, - 108,179,130,177,22,225,8,148,77,121,3,35,5,70,202,246,82,81,42,241,183,198,192,146,110,101,201,64,253,249,4,0, - 96,133,69,44,177,1,82,128,89,186,203,155,246,59,34,229,36,210,175,177,207,17,7,109,13,140,149,233,198,85,198,245, - 89,189,122,19,179,227,103,56,119,250,4,103,107,167,88,187,118,45,147,227,211,92,117,195,205,60,118,245,174,158,214,131, - 143,111,20,66,172,18,214,158,107,119,151,47,249,124,1,56,163,13,111,79,43,153,139,250,167,151,2,64,46,136,24,84, - 11,156,161,145,117,170,115,205,47,242,208,177,143,114,251,214,25,30,57,244,121,206,235,55,177,122,215,143,242,46,41,249, - 196,223,254,1,243,115,51,120,174,135,54,17,74,164,201,168,8,137,182,18,108,130,104,123,53,47,217,180,46,69,47,87, - 43,85,146,68,35,16,23,199,239,67,3,67,164,118,169,9,181,90,21,221,219,151,6,13,168,231,216,55,108,74,108,59, - 74,165,9,28,78,234,237,99,90,130,133,201,5,118,237,220,198,19,79,28,228,250,107,223,194,248,244,9,14,60,251,21, - 38,39,199,201,100,4,165,130,123,113,234,134,6,71,56,184,174,67,84,111,209,105,76,64,26,199,51,61,12,225,233,124, - 153,80,185,228,237,247,136,119,177,134,172,202,144,213,14,53,251,124,255,156,244,125,243,237,192,231,249,199,104,131,210,134, - 103,86,45,103,95,87,39,87,29,56,74,120,246,60,74,107,226,54,117,112,233,124,31,91,176,67,169,195,223,144,15,175, - 220,15,175,58,245,186,215,174,251,213,191,121,159,232,233,42,162,163,10,66,88,144,10,109,21,70,180,147,60,165,32,165, - 118,108,187,164,79,53,32,75,117,134,64,164,241,51,237,23,223,216,165,132,13,217,230,122,82,228,145,242,27,151,45,49, - 75,127,175,210,76,236,165,22,36,245,46,37,17,26,43,45,210,66,190,144,197,118,117,35,19,203,93,119,223,207,211,207, - 222,197,149,215,94,203,198,29,87,208,243,250,59,178,71,30,124,124,237,86,107,215,71,130,61,79,88,234,127,202,115,254, - 195,47,134,187,185,146,212,198,242,245,164,177,38,19,164,158,198,75,174,139,47,22,128,18,72,52,204,150,224,216,192,189, - 159,155,152,188,252,142,209,210,213,239,225,209,83,159,226,154,141,115,60,113,230,243,156,27,191,150,177,157,63,194,47,13, - 12,242,249,143,252,37,123,246,62,141,20,22,75,26,51,100,219,185,244,32,48,38,193,90,8,163,8,41,4,158,151,193, - 207,248,56,82,165,211,179,196,16,6,17,58,209,20,11,121,180,78,173,56,150,252,160,51,110,6,107,45,137,214,237,205, - 248,212,156,94,41,133,116,124,34,109,209,113,136,43,18,106,243,9,165,206,44,215,94,181,149,135,31,57,206,216,234,43, - 25,25,219,197,225,67,15,115,248,192,3,212,234,227,72,17,162,128,140,155,198,205,234,86,132,159,203,209,104,70,194,166, - 11,196,241,95,10,73,179,107,152,46,109,172,254,30,250,241,41,43,24,16,121,38,169,34,173,37,80,105,142,154,43,51, - 72,94,154,70,62,19,70,152,98,158,71,174,189,156,179,27,86,211,113,232,56,131,211,83,232,182,141,238,165,243,93,0, - 208,35,223,226,226,136,83,102,198,247,96,109,3,118,29,223,117,217,138,159,252,195,223,17,61,93,101,140,105,130,171,210, - 182,202,74,84,27,8,46,142,157,77,123,74,99,211,88,153,148,93,110,79,184,172,109,195,144,2,43,144,164,230,235,90, - 132,169,203,95,123,26,102,144,72,68,202,175,90,211,30,99,139,246,224,169,189,81,213,206,155,50,194,32,210,102,36,205, - 170,151,146,66,111,15,65,164,185,253,142,219,249,195,223,251,35,238,249,210,221,220,252,218,87,177,237,182,155,249,108,199, - 31,246,111,91,92,92,81,177,162,119,28,59,225,130,254,78,133,255,210,50,105,54,229,196,46,122,74,91,82,129,225,67, - 192,239,242,210,244,40,115,144,236,133,115,49,60,120,93,210,24,249,226,123,255,237,171,78,118,255,81,207,198,109,239,228, - 174,147,159,225,138,145,179,140,85,239,229,153,201,141,120,189,87,243,174,95,93,199,138,187,254,134,175,126,234,111,105,180, - 2,132,148,56,9,196,42,193,8,75,70,120,72,3,58,140,145,89,73,198,177,132,141,58,65,210,66,40,65,198,207,128, - 53,40,71,209,217,213,141,177,150,36,14,201,122,57,180,73,176,50,211,30,4,216,244,102,34,210,40,232,40,73,109,85, - 131,32,192,69,129,136,105,73,203,212,228,52,229,142,65,110,188,97,29,247,62,178,155,254,161,27,217,124,249,205,44,223, - 176,133,67,251,30,231,236,241,251,16,97,72,33,91,64,121,150,196,26,140,114,105,136,212,144,204,2,21,107,56,219,168, - 176,58,55,74,168,147,239,225,157,85,82,23,169,78,90,58,46,15,175,95,143,149,18,247,185,250,238,37,29,169,13,82, - 27,206,151,75,156,191,122,39,199,163,152,177,74,133,76,43,160,171,25,162,171,181,75,104,242,114,94,167,109,223,130,32, - 61,12,76,67,41,7,171,38,4,171,58,111,184,38,179,97,213,10,48,205,20,80,218,166,232,152,212,10,73,146,182,93, - 98,169,52,21,150,56,14,9,91,13,130,160,133,20,2,141,197,241,92,116,98,81,72,208,130,68,107,162,88,227,58,30, - 82,72,180,17,120,249,84,60,39,17,8,37,41,20,10,40,183,61,186,183,96,147,118,176,158,72,91,51,99,45,210,202, - 182,103,177,73,135,249,74,82,232,233,160,50,49,193,47,252,236,59,120,255,251,63,205,196,228,56,155,55,111,224,254,171, - 174,206,215,191,242,229,101,74,138,161,78,99,15,255,123,104,13,240,237,61,102,50,164,155,216,51,164,155,216,75,220,153, - 36,93,57,249,125,224,115,192,79,1,231,95,68,69,37,73,87,49,118,66,101,23,236,14,97,232,142,250,212,216,95,253, - 254,111,92,206,47,255,169,191,105,251,79,115,207,225,15,177,189,251,36,55,47,123,146,7,46,92,160,150,187,158,87,220, - 241,111,89,177,250,50,62,251,177,223,227,248,161,221,100,29,7,37,178,41,99,227,8,140,4,65,76,54,83,38,91,44, - 34,125,65,206,115,200,56,170,205,163,9,242,249,34,202,245,104,5,1,190,239,163,148,67,98,82,32,87,74,33,244,146, - 252,65,145,201,248,152,212,166,158,140,167,144,74,225,185,89,154,145,69,182,34,102,231,38,24,27,27,229,134,107,87,241, - 204,254,61,148,114,59,65,141,176,121,251,32,99,195,27,56,114,240,75,204,77,95,192,247,32,239,187,52,98,80,237,16, - 178,165,214,232,193,233,51,52,130,26,201,247,48,222,91,34,168,217,8,81,116,232,238,234,72,23,109,173,229,187,53,163, - 112,218,161,134,177,82,244,118,119,211,227,56,228,187,58,185,112,239,35,168,90,253,18,162,188,212,231,211,125,161,242,21, - 40,130,156,135,14,11,203,38,10,217,238,93,183,220,146,150,249,246,185,221,33,33,192,10,145,190,184,34,45,215,177,154, - 168,213,96,126,118,146,70,179,70,28,181,104,5,13,116,3,226,88,179,88,173,208,106,182,208,218,48,51,53,211,246,37, - 22,136,88,210,213,213,197,220,194,2,70,74,138,165,14,234,173,58,177,78,245,42,43,87,143,210,223,223,71,169,80,162, - 183,183,143,108,169,4,82,161,218,83,155,165,164,80,129,104,175,40,216,180,220,247,50,116,118,247,112,235,171,174,101,122, - 98,138,193,129,53,172,127,253,237,153,217,175,124,121,100,153,49,163,46,20,159,133,214,239,125,135,234,37,3,172,252,14, - 32,37,218,237,217,223,167,220,25,47,230,126,126,57,152,24,22,12,226,172,143,157,219,185,48,31,253,207,63,248,13,255, - 199,223,243,159,217,113,245,59,121,236,208,215,152,169,60,197,173,91,15,113,120,98,146,131,19,55,144,95,249,42,254,197, - 191,219,206,51,247,125,132,7,238,251,4,179,231,79,145,83,2,235,103,168,89,77,214,201,128,86,72,235,16,197,150,86, - 37,38,151,41,224,186,46,205,122,147,222,222,62,242,249,220,197,22,55,73,98,130,32,32,159,47,96,180,126,78,6,97, - 12,142,163,200,102,253,148,196,206,229,48,198,144,36,9,174,43,137,163,144,106,181,198,252,124,149,129,161,94,214,173,201, - 112,234,196,5,58,75,155,152,171,79,147,47,174,231,138,171,7,57,121,226,49,142,236,189,27,130,38,42,159,67,40,41, - 45,8,167,253,156,53,90,117,30,108,125,127,46,222,45,133,49,148,84,36,250,123,107,97,38,172,69,91,139,136,34,230, - 10,5,158,184,241,26,42,247,63,134,170,84,47,161,202,75,1,160,167,190,197,221,217,3,37,160,171,5,67,206,182,157, - 133,13,91,54,129,14,46,146,194,66,166,160,35,68,58,38,215,180,35,94,130,128,51,71,78,18,183,90,156,60,123,138, - 133,197,5,130,32,68,89,133,53,6,63,147,105,231,139,91,134,7,135,211,133,73,199,161,163,51,79,28,133,12,143,118, - 164,137,161,113,68,198,43,210,217,81,38,137,99,22,91,117,22,39,35,38,130,128,3,218,82,238,232,164,171,167,143,190, - 129,65,186,122,123,17,106,41,35,93,94,220,137,2,75,161,92,162,114,161,198,202,85,3,212,226,212,200,97,211,77,215, - 240,245,193,254,126,59,49,181,78,8,49,16,88,59,223,13,137,255,45,238,143,75,169,1,115,164,33,121,223,174,170,89, - 11,252,87,224,20,112,125,58,69,252,182,99,54,63,173,52,169,97,29,11,190,144,137,76,146,9,62,246,222,255,132,174, - 84,217,126,199,91,25,191,48,198,223,223,251,113,110,222,58,75,199,232,151,120,236,236,49,90,185,155,185,234,246,247,176, - 249,218,215,242,204,131,159,102,247,61,95,100,122,230,48,142,178,8,153,39,50,9,36,1,50,48,68,6,130,36,70,38, - 10,165,28,6,7,7,47,26,142,165,94,215,105,162,234,18,32,165,55,25,139,227,166,162,66,221,30,203,63,55,154,119, - 145,82,18,199,49,11,243,243,20,242,121,124,63,203,200,64,63,213,217,211,212,235,46,165,66,39,243,205,10,34,238,100, - 213,170,219,232,239,26,228,192,179,119,179,24,206,209,240,60,215,166,97,154,50,223,150,122,124,47,189,151,104,131,127,0, - 148,11,133,111,200,129,255,94,31,11,120,73,194,92,46,71,207,29,55,113,100,255,17,70,246,29,226,18,61,253,34,1, - 232,53,223,60,94,78,171,31,254,2,100,25,178,13,200,55,202,157,94,185,88,120,238,242,124,190,27,95,59,31,70,27, - 141,43,4,11,211,179,92,56,115,158,7,191,126,31,197,114,39,195,163,203,72,104,209,55,214,137,142,90,116,119,116,81, - 89,92,36,54,17,142,43,40,230,75,36,113,76,152,196,20,75,229,52,143,42,138,40,148,10,228,11,57,16,22,87,102, - 41,116,20,210,246,75,150,49,214,210,108,133,204,207,92,96,118,234,2,67,195,35,44,223,184,1,148,215,78,134,16,44, - 169,26,189,76,6,43,37,86,196,44,46,84,33,137,25,91,53,74,112,221,174,238,250,39,191,176,62,3,107,198,224,204, - 155,160,146,255,54,79,212,19,164,86,171,223,137,100,94,178,136,248,98,187,10,250,207,124,251,152,153,32,125,206,133,0, - 37,16,242,140,180,42,145,33,182,85,229,99,127,241,223,57,55,127,154,31,121,235,47,16,103,255,35,159,223,255,247,108, - 236,219,205,109,203,14,112,114,102,154,51,19,219,241,58,47,231,234,215,255,18,219,175,123,3,207,62,248,9,30,255,234, - 199,169,213,171,180,156,136,134,209,120,65,11,191,208,194,46,54,81,178,128,155,117,241,51,62,158,227,34,132,162,209,106, - 162,164,75,24,68,196,113,140,231,101,80,109,65,160,235,58,237,73,153,38,155,205,34,5,248,190,79,24,134,105,204,15, - 16,199,17,173,102,147,74,173,2,18,54,111,238,99,239,254,35,52,163,245,248,110,158,102,18,208,170,75,74,29,107,217, - 113,117,7,15,62,249,89,106,179,23,164,133,108,29,188,127,3,226,119,193,126,183,245,201,146,37,111,196,115,137,171,159, - 4,62,109,204,247,12,220,190,45,233,221,54,116,107,109,219,72,183,181,92,216,127,248,18,186,188,152,215,109,241,5,62, - 169,83,182,69,168,52,106,94,230,11,37,225,56,18,99,211,81,174,160,173,223,177,96,49,24,171,81,82,208,170,55,88, - 152,159,97,239,222,39,201,21,92,54,110,94,77,179,213,162,148,201,224,23,50,72,147,33,142,34,202,229,18,133,114,137, - 68,39,68,65,64,33,155,37,155,203,167,252,141,209,228,140,143,114,36,137,73,72,76,130,18,138,140,78,91,2,233,164, - 161,125,133,130,79,169,109,200,30,55,42,204,140,95,160,111,120,20,107,4,86,56,136,139,194,69,7,199,247,113,154,25, - 38,46,156,33,142,12,110,206,101,228,77,175,247,206,127,242,11,171,54,88,187,206,192,83,143,65,229,67,192,193,111,226, - 111,2,224,215,72,179,180,95,236,69,178,68,115,126,1,184,163,253,125,47,52,244,93,34,251,115,105,5,160,141,148,122, - 10,165,164,73,136,51,18,220,22,247,125,238,125,212,79,158,227,245,239,254,77,70,175,255,89,78,158,126,128,227,143,127, - 134,203,86,76,112,229,80,200,145,241,195,204,85,174,194,27,216,192,43,223,248,107,92,126,205,235,248,244,223,253,79,78, - 28,60,128,54,14,213,100,150,48,108,161,100,6,33,4,189,189,189,228,115,89,194,32,196,216,212,27,104,41,1,99,201, - 196,222,201,56,23,125,130,148,227,160,148,66,57,10,207,115,46,102,143,45,249,18,197,113,68,181,182,136,227,123,40,199, - 5,19,177,110,93,31,143,63,117,150,56,92,75,206,87,72,63,33,137,93,92,217,143,162,72,35,140,29,4,93,198,210, - 177,8,78,25,162,151,91,49,136,54,232,76,146,186,215,205,145,186,40,22,121,241,170,244,239,89,53,100,45,197,56,230, - 224,214,13,212,138,5,244,254,195,112,137,23,122,249,99,248,54,24,137,66,62,143,116,36,214,36,41,255,44,100,26,73, - 35,20,182,173,235,17,198,18,54,27,180,90,117,250,6,123,232,40,21,105,197,85,188,188,79,169,179,139,170,205,49,61, - 49,137,104,70,148,10,69,206,94,152,160,214,104,176,56,51,67,78,185,244,12,150,24,24,30,192,43,228,241,51,62,120, - 30,158,35,113,76,130,176,6,169,45,113,24,166,21,142,209,72,145,198,254,10,99,81,2,206,158,62,73,161,212,65,190, - 208,209,142,45,94,26,249,75,220,140,79,33,219,73,88,63,68,179,17,82,206,185,172,223,181,139,61,163,195,189,27,207, - 93,88,174,161,191,23,198,143,67,252,4,223,24,209,211,108,223,89,95,234,182,181,109,183,110,187,72,247,195,14,240,15, - 87,62,18,82,143,146,159,77,43,160,76,40,101,102,210,203,40,199,177,88,147,42,140,115,46,236,221,243,5,78,76,236, - 225,214,183,252,75,174,190,225,237,68,3,235,121,224,200,215,233,170,62,195,43,86,213,136,230,191,204,179,103,158,161,82, - 190,153,222,225,43,233,91,185,139,243,71,143,80,82,62,137,81,44,198,18,43,211,74,181,163,163,3,173,45,173,86,72, - 62,159,199,109,139,21,151,44,91,93,215,35,81,26,167,13,50,182,237,23,148,198,252,152,246,126,24,228,218,124,80,163, - 209,32,10,35,146,208,208,106,132,184,82,162,154,130,245,235,11,60,253,196,17,124,103,53,184,10,229,184,84,171,115,220, - 126,199,107,56,59,189,215,137,235,139,93,2,74,205,182,47,244,2,47,111,23,76,3,171,219,207,239,111,241,141,246,173, - 255,40,109,144,5,147,104,122,87,47,103,119,111,55,157,247,62,204,194,37,16,122,249,0,100,128,169,70,5,109,52,158, - 16,8,41,150,214,183,144,207,11,249,22,54,193,36,33,97,28,18,26,136,172,67,182,208,65,172,5,159,253,224,231,147, - 252,145,51,81,249,194,68,131,102,43,156,179,194,132,81,8,88,65,162,77,67,39,40,87,234,70,214,167,81,40,120,153, - 238,110,183,212,215,231,169,254,190,172,237,239,247,220,145,97,89,88,214,75,71,111,7,165,124,14,207,53,160,35,146,176, - 133,176,144,81,10,27,133,156,57,126,130,141,219,46,79,31,156,18,24,155,234,31,51,121,31,213,82,216,216,112,104,239, - 1,54,94,185,133,209,177,85,176,126,99,62,60,119,97,181,130,205,85,184,240,255,192,228,8,232,85,237,202,36,79,170, - 247,153,253,46,248,129,165,29,165,107,218,96,246,205,23,79,79,90,113,185,2,10,129,177,185,89,37,164,193,161,16,180, - 208,174,36,214,14,89,215,82,153,57,206,199,255,228,215,56,254,208,125,220,244,182,159,101,195,214,215,177,184,112,45,247, - 159,122,136,13,229,211,108,31,29,103,166,254,73,162,243,67,228,106,147,88,199,208,148,139,120,162,128,105,37,120,74,210, - 217,217,73,198,203,224,56,46,133,66,234,19,20,133,81,202,233,56,146,32,104,145,205,230,47,102,205,107,157,242,63,218, - 24,146,86,3,109,76,234,17,148,205,166,70,102,237,141,251,88,74,106,139,115,120,202,210,242,44,218,10,178,89,201,101, - 59,243,60,189,247,16,61,93,215,80,79,90,116,44,203,112,249,117,155,25,191,115,64,6,231,143,229,114,80,168,131,219, - 1,65,129,151,182,127,190,180,186,28,144,250,119,247,112,209,115,251,31,253,8,32,14,35,114,133,60,111,186,241,90,62, - 122,239,195,232,75,32,244,242,0,40,11,198,206,204,196,81,148,168,76,214,77,53,55,214,182,137,222,182,74,217,10,48, - 49,113,171,133,175,92,58,253,60,25,229,227,10,159,7,247,61,203,194,71,63,95,191,221,154,195,89,216,35,211,106,249, - 31,12,136,108,172,177,113,3,170,13,244,248,148,171,57,216,21,195,64,4,61,11,66,246,93,200,251,69,53,220,159,111, - 140,141,22,114,107,87,120,107,118,108,21,195,171,150,211,219,85,34,136,91,116,151,60,166,43,11,84,234,243,148,139,93, - 232,68,163,149,64,197,22,33,92,158,125,234,9,146,19,231,216,125,224,36,251,190,248,69,198,182,111,167,153,207,58,79, - 192,218,87,10,110,139,45,139,30,220,223,7,115,222,243,218,176,230,119,121,39,13,129,219,72,45,68,119,242,141,230,235, - 30,105,124,143,134,188,128,129,5,207,235,108,42,71,120,90,32,149,34,81,2,97,5,73,96,112,85,1,215,141,217,247, - 244,231,57,120,224,49,118,94,117,19,55,191,254,103,24,89,255,54,206,206,157,224,220,133,167,232,244,142,210,223,125,138, - 145,174,57,114,202,39,104,25,172,87,33,10,22,200,229,11,100,243,57,130,176,133,163,36,158,151,65,8,73,156,196,56, - 110,6,99,37,141,70,64,177,20,130,205,33,109,26,241,19,39,1,137,78,240,253,18,54,106,96,13,132,97,152,106,130, - 28,143,140,231,17,4,33,100,28,162,160,6,139,22,175,100,104,36,62,197,142,60,163,67,49,227,51,135,160,80,96,197, - 134,213,204,84,3,236,64,159,154,131,222,2,140,72,40,253,66,106,24,247,146,193,125,201,210,228,205,252,96,198,244,232, - 36,161,92,200,243,230,27,175,37,119,223,195,44,84,47,129,208,63,0,160,225,111,65,66,251,41,49,104,179,96,250,143, - 159,106,86,166,23,51,197,229,253,34,229,129,12,234,226,186,68,58,148,55,70,147,232,4,37,5,133,124,142,64,39,8, - 44,173,243,231,185,202,154,233,28,220,19,192,23,61,24,247,47,6,0,191,240,157,77,131,106,64,209,131,46,15,122,58, - 172,233,95,85,111,246,36,71,78,245,53,142,156,26,108,222,245,64,255,184,159,29,126,106,221,218,1,239,53,183,248,59, - 111,184,154,213,195,221,148,18,216,247,204,30,174,187,249,150,116,132,172,193,120,30,135,190,254,40,147,79,62,203,168,117, - 136,109,76,56,95,227,236,221,247,49,236,23,196,99,219,119,12,179,111,223,43,110,208,201,100,3,78,159,132,106,247,243, - 110,164,115,237,73,213,119,115,98,210,77,249,183,124,83,27,118,30,232,6,53,9,61,2,70,79,249,217,174,138,78,112, - 19,75,36,93,26,58,65,201,4,132,197,146,128,149,56,190,143,164,202,67,247,126,138,221,123,30,231,234,27,223,200,43, - 110,125,11,254,208,143,48,94,27,231,236,133,103,248,250,222,251,241,243,46,30,5,116,24,145,152,0,215,47,2,6,161, - 68,187,186,209,237,236,120,77,162,227,116,162,169,53,73,152,16,169,22,202,247,144,210,193,90,73,28,181,200,203,12,126, - 156,2,163,177,10,84,134,70,28,227,88,40,228,114,32,114,44,52,4,93,210,210,172,47,162,242,69,106,21,65,71,38, - 203,193,201,167,25,222,122,13,221,197,65,230,206,61,66,105,216,99,143,155,25,92,21,135,235,68,106,198,54,245,157,84, - 11,182,13,54,89,82,239,159,191,36,141,81,250,65,63,113,146,208,93,200,179,251,198,235,232,190,247,33,184,4,66,223, - 8,64,31,248,22,37,164,74,51,183,26,2,170,250,194,249,248,212,83,187,245,200,138,55,56,152,56,229,128,158,95,48, - 11,129,17,130,216,26,60,47,131,206,103,72,26,49,213,48,34,123,252,92,50,10,167,99,120,170,12,251,143,64,237,99, - 60,103,216,245,66,21,195,43,65,172,5,57,148,218,187,122,58,245,141,206,73,33,202,69,107,187,243,48,212,31,180,54, - 13,237,221,123,217,227,135,14,109,121,255,167,191,216,187,235,221,111,146,239,124,237,143,112,126,226,32,179,179,85,122,74, - 101,172,178,60,113,207,3,204,60,248,12,189,137,203,162,14,72,124,23,139,164,208,140,233,118,51,116,92,117,19,95,157, - 154,237,223,49,113,110,99,14,150,73,56,114,20,226,28,255,48,66,247,187,45,203,91,164,30,64,180,43,161,227,41,247, - 211,45,96,163,145,106,237,25,100,222,152,180,183,21,130,52,173,194,74,164,18,196,38,85,121,199,38,65,90,75,62,231, - 19,53,230,248,218,231,254,150,189,143,125,157,181,87,95,207,214,203,110,98,164,176,145,185,74,158,124,182,129,113,154,232, - 208,65,24,151,222,174,62,60,55,131,209,22,235,62,71,154,10,169,48,86,224,42,139,2,148,240,49,38,70,27,23,43, - 20,249,194,16,35,99,221,212,227,41,26,141,42,74,7,100,140,164,228,122,52,99,152,175,213,241,114,57,98,109,137,162, - 38,217,2,56,56,100,45,8,109,153,156,156,166,111,104,25,107,174,184,153,153,185,113,156,224,8,59,95,113,35,95,191, - 255,80,169,126,124,207,72,6,186,207,130,243,63,32,105,188,192,243,109,218,36,115,12,252,27,224,198,246,215,252,83,242, - 130,214,73,66,35,159,227,236,13,215,176,101,223,97,226,83,103,47,45,181,46,1,144,255,173,91,7,13,76,41,56,210, - 169,147,43,206,61,252,104,39,111,125,61,98,105,157,93,152,180,245,18,233,116,74,27,155,218,48,196,26,27,197,248,174, - 143,240,74,20,206,94,168,23,82,223,151,115,171,160,245,44,240,249,239,240,160,124,176,99,160,71,65,111,134,240,46,168, - 29,2,177,222,90,153,128,147,133,156,65,236,206,97,247,223,26,69,215,109,59,124,120,215,23,255,243,255,90,243,191,142, - 158,45,188,225,221,63,198,153,163,103,233,185,246,74,238,253,244,167,169,60,180,155,46,55,71,147,16,47,159,101,106,106, - 156,201,133,89,150,245,13,144,201,56,12,58,25,250,55,110,80,227,19,231,122,214,65,103,5,188,46,104,244,145,106,127, - 158,127,7,254,174,198,180,164,41,132,197,118,235,85,77,63,50,157,176,198,194,245,161,114,214,158,21,194,83,82,32,77, - 106,76,2,169,162,215,216,37,11,1,129,209,237,142,55,106,33,133,164,232,100,104,206,30,229,145,79,61,203,222,47,127, - 148,101,3,43,112,154,51,8,25,99,28,7,43,12,153,124,7,224,209,106,134,228,114,170,29,1,38,241,60,31,19,4, - 109,11,15,133,112,125,66,4,58,49,100,173,139,137,67,74,189,131,172,94,117,3,129,219,160,90,25,167,114,254,12,141, - 241,83,152,218,60,133,172,194,218,132,230,194,28,126,206,197,68,9,113,224,35,203,30,177,142,152,159,169,51,189,80,97, - 227,13,175,39,50,157,248,225,35,244,173,88,77,82,188,6,151,191,17,9,168,12,168,4,196,23,218,213,230,11,157,1, - 224,39,219,191,38,255,68,47,52,155,36,116,231,114,76,189,98,23,149,66,30,111,223,161,75,32,4,56,175,248,22,127, - 81,1,115,4,102,90,112,160,27,206,78,236,217,55,92,175,7,94,54,171,48,70,183,149,207,207,191,83,165,147,176,44, - 138,140,149,148,186,122,120,252,169,103,233,156,156,152,151,112,214,194,236,57,208,111,0,254,11,112,250,59,60,176,165,26, - 107,105,204,58,1,182,3,244,97,208,191,13,225,126,108,173,46,228,116,36,196,153,110,163,79,188,91,39,175,248,218,7, - 62,116,197,99,103,207,117,154,205,91,188,147,251,15,138,234,19,251,88,153,47,19,232,128,40,171,104,85,107,184,40,114, - 217,28,243,205,6,211,181,58,203,178,9,3,67,131,84,148,83,210,58,233,117,33,191,31,22,178,237,187,239,104,187,90, - 89,154,132,137,23,104,13,94,10,225,246,252,11,168,0,69,3,27,4,98,71,75,80,170,72,97,173,54,36,198,166,123, - 113,109,107,18,251,60,204,23,168,212,39,210,154,182,108,161,133,194,82,118,75,216,56,224,216,137,71,232,236,232,99,96, - 96,3,70,70,132,166,198,192,80,47,74,57,24,29,227,58,94,106,28,143,192,104,157,146,200,113,140,149,14,210,86,72, - 140,143,16,121,226,56,34,227,123,24,221,162,94,159,33,215,177,154,129,238,229,244,119,93,65,188,174,194,252,212,41,42, - 211,39,80,139,231,112,231,199,105,53,102,201,72,151,164,161,193,248,160,20,245,230,44,214,19,248,189,35,196,149,3,140, - 22,230,161,112,25,39,78,156,134,179,135,227,66,26,85,168,151,146,80,95,8,128,254,93,58,37,164,183,205,163,253,83, - 142,100,182,198,16,7,17,3,91,54,176,63,159,195,63,116,148,124,165,246,207,58,90,200,121,226,219,0,128,77,187,134, - 51,57,56,161,247,29,216,122,238,240,177,194,134,203,55,162,105,181,151,77,219,190,199,82,34,218,134,89,38,163,136,48, - 36,174,67,50,49,75,95,20,77,27,56,231,67,245,44,216,113,210,176,191,255,240,2,83,161,239,212,194,40,158,139,251, - 217,2,201,39,173,153,217,134,172,205,41,103,194,96,39,110,215,58,56,118,207,253,215,254,233,179,7,6,244,53,55,136, - 45,195,163,84,234,53,50,217,12,213,133,58,253,221,61,248,29,61,244,234,144,90,189,70,208,10,113,98,139,109,181,104, - 10,81,86,176,49,20,98,75,217,90,115,12,90,18,188,30,200,180,65,48,216,14,205,24,162,10,36,175,2,51,198,115, - 49,210,170,61,53,179,223,226,34,81,109,238,98,22,56,75,26,53,61,4,185,0,6,21,182,107,193,245,212,28,86,40, - 209,246,225,65,182,141,226,45,218,166,254,58,142,148,104,169,72,172,193,74,75,98,12,194,26,12,6,35,19,172,107,8, - 165,32,223,223,67,215,96,63,245,202,28,174,3,25,233,18,71,33,174,163,136,194,144,140,159,26,146,213,226,56,117,20, - 48,22,35,211,113,187,140,12,210,19,132,162,69,70,120,120,246,44,3,250,20,241,252,8,85,49,66,226,244,163,253,101, - 184,67,187,24,28,189,28,25,207,19,213,207,241,232,221,159,39,172,30,167,25,79,192,180,71,103,103,9,108,72,84,247, - 200,196,45,138,242,12,34,51,64,192,48,167,15,252,111,26,166,34,4,162,96,176,221,125,224,191,29,90,255,235,155,158, - 179,159,110,243,60,147,252,240,100,193,139,118,75,118,104,213,24,238,216,8,93,135,142,81,46,22,200,122,223,56,15,210, - 198,180,29,37,126,200,1,168,247,219,220,173,207,64,18,195,84,6,142,118,206,207,205,28,190,231,190,222,181,151,111,148, - 26,131,176,18,99,44,82,138,246,226,168,196,85,14,145,23,161,28,69,53,137,48,71,143,7,101,152,146,48,81,131,214, - 191,39,93,59,200,127,15,30,120,210,174,138,214,89,211,186,160,205,169,33,169,108,2,203,234,136,29,215,108,189,92,174, - 29,26,33,10,154,36,36,204,78,204,179,122,221,90,138,217,60,213,122,149,176,217,66,70,134,178,85,224,88,198,122,250, - 216,219,219,159,143,38,206,95,230,166,180,250,122,139,93,48,136,18,216,142,246,150,255,188,129,113,9,51,207,192,220,143, - 64,179,149,238,113,133,203,161,121,103,26,251,99,103,193,22,33,185,21,204,70,176,109,87,1,100,27,132,154,237,22,204, - 73,253,1,18,43,68,224,88,27,238,21,34,179,104,141,202,180,13,121,76,123,186,40,108,90,13,25,44,113,18,131,146, - 23,183,213,109,123,41,216,160,144,196,72,45,17,81,150,206,82,23,157,69,143,218,92,72,62,91,66,99,112,165,67,33, - 151,197,113,93,220,140,135,148,18,173,19,60,215,193,106,75,66,136,84,46,54,17,224,36,68,73,66,98,19,108,220,162, - 39,43,88,53,50,78,61,58,205,212,130,195,228,162,207,108,216,71,160,198,176,249,101,228,186,183,113,213,237,195,60,240, - 241,223,68,196,51,76,78,78,18,199,13,146,160,202,217,83,139,76,29,254,26,195,253,62,13,255,90,166,39,231,184,98, - 213,58,30,184,230,21,153,167,31,184,111,249,21,176,173,14,7,222,10,117,7,226,223,121,222,107,124,45,124,15,13,58, - 126,176,142,27,39,88,4,147,27,215,242,112,108,233,126,228,32,151,111,88,131,20,130,158,142,46,98,223,225,212,112,192, - 234,249,35,63,212,32,228,204,124,7,222,194,135,69,11,135,58,224,232,153,47,126,105,108,226,39,223,92,28,232,43,163, - 19,221,118,62,20,24,99,17,6,114,194,197,58,14,67,165,46,142,213,90,168,233,153,192,75,141,167,102,124,136,127,227, - 121,63,59,7,252,53,112,231,119,113,39,17,192,161,116,34,162,255,212,232,133,6,204,42,41,131,174,108,14,207,90,180, - 209,92,152,155,98,205,242,149,4,58,161,53,59,75,173,81,163,209,168,147,203,231,201,10,197,162,74,200,27,67,180,110, - 149,247,224,236,196,104,167,160,39,31,155,43,124,75,3,172,159,3,207,73,219,176,166,130,57,7,166,61,152,12,82,35, - 179,200,73,53,116,83,37,104,154,212,43,32,114,97,254,38,168,89,72,198,65,151,161,181,3,90,25,72,202,160,175,4, - 179,10,120,28,90,89,107,231,91,82,182,158,208,137,103,164,159,238,102,37,150,68,164,249,92,210,128,86,233,230,191,35, - 36,198,104,210,42,41,5,39,129,76,197,78,137,64,138,182,119,180,142,241,4,20,179,69,60,223,167,22,215,136,147,144, - 56,118,208,198,224,122,30,25,63,131,49,138,36,136,136,194,16,75,130,144,14,117,147,80,84,26,47,80,216,102,72,100, - 251,121,252,252,50,78,214,106,140,20,38,25,235,213,108,236,155,195,154,113,206,205,238,231,196,124,15,83,199,135,201,116, - 108,102,211,150,171,56,183,239,126,84,62,67,103,79,23,171,151,239,224,150,215,102,153,159,158,103,114,188,14,225,97,154, - 11,243,140,150,11,220,246,186,183,115,239,153,211,35,171,206,156,190,170,8,199,5,204,172,129,137,78,176,141,118,165,171, - 190,7,220,91,234,109,109,47,70,87,127,203,246,200,90,164,146,66,57,202,10,243,127,79,194,232,0,115,51,21,166,39, - 22,184,229,202,157,88,11,113,162,193,194,189,59,251,104,57,30,187,118,239,35,225,135,51,167,195,217,245,29,190,224,49, - 104,85,225,120,14,246,116,60,245,244,166,211,247,63,189,110,224,45,183,99,68,170,17,86,58,139,164,133,69,145,144,32, - 133,193,149,30,78,208,192,204,205,68,18,170,57,104,124,1,204,31,180,73,216,165,22,175,249,93,60,240,12,112,21,169, - 10,246,6,96,30,226,24,230,134,140,158,58,120,116,223,134,96,120,84,29,189,48,73,103,95,47,245,86,64,92,173,147, - 247,179,20,10,57,18,155,208,208,33,129,182,104,161,72,170,13,122,123,202,202,125,235,155,74,214,186,229,217,106,125,32, - 142,66,194,74,213,122,81,152,196,54,164,30,104,225,90,73,41,137,66,181,184,216,234,136,194,86,103,28,71,202,232,166, - 50,118,209,215,186,233,98,181,132,64,195,84,11,230,69,10,70,129,133,105,9,51,2,230,151,193,76,4,243,71,161,238, - 131,235,66,102,194,24,47,191,118,141,44,47,44,18,214,235,72,87,33,141,193,152,212,168,40,117,55,209,32,76,123,83, - 61,141,82,150,8,16,169,58,221,74,151,68,26,172,136,17,194,16,39,233,96,160,209,104,97,149,68,138,84,152,105,219, - 62,220,73,18,227,72,213,22,150,90,180,246,208,45,133,173,215,241,125,23,137,33,50,33,94,71,15,197,254,107,145,249, - 14,78,212,207,115,118,122,150,130,188,64,89,158,98,176,212,228,21,131,14,54,57,203,68,235,28,135,91,57,206,61,61, - 207,79,255,244,187,24,29,217,198,211,251,31,97,106,246,12,202,184,108,94,191,138,254,101,99,220,249,217,221,204,197,69, - 70,135,70,217,250,227,255,218,123,248,189,191,179,233,117,213,249,27,170,48,177,6,30,126,4,22,159,1,251,197,231,77, - 12,95,238,49,192,244,194,12,29,29,57,162,56,249,14,0,132,152,24,215,120,158,123,49,125,246,255,246,153,254,166,106, - 192,72,201,167,124,88,238,72,250,18,243,67,211,134,126,51,0,127,219,179,46,37,163,167,66,216,223,209,106,157,62,254, - 55,31,28,91,127,253,43,253,114,159,151,78,188,108,2,2,148,204,160,114,25,162,106,19,167,88,162,88,109,208,129,142, - 73,199,249,118,241,185,201,207,119,38,235,218,15,76,61,239,207,75,21,207,211,192,47,183,63,159,125,30,169,123,11,4, - 121,56,219,1,199,87,46,204,108,123,242,196,190,158,140,246,40,248,89,202,142,34,235,251,104,87,80,181,17,249,21,3, - 12,244,118,210,104,53,177,113,194,220,212,52,51,187,199,185,108,213,70,209,33,60,146,82,55,90,88,132,53,34,177,198, - 109,186,16,4,1,42,189,248,157,32,12,243,73,98,168,36,26,27,37,152,32,180,45,221,50,68,129,201,86,234,177,91, - 173,5,162,82,105,9,173,181,103,146,200,105,52,22,125,99,230,114,48,147,129,211,26,142,135,112,18,33,93,97,205,170, - 9,199,235,222,118,245,53,156,250,210,157,132,214,96,100,90,221,72,1,86,166,147,48,97,212,146,137,118,26,84,36,68, - 154,72,138,76,189,149,72,117,89,54,129,66,182,132,182,130,88,235,116,130,102,64,40,65,156,36,237,148,12,80,66,97, - 116,186,43,39,29,151,196,24,164,8,145,97,140,13,242,180,132,64,197,30,243,139,211,60,244,192,123,217,114,217,13,116, - 140,141,162,115,131,196,238,8,13,189,129,11,211,103,136,142,29,166,171,40,24,27,113,48,245,115,252,220,187,175,103,93, - 95,157,39,30,254,51,194,240,24,219,7,71,169,212,138,28,222,115,132,83,135,87,242,166,31,123,7,95,254,200,71,72, - 14,31,100,96,229,70,46,220,254,134,238,71,63,254,215,87,95,13,115,13,88,240,97,119,3,154,57,190,55,171,20,19, - 139,21,94,123,197,90,74,133,252,119,4,33,99,140,181,63,96,54,171,145,235,112,202,110,162,247,177,125,63,156,45,216, - 99,47,98,124,12,180,20,156,148,112,40,127,255,189,27,14,127,253,254,209,235,222,113,135,208,214,96,149,65,227,165,102, - 244,74,33,132,32,227,123,72,215,33,178,246,37,197,168,23,219,147,142,114,202,63,177,145,84,41,188,240,60,78,224,120, - 155,200,245,248,198,45,243,126,72,234,112,65,195,190,85,179,139,151,77,214,102,186,54,93,245,10,89,12,67,50,170,192, - 140,12,81,197,28,43,55,109,100,104,205,10,156,98,150,32,9,137,130,16,105,45,217,66,47,245,147,19,248,89,72,116, - 11,141,70,234,20,61,77,75,80,148,2,161,99,172,16,20,164,2,207,65,102,221,37,79,52,81,149,90,25,101,149,103, - 133,155,196,113,46,49,150,80,107,148,1,211,10,160,214,52,157,211,211,13,255,236,177,185,176,82,155,30,17,226,168,197, - 84,34,216,220,88,191,161,99,217,134,245,84,63,246,145,84,151,211,54,230,90,138,72,22,214,98,132,2,37,73,255,233, - 212,9,50,137,13,70,75,144,62,74,106,76,18,98,146,152,108,54,67,24,54,137,147,0,65,202,33,105,13,185,108,39, - 90,39,169,17,125,123,9,53,181,47,81,88,19,145,36,9,17,14,81,208,174,146,154,9,73,125,150,82,118,142,112,230, - 62,138,93,43,144,129,68,235,136,196,106,178,217,18,178,184,134,11,245,44,181,51,17,181,70,133,91,54,94,205,35,247, - 222,201,198,177,38,221,197,49,162,102,158,137,164,130,191,90,48,25,87,201,184,176,101,203,229,60,248,137,207,18,52,37, - 35,171,54,240,208,246,237,203,123,247,236,185,126,21,76,159,133,218,74,56,42,32,204,182,227,154,95,46,36,40,128,86, - 204,93,79,29,231,95,253,232,237,20,115,89,162,56,254,118,247,189,31,188,201,153,235,48,151,47,147,60,182,239,135,114, - 90,230,108,126,17,61,116,8,201,65,184,96,16,79,246,52,195,13,39,255,224,247,203,43,175,92,95,30,90,54,132,49, - 25,140,10,145,194,162,28,23,161,28,28,199,165,148,117,201,27,243,146,28,115,239,109,143,98,111,32,221,193,122,8,120, - 42,173,194,184,21,24,35,221,249,249,237,209,110,26,175,216,136,8,82,75,8,41,5,225,125,7,236,225,217,218,124,3, - 246,116,88,246,244,30,62,190,108,124,221,198,190,53,157,157,92,168,205,211,179,125,61,87,223,124,61,110,46,131,113,4, - 185,98,30,71,41,38,206,158,37,14,90,108,186,122,39,31,63,240,33,234,170,68,62,91,0,107,240,4,100,61,135,188, - 54,132,128,201,180,109,72,196,115,153,101,75,30,57,153,216,193,70,6,100,130,239,40,148,77,16,82,146,104,144,221,5, - 220,222,188,76,214,174,47,26,179,181,248,165,135,246,44,47,31,56,180,238,199,9,23,38,161,152,189,102,123,214,201,8, - 194,48,198,207,58,109,240,73,35,101,172,105,71,239,200,4,35,20,82,120,88,171,48,177,192,234,152,56,106,18,199,117, - 50,74,144,207,101,233,44,118,160,148,64,8,155,154,134,197,17,174,114,136,181,161,21,182,200,229,178,40,165,136,162,40, - 181,93,69,16,39,26,147,24,116,18,35,176,233,186,134,147,163,190,88,167,195,87,188,229,103,95,203,192,96,23,113,28, - 34,76,130,52,169,105,153,227,148,153,152,147,124,238,171,123,25,159,126,156,43,182,230,56,118,110,145,226,250,87,17,200, - 83,28,57,118,138,153,133,73,74,125,17,214,134,228,76,68,227,224,103,89,59,186,130,135,74,46,141,184,138,51,221,98, - 195,117,183,136,207,157,155,88,251,115,115,83,183,102,211,61,252,135,214,97,79,91,152,95,132,166,110,143,234,159,95,13, - 191,148,115,102,124,154,63,254,240,157,252,226,91,95,69,169,144,251,118,32,244,131,7,64,34,37,172,127,104,73,232,23, - 3,251,58,29,133,46,14,10,158,54,150,21,157,79,61,51,240,212,95,254,237,198,219,126,227,151,92,55,163,211,241,173, - 112,144,210,65,58,10,157,196,116,117,22,201,186,110,219,98,254,219,191,105,124,82,187,139,92,251,223,242,218,119,175,32, - 29,127,47,145,225,23,99,120,107,195,221,236,126,219,213,100,60,7,225,58,24,207,97,112,172,143,161,223,255,124,184,23, - 142,187,240,240,198,74,107,205,125,7,14,118,30,187,252,106,119,231,245,87,112,245,107,95,133,151,205,165,62,214,66,32, - 76,140,176,130,254,129,33,166,207,157,167,111,69,63,21,23,62,253,241,79,4,87,117,14,76,140,40,213,202,11,37,202, - 25,95,120,70,91,143,36,84,74,218,80,91,217,178,86,33,5,197,40,168,106,173,109,36,85,102,198,58,217,166,116,164, - 201,122,194,31,232,43,228,123,123,138,185,82,103,169,156,119,133,34,65,52,234,216,48,192,201,186,236,220,190,131,207,52, - 131,242,157,23,78,101,87,68,161,94,117,229,14,113,122,110,254,226,126,138,16,92,180,187,16,237,63,91,97,145,210,66, - 146,144,104,77,28,6,228,178,138,109,219,215,176,115,231,6,6,7,250,89,190,124,53,205,38,60,240,192,19,68,113,66, - 20,69,88,107,209,73,154,15,102,109,66,146,164,6,244,105,56,161,67,46,155,199,81,46,129,14,169,213,2,114,37,15, - 43,99,172,208,104,13,141,106,147,122,117,134,164,187,132,49,25,164,128,216,90,4,25,180,245,249,223,239,251,3,62,251, - 165,123,121,219,107,199,24,240,135,137,206,62,192,200,174,215,80,11,86,80,218,182,140,214,228,126,142,31,219,199,80,209, - 208,229,58,76,28,121,152,142,242,28,17,167,56,51,211,203,224,192,24,121,109,96,235,86,255,35,247,126,109,219,59,160, - 80,196,174,183,112,48,134,67,83,105,209,59,57,13,181,24,194,206,151,89,170,92,152,154,227,125,159,248,10,255,242,109, - 175,254,39,7,66,63,212,99,248,229,47,226,139,22,83,222,37,249,5,107,207,157,135,7,59,96,244,204,135,63,222,115, - 244,214,107,135,151,111,94,78,38,223,131,240,28,60,215,195,145,30,49,134,216,106,98,215,83,34,245,20,194,182,57,155, - 111,30,193,215,72,125,148,243,109,82,90,191,192,164,107,137,80,92,250,92,235,169,19,108,253,177,63,97,247,117,235,185, - 80,240,177,203,122,25,60,62,193,44,216,5,88,40,73,113,176,104,236,225,222,61,251,214,53,174,189,105,224,198,31,123, - 39,137,14,48,109,163,117,4,104,41,17,214,160,74,29,248,3,9,65,163,202,174,155,47,35,249,244,167,247,190,101,252, - 100,3,40,170,116,75,221,145,96,36,68,6,90,54,157,110,77,89,88,84,208,20,233,194,68,70,67,46,134,76,12,158, - 62,66,182,226,120,229,179,29,221,195,251,7,7,135,157,161,193,242,178,190,65,183,47,223,75,172,96,172,91,240,234,157, - 235,57,209,95,114,31,218,119,76,252,233,246,157,226,209,15,126,100,137,12,189,152,151,150,122,46,153,52,5,68,184,72, - 35,48,73,72,49,235,242,138,155,174,225,182,219,94,201,166,77,107,40,20,178,104,29,226,120,89,246,236,57,77,24,5, - 68,113,154,59,18,197,26,41,51,8,35,48,164,153,97,126,166,221,138,216,152,40,12,41,20,242,212,91,13,130,88,147, - 49,160,109,4,186,65,172,21,81,51,166,213,146,248,8,116,220,66,40,69,44,92,156,156,207,211,207,62,195,125,15,222, - 69,94,249,100,84,39,121,191,128,27,79,83,158,184,11,71,75,142,78,187,148,70,54,51,58,230,33,22,158,37,8,103, - 48,174,230,208,161,51,172,217,212,65,159,189,158,82,239,54,130,112,158,203,86,95,205,201,181,55,149,255,122,247,23,182, - 118,28,220,189,106,103,189,181,107,53,28,207,194,129,24,14,78,193,97,5,167,47,164,34,209,208,121,25,111,246,241,233, - 121,254,236,19,95,229,23,223,254,42,138,249,236,119,228,132,46,157,255,11,0,52,255,34,191,240,33,160,15,90,87,194, - 65,3,247,14,158,155,26,222,243,71,239,237,44,253,206,111,229,50,190,38,155,45,80,46,101,80,66,18,217,24,183,152, - 71,45,27,245,245,225,227,217,16,252,155,64,190,234,121,165,244,18,152,212,73,85,176,159,123,9,99,85,155,104,114,137, - 102,242,171,123,56,6,76,57,138,13,214,162,64,14,9,242,218,82,114,32,211,165,49,61,235,151,131,202,226,196,97,10, - 131,82,96,219,53,153,149,14,177,213,20,122,122,177,81,196,230,109,91,184,48,50,224,150,78,76,22,45,20,3,48,115, - 105,118,151,246,192,22,192,203,66,38,129,121,224,209,4,206,56,16,9,200,56,80,80,144,247,133,40,88,232,238,76,162, - 193,177,217,137,179,149,217,137,206,211,251,232,61,151,43,244,62,211,213,215,39,58,186,243,163,235,199,252,98,206,119,94, - 185,113,187,200,116,244,184,217,98,153,201,233,185,148,116,54,105,194,136,84,41,63,99,76,140,181,6,87,248,68,97,204, - 202,229,67,252,198,175,255,75,182,108,92,1,54,33,138,18,162,86,12,196,40,233,50,59,51,135,239,231,9,163,6,202, - 241,240,132,106,251,100,91,176,54,245,90,106,171,160,43,149,10,165,82,137,122,195,16,39,1,82,1,184,8,225,96,73, - 147,48,144,138,133,74,19,163,178,104,33,17,38,196,8,129,181,25,190,240,169,123,136,155,10,95,41,102,79,44,128,238, - 161,123,32,198,149,103,136,231,224,194,211,179,68,227,231,89,185,186,159,242,138,141,116,13,140,112,254,244,9,78,79,45, - 32,131,26,29,180,144,241,33,186,202,89,84,255,50,70,54,111,96,230,71,222,236,76,158,61,85,126,232,209,251,202,143, - 60,122,215,242,213,39,246,110,223,105,146,211,157,112,32,129,103,38,96,183,129,83,59,97,177,6,177,247,18,11,162,243, - 211,115,188,255,227,151,64,232,159,204,20,108,233,60,145,146,192,118,21,44,28,21,226,41,215,218,209,206,47,62,52,248, - 212,234,79,109,187,230,23,127,222,169,45,44,96,35,7,71,129,16,22,47,227,209,185,105,75,46,184,235,222,225,2,12, - 20,225,248,40,180,158,239,187,236,1,79,146,202,173,95,108,95,255,66,239,182,237,137,22,245,52,126,106,192,71,108,149, - 214,222,120,24,113,249,131,163,3,93,255,250,218,45,128,64,75,137,37,73,53,52,86,32,177,160,5,170,157,79,223,85, - 238,66,74,151,248,242,29,195,247,156,248,242,254,72,8,119,118,217,80,39,91,55,149,71,134,150,201,206,76,54,62,188, - 119,95,179,116,255,253,23,182,65,103,132,141,52,156,146,80,237,2,49,14,202,3,71,88,155,113,32,167,5,29,210,210, - 215,1,195,87,192,232,21,205,122,223,98,179,222,213,56,127,178,120,240,192,147,189,143,143,173,222,184,113,219,206,206,219, - 55,174,227,238,191,249,36,103,206,78,226,100,50,237,69,223,246,30,152,76,147,79,165,6,75,68,54,47,120,219,219,223, - 72,189,94,101,102,102,134,254,190,94,132,208,224,136,52,58,25,143,241,241,25,164,244,145,78,140,21,85,140,141,144,210, - 18,69,26,99,12,82,42,98,157,16,5,33,66,8,226,56,68,74,129,54,45,170,213,6,249,108,9,95,229,9,194,42, - 74,65,146,68,84,26,139,212,77,3,43,19,124,1,190,155,101,247,238,125,124,245,174,123,208,72,106,113,131,103,15,159, - 226,252,226,38,186,199,58,81,73,196,196,220,34,187,118,173,101,245,152,33,227,183,72,58,60,76,118,136,51,213,5,182, - 223,242,106,238,251,227,15,179,102,125,63,214,137,105,212,22,41,134,103,144,11,130,78,127,3,185,194,50,198,222,244,11, - 52,238,248,113,239,252,222,199,134,62,243,192,157,125,35,123,239,91,179,179,190,176,173,11,182,37,240,164,134,253,187,225, - 108,17,230,55,65,180,159,23,31,113,187,4,66,191,240,182,87,81,42,92,2,161,127,84,0,250,173,23,249,133,173,116, - 212,205,40,232,9,107,199,107,130,7,187,12,253,231,223,251,151,217,71,58,10,235,95,249,83,111,144,141,197,102,26,27, - 44,5,50,134,193,45,235,220,211,66,140,89,107,215,122,176,111,1,90,30,207,173,44,36,237,10,40,251,18,30,240,18, - 80,133,164,41,21,243,160,174,130,114,21,214,10,184,38,177,246,154,61,142,186,108,207,170,141,203,6,174,190,76,14,246, - 244,3,150,216,73,144,218,32,100,6,131,64,137,246,35,176,26,161,65,228,178,20,125,151,107,127,250,39,250,159,90,179, - 166,227,242,237,59,221,205,87,94,33,7,6,250,241,148,2,145,97,174,81,235,254,47,111,253,137,98,249,203,95,93,92, - 14,235,76,90,13,86,130,174,156,126,56,159,73,134,39,170,97,54,209,205,94,168,248,150,201,4,142,251,144,55,208,165, - 5,253,121,33,6,242,198,142,45,179,108,89,125,230,76,240,145,102,115,235,202,222,219,123,243,139,117,250,154,77,78,233, - 136,166,35,145,56,68,113,219,78,22,137,84,6,99,45,90,27,86,173,92,201,232,112,7,199,142,31,96,177,209,162,191, - 103,144,114,49,135,213,17,137,129,153,233,89,194,216,67,71,154,160,25,163,117,76,34,99,4,14,142,82,132,65,11,107, - 92,28,71,96,180,69,107,75,146,88,28,233,225,170,136,66,206,39,104,52,83,123,85,44,73,28,179,48,211,64,73,69, - 147,26,245,106,130,176,17,7,142,28,229,45,239,124,35,171,214,174,38,95,40,208,221,81,102,213,202,110,30,127,226,107, - 116,84,78,179,110,101,142,19,167,78,81,77,178,116,14,150,168,31,127,132,19,39,190,192,230,155,111,227,177,199,31,230, - 83,159,123,128,119,47,191,149,238,145,45,212,235,17,65,116,146,188,62,75,71,253,36,121,14,80,173,116,18,184,27,88, - 189,227,54,130,237,183,58,11,103,158,233,125,234,177,207,117,116,223,251,197,209,229,11,211,91,123,96,127,2,79,207,195, - 211,111,134,83,175,72,205,79,227,23,107,195,122,126,122,142,247,125,252,43,252,203,183,191,250,18,8,253,99,2,208,111, - 191,20,77,66,27,136,28,104,97,57,28,193,151,70,19,237,156,248,159,127,168,30,42,103,215,94,251,250,183,136,168,122, - 6,27,43,84,162,232,218,190,220,185,176,105,213,160,222,127,124,125,219,246,116,166,10,250,239,218,213,79,22,216,192,119, - 182,86,48,237,15,153,2,160,152,6,25,167,252,76,126,27,244,44,194,38,7,174,31,151,188,242,220,192,200,202,198,142, - 173,165,155,70,134,193,8,62,255,39,31,226,186,55,188,154,245,87,109,66,219,24,107,52,162,157,154,97,37,88,43,81, - 70,98,173,68,72,197,77,183,190,138,155,110,123,109,38,93,116,139,176,198,164,22,22,38,160,59,239,243,250,255,248,43, - 29,119,223,119,223,192,170,86,184,50,132,21,37,152,94,86,240,26,215,254,206,91,57,114,190,198,226,175,127,212,58,25, - 87,111,74,52,43,180,73,230,33,248,40,44,92,111,57,171,172,205,70,136,161,38,200,85,54,46,141,9,102,14,206,84, - 122,175,236,233,228,45,219,119,176,122,120,144,175,29,220,195,133,153,69,140,147,5,41,177,73,76,36,99,148,200,98,2, - 203,201,99,167,184,238,154,215,176,108,85,63,205,0,142,31,62,199,252,220,34,35,195,125,4,65,68,101,113,30,215,45, - 179,56,191,136,159,201,17,71,146,70,163,74,198,151,248,25,159,68,71,88,155,32,132,135,231,101,136,99,112,28,31,97, - 20,229,130,139,235,89,164,155,38,126,26,12,94,198,101,97,174,202,212,133,26,142,239,208,217,53,72,177,84,226,95,239, - 188,140,92,71,169,189,165,223,78,26,181,146,7,190,250,36,193,66,200,232,96,204,230,245,203,153,89,116,104,212,170,68, - 97,139,93,215,92,201,195,15,31,226,191,253,225,167,89,140,28,238,255,242,39,120,203,143,175,162,232,119,81,149,155,168, - 216,117,212,90,169,101,71,201,158,98,212,59,77,101,106,15,161,222,66,121,232,42,226,119,110,119,155,55,189,97,240,209, - 251,239,238,203,220,243,169,53,151,205,143,111,238,130,13,9,60,213,5,71,3,56,223,130,249,22,132,241,139,0,162,241, - 153,121,222,251,137,175,240,115,111,185,149,174,66,238,82,202,233,63,6,0,245,190,140,111,10,129,255,15,170,151,195,238, - 10,176,170,169,197,233,255,244,135,60,214,146,107,118,188,253,102,105,91,85,130,160,2,133,50,133,55,189,161,103,126,255, - 239,109,40,192,218,105,56,243,21,88,252,111,237,159,147,5,254,15,208,249,45,52,28,73,123,244,222,9,162,9,238,83, - 224,143,65,105,10,186,61,232,3,134,93,88,101,96,203,161,156,191,109,239,154,13,99,219,215,95,38,70,50,9,173,184, - 142,107,50,20,206,204,241,224,255,249,48,65,229,141,108,191,237,26,52,139,168,56,1,229,161,201,34,173,196,72,137,176, - 81,106,178,166,117,59,58,90,96,81,72,233,32,150,242,233,117,194,117,87,95,197,3,183,221,56,52,243,185,175,12,118, - 10,54,212,45,199,15,159,93,12,30,251,47,159,215,255,106,253,16,191,1,140,253,250,79,51,246,181,199,40,61,178,151, - 66,250,248,205,221,16,174,135,112,25,214,137,97,110,26,244,181,63,254,182,242,132,163,168,157,153,32,235,101,217,62,180, - 140,85,195,203,248,155,175,125,153,163,11,149,180,66,145,16,11,137,65,35,177,92,56,63,142,137,13,97,208,164,92,234, - 229,198,155,174,103,252,252,105,46,156,63,207,137,35,231,168,53,91,148,74,5,114,121,143,86,171,73,18,71,120,202,69, - 181,165,157,158,155,199,203,164,177,58,73,172,145,42,38,8,234,100,28,15,199,247,136,146,16,17,164,137,24,253,189,125, - 108,218,124,5,235,214,173,160,111,176,135,98,169,132,114,220,52,230,89,199,36,173,58,66,73,140,86,168,140,225,228,193, - 11,220,249,247,15,115,235,149,189,140,207,88,38,38,103,240,179,89,100,70,160,114,61,124,242,238,125,124,232,131,79,17, - 219,60,142,155,240,212,83,95,100,126,113,130,155,110,254,49,150,173,186,145,200,207,18,20,251,72,138,61,232,214,10,26, - 245,167,41,101,46,48,160,38,89,152,57,78,203,221,72,166,107,35,234,45,219,85,237,230,55,247,62,250,192,103,58,7, - 191,242,209,209,85,243,211,59,58,224,176,128,61,6,246,238,131,147,62,204,119,180,239,109,223,110,247,112,106,122,158,123, - 190,254,36,111,127,235,109,196,65,240,131,55,134,151,75,130,211,31,82,0,122,185,126,199,191,10,246,189,80,217,6,207, - 84,128,229,141,186,158,252,205,255,126,243,151,159,217,179,110,251,123,126,202,31,30,44,18,53,91,148,111,186,193,187,240, - 55,31,93,95,56,123,97,151,134,99,151,195,193,253,16,149,219,163,245,163,164,118,120,226,121,31,103,64,172,2,121,1, - 252,13,144,143,82,109,98,95,19,134,29,88,230,195,88,13,70,23,97,240,28,12,76,45,27,232,17,107,175,204,245,101, - 186,168,207,46,226,118,65,156,5,145,40,10,194,195,209,154,167,62,254,85,148,231,177,229,198,109,152,164,133,21,46,137, - 214,120,74,99,117,64,101,126,30,41,92,202,93,253,128,131,69,182,251,61,139,21,150,176,85,33,137,19,10,221,195,236, - 250,137,31,237,57,240,185,175,12,189,2,177,198,40,177,34,214,102,241,213,199,38,235,61,199,38,77,2,12,61,190,15, - 198,103,196,49,144,66,8,222,97,173,249,20,216,38,72,3,29,64,127,0,114,213,101,59,212,198,177,17,190,246,251,127, - 198,154,142,110,116,28,208,159,205,241,234,203,118,113,246,174,47,147,56,30,194,58,56,66,18,91,131,116,4,71,143,29, - 199,154,52,251,188,85,171,34,112,25,89,53,198,208,178,101,140,173,88,164,220,55,200,163,143,62,205,161,67,7,169,54, - 230,112,132,67,198,201,18,39,49,186,73,154,124,42,36,142,43,144,74,160,140,193,10,77,98,18,58,187,58,89,179,110, - 5,155,54,111,100,205,186,181,12,13,15,145,205,57,24,27,166,22,32,6,76,146,164,105,35,78,123,173,195,182,141,234, - 85,7,239,253,203,223,224,169,19,71,40,117,110,228,240,196,113,150,173,42,49,49,222,224,236,217,179,52,131,152,179,147, - 139,44,38,77,148,235,33,181,79,87,214,99,252,228,147,124,224,240,1,54,111,121,45,175,188,253,205,116,47,91,142,113, - 61,34,53,74,152,93,206,108,120,6,79,239,102,48,123,148,188,152,226,216,228,50,146,194,46,74,29,235,176,111,251,101, - 167,250,138,59,70,239,187,251,115,195,197,175,126,120,227,206,122,101,103,55,236,9,225,225,8,30,219,2,167,239,132,240, - 150,111,83,101,91,32,115,248,36,79,62,186,151,61,219,214,254,192,105,110,172,182,120,113,130,211,158,16,255,176,97,145, - 243,114,191,177,9,252,28,216,223,129,234,245,240,76,12,97,95,146,204,21,62,249,185,27,158,120,122,239,142,158,159,121, - 91,207,21,119,220,72,255,166,85,28,124,215,219,6,103,255,251,31,94,221,13,251,59,224,194,126,152,105,144,138,11,51, - 41,143,195,29,224,132,224,27,200,157,132,156,16,162,179,0,35,218,218,81,23,70,66,24,173,193,232,108,70,13,85,151, - 143,118,71,27,54,20,135,175,186,194,221,184,124,132,43,202,30,95,255,139,123,161,101,209,229,60,117,211,164,172,125,92, - 153,37,16,146,216,9,232,52,134,7,63,242,25,138,3,93,44,91,191,10,27,7,184,142,38,104,85,169,77,77,18,6, - 45,84,38,71,161,88,66,122,105,59,102,1,132,33,104,86,153,60,119,18,147,64,20,132,92,121,237,101,242,145,203,86, - 13,5,79,159,24,113,16,87,186,66,196,85,107,199,31,135,202,27,160,89,252,202,35,145,0,91,149,82,72,229,48,26, - 71,252,120,74,184,103,67,88,225,192,242,102,111,79,103,207,142,77,157,29,253,253,68,158,143,49,150,68,1,73,200,246, - 101,99,108,26,26,100,247,248,56,158,244,17,86,146,88,141,116,28,206,157,31,103,97,190,194,208,96,153,90,163,73,117, - 113,14,227,196,116,116,245,48,48,54,200,107,86,142,113,203,107,111,229,217,189,123,121,240,222,251,121,248,193,71,153,56, - 63,133,148,30,57,183,128,227,42,194,168,65,173,17,226,251,14,125,125,93,172,90,179,156,173,91,183,177,117,219,22,134, - 151,13,166,182,171,198,16,235,132,80,71,169,37,172,77,121,162,116,12,105,177,54,245,132,178,6,92,47,195,158,199,143, - 241,249,79,61,194,181,175,249,121,250,10,27,89,49,154,165,48,178,154,199,38,79,240,245,103,31,192,77,36,82,101,80, - 94,54,141,36,180,13,50,142,207,112,255,86,140,8,153,158,188,155,143,188,255,62,198,86,92,201,229,55,188,145,225,245, - 151,33,61,151,68,46,71,139,229,28,174,236,161,211,28,98,77,247,121,102,91,179,204,206,174,193,45,109,39,91,90,71, - 231,143,254,170,92,188,229,142,222,175,124,254,131,221,93,119,127,113,213,85,113,99,101,1,74,49,124,169,4,167,247,131, - 254,78,237,152,186,247,9,214,61,178,7,97,127,0,5,209,75,202,248,31,70,0,250,249,31,187,227,101,127,115,40,4, - 227,90,219,229,159,189,183,50,219,10,247,84,97,222,135,115,219,79,158,62,53,254,159,254,215,229,15,127,242,139,171,86, - 190,243,71,75,249,85,171,229,190,130,191,188,175,30,12,7,144,149,164,194,195,129,182,14,104,64,144,47,35,70,98,107, - 215,74,88,150,129,158,196,218,254,58,140,205,73,70,167,187,75,189,254,214,141,197,190,107,175,202,110,189,254,58,57,184, - 97,61,157,93,93,228,60,15,18,77,117,110,150,51,219,78,179,247,177,253,100,108,142,156,91,38,12,99,84,70,226,34, - 8,181,65,139,58,185,88,242,200,231,191,194,200,202,159,69,217,144,96,161,202,92,181,78,88,115,112,165,196,198,81,218, - 178,184,217,54,87,4,104,77,88,91,64,154,4,172,96,126,250,2,163,203,71,89,249,230,215,246,237,121,250,143,187,175, - 210,102,27,208,237,192,116,11,38,59,225,212,28,156,171,192,124,193,152,16,27,155,12,216,115,32,26,208,225,195,234,16, - 58,162,203,118,12,12,44,31,201,0,204,218,132,185,249,10,29,253,69,140,78,200,36,17,55,239,184,156,221,231,63,77, - 228,104,18,43,48,214,128,181,44,86,235,156,60,115,129,161,129,14,226,32,2,5,149,185,84,76,209,217,219,143,142,35, - 28,79,114,249,149,219,185,226,202,29,252,196,79,253,24,251,246,28,224,137,199,158,230,240,225,163,8,145,142,224,215,174, - 219,201,43,175,191,150,117,27,214,208,211,221,129,200,120,96,53,38,14,208,137,69,27,1,66,33,80,32,36,66,164,27, - 249,105,46,156,68,155,36,213,39,161,48,49,188,247,15,255,128,53,27,174,99,243,85,111,34,23,204,176,125,85,7,103, - 90,189,108,191,106,43,123,239,251,56,81,165,65,44,45,218,196,16,249,184,210,16,198,85,170,181,2,93,221,157,108,223, - 178,21,76,194,249,201,3,220,245,201,67,44,95,249,74,118,92,119,7,157,99,43,9,173,193,235,221,202,124,180,146,218, - 236,110,86,230,206,177,206,123,154,201,197,25,234,254,86,156,100,140,114,223,213,116,253,202,118,121,250,85,111,239,250,240, - 159,254,215,87,190,227,216,222,74,25,14,206,193,248,209,212,219,233,219,15,55,180,70,54,91,63,144,23,169,37,221,16, - 216,244,188,63,255,176,0,145,243,59,191,246,238,151,255,221,74,98,90,17,61,119,63,206,211,173,176,57,11,39,214,193, - 124,0,39,70,44,123,226,221,7,118,46,238,254,205,205,161,159,233,93,158,36,167,53,92,80,16,68,164,251,92,127,159, - 246,231,170,19,49,96,148,122,85,148,232,91,166,50,238,234,70,95,87,201,27,91,150,203,237,220,84,232,189,242,106,247, - 170,237,155,233,31,91,70,33,95,64,160,177,38,65,199,49,81,171,133,43,28,10,249,78,174,184,126,23,123,158,217,71, - 216,140,73,132,139,41,42,78,76,143,179,170,220,75,81,56,52,109,64,62,91,96,238,228,9,230,206,156,162,80,204,80, - 169,212,121,252,201,61,124,240,125,127,205,205,175,190,142,119,253,228,59,8,91,33,174,159,180,125,28,52,205,197,69,90, - 243,139,88,29,162,227,244,197,159,157,156,224,182,55,189,195,255,223,79,28,219,250,245,3,7,123,152,158,93,219,91,173, - 47,174,176,204,101,96,82,192,73,13,135,106,112,2,107,103,14,64,115,17,148,11,125,2,198,166,17,197,145,87,189,106, - 48,167,28,180,209,204,218,128,189,19,11,220,177,236,10,154,245,5,194,176,197,182,21,43,184,122,205,58,30,56,121,140, - 68,185,169,233,153,84,4,81,200,161,163,39,184,250,170,205,184,78,10,14,214,66,101,118,22,79,42,114,165,46,180,128, - 132,4,97,45,221,125,93,220,248,170,91,185,254,230,155,105,181,26,24,157,0,134,92,161,128,114,50,64,132,77,52,38, - 137,48,86,35,5,40,71,130,78,9,122,179,148,45,212,78,154,21,50,181,106,148,86,97,181,197,205,149,249,226,167,238, - 228,171,247,220,207,143,189,231,15,241,187,122,112,170,83,152,150,192,196,9,157,221,253,244,116,140,50,62,127,20,199,1, - 45,35,146,88,224,186,89,92,229,210,106,213,152,153,75,144,86,179,124,120,140,203,119,172,38,138,66,90,213,89,206,237, - 254,40,97,243,42,220,225,109,248,189,61,72,153,195,25,188,141,115,141,115,148,155,79,49,82,154,160,170,90,76,235,38, - 51,147,5,230,239,188,11,142,236,182,203,42,139,13,9,201,210,82,243,146,31,211,203,145,120,188,148,243,188,148,170,212, - 120,236,123,120,161,54,72,227,190,151,28,58,127,104,42,160,197,234,119,97,122,32,37,34,140,232,49,150,67,41,113,28, - 119,192,244,2,84,90,112,202,194,238,14,88,39,130,176,23,152,116,225,169,24,42,187,218,252,79,51,125,98,101,221,218, - 222,86,146,92,190,251,230,235,111,189,252,103,127,212,95,121,229,101,116,118,15,80,46,22,17,184,24,83,131,216,98,194, - 6,70,91,148,148,72,161,144,210,96,116,140,112,44,107,215,175,99,120,120,132,202,153,89,180,74,149,136,98,237,0,182, - 179,135,218,145,11,20,157,28,74,11,178,70,179,255,177,61,100,55,174,226,11,239,255,115,90,159,248,66,243,109,245,32, - 56,60,61,145,63,123,219,171,51,43,150,151,83,235,83,37,105,213,106,212,230,22,176,173,16,107,12,2,7,169,52,97, - 88,161,103,112,132,255,250,145,191,235,90,172,78,117,77,78,76,177,239,254,251,147,175,126,226,51,11,165,221,7,207,111, - 105,197,43,251,97,163,129,19,9,28,158,128,83,82,136,166,180,118,5,208,51,49,48,210,189,245,149,215,148,209,49,74, - 41,138,197,28,143,157,121,140,27,47,187,140,92,38,75,37,105,209,211,108,242,214,43,94,193,222,11,231,168,4,17,24, - 139,81,2,141,228,196,153,51,233,84,80,72,28,41,72,140,1,163,89,24,159,34,9,5,229,254,126,140,6,173,99,140, - 8,81,34,53,148,205,102,51,72,229,97,173,198,152,8,171,147,182,177,25,96,28,4,10,33,52,90,167,213,158,20,96, - 218,161,201,194,62,39,180,177,88,148,80,8,165,8,170,1,127,249,23,31,76,35,169,29,135,140,205,97,18,7,215,19, - 184,40,92,153,165,123,104,152,83,103,159,197,87,5,164,236,68,136,0,76,66,18,122,40,207,18,199,77,90,58,199,248, - 220,4,129,182,148,187,202,20,250,124,60,71,160,226,99,36,103,26,52,167,71,233,27,217,4,57,65,208,53,68,93,189, - 158,227,115,251,25,245,206,112,244,145,255,195,153,15,223,213,124,91,99,97,124,8,78,231,225,104,4,79,184,112,170,148, - 210,129,47,171,98,88,2,18,251,188,95,29,210,165,105,219,150,144,44,217,201,214,158,167,103,211,237,143,239,213,70,255, - 210,73,248,70,7,136,127,214,28,208,11,189,88,178,141,206,165,116,80,54,25,192,124,8,199,28,200,218,244,115,149,63, - 133,232,227,41,127,196,111,183,65,8,33,68,108,173,51,186,125,179,115,213,107,95,77,78,129,112,92,146,184,137,49,18, - 169,34,148,178,88,157,65,57,233,2,37,218,193,160,17,78,130,49,6,183,203,163,88,234,164,170,23,201,40,135,34,1, - 117,163,25,216,186,134,163,231,39,232,52,30,74,122,148,242,125,124,237,107,15,17,253,201,159,52,55,62,125,224,244,6, - 56,225,128,245,79,78,108,56,116,247,189,171,150,253,226,207,72,176,152,48,160,58,63,67,43,104,34,19,129,81,14,70, - 217,246,210,173,67,125,113,138,98,169,72,127,95,137,254,254,78,182,109,223,225,220,246,227,111,239,125,228,254,71,122,159, - 253,212,157,43,159,249,234,189,23,54,207,45,142,142,192,186,12,92,136,173,157,5,70,34,40,231,118,236,40,143,109,89, - 35,34,211,196,35,139,239,120,156,91,152,227,240,228,4,87,141,142,225,196,17,213,102,157,145,114,47,55,172,219,204,157, - 187,159,190,184,21,47,5,28,60,116,156,133,169,10,185,140,160,110,67,132,54,233,135,99,89,152,157,34,182,49,221,3, - 253,8,52,173,122,19,37,21,158,239,35,165,194,232,180,181,82,202,37,165,59,20,194,166,246,159,82,24,76,210,74,237, - 91,93,63,37,151,133,76,173,65,5,36,54,193,36,9,74,42,172,80,72,191,192,61,95,254,18,207,236,222,67,222,207, - 227,187,14,82,104,10,94,157,130,235,96,19,23,233,186,116,116,14,225,56,30,142,167,176,198,65,138,12,218,36,88,101, - 16,142,192,34,152,157,95,192,40,15,47,170,147,143,93,172,22,24,207,67,10,69,193,153,71,133,211,156,157,216,143,59, - 186,158,190,213,155,241,115,93,36,93,59,152,138,214,51,123,236,110,251,182,198,194,248,6,184,43,128,251,66,56,161,96, - 162,158,190,255,146,59,190,139,247,181,253,38,16,58,3,124,186,125,225,188,166,77,110,223,73,234,91,253,76,27,116,30, - 2,238,227,59,135,47,188,220,51,7,140,243,226,133,151,255,44,0,232,155,79,41,181,38,13,247,66,232,183,53,68,69, - 224,179,237,23,115,24,120,36,5,44,83,178,118,174,12,7,131,63,122,255,225,207,52,170,27,95,249,175,126,70,118,142, - 173,32,235,58,184,145,70,203,24,227,104,192,199,42,131,197,32,172,147,218,149,138,4,240,208,54,193,70,17,69,199,197, - 203,88,20,2,89,151,228,189,94,26,165,18,83,173,152,250,226,52,227,251,247,210,119,112,207,244,174,106,229,41,15,30, - 138,5,207,198,144,235,181,188,250,244,103,191,208,177,248,99,111,237,45,120,14,213,233,243,52,26,243,196,26,92,225,161, - 188,12,210,245,168,86,99,76,61,166,191,71,81,89,152,160,220,55,64,98,21,150,26,189,93,157,188,225,77,111,225,142, - 55,190,174,124,232,208,193,242,189,31,248,208,216,222,79,126,121,124,228,236,248,248,58,107,23,59,64,237,67,248,157,175, - 188,118,56,239,186,196,129,1,109,176,137,197,10,151,251,14,29,96,219,200,74,50,218,33,116,35,22,27,243,220,180,97, - 51,15,31,57,200,124,162,209,113,140,231,42,46,156,155,228,194,133,25,214,172,30,36,177,49,174,21,40,229,146,96,16, - 34,161,190,56,131,181,33,221,125,253,228,114,89,234,245,26,65,101,145,92,62,139,235,151,16,202,193,46,205,118,69,234, - 21,36,226,144,168,89,37,136,106,56,158,2,161,176,184,32,228,115,222,223,74,34,176,200,118,66,71,210,108,242,129,15, - 252,13,6,131,192,69,57,89,116,70,227,183,170,248,202,96,148,139,245,36,57,183,128,175,114,228,242,89,146,40,33,8, - 44,202,85,196,196,248,94,9,37,37,36,134,176,90,37,204,250,84,106,46,197,66,9,98,8,26,53,180,235,145,205,100, - 240,11,45,42,23,30,101,234,248,179,228,122,70,217,120,229,245,20,186,6,88,179,122,7,254,189,127,63,23,193,83,45, - 184,127,57,204,45,19,66,127,170,220,203,121,225,80,196,126,203,41,152,32,245,87,202,72,73,40,21,179,97,131,147,213, - 89,222,3,124,0,184,11,248,125,210,72,160,159,109,87,58,191,218,254,222,190,118,107,244,239,128,155,219,85,79,208,6, - 136,137,239,227,69,219,221,6,186,195,237,235,42,119,9,128,190,69,135,246,60,17,225,82,170,68,0,188,11,248,205,246, - 215,156,1,115,6,38,98,184,175,79,27,191,242,103,127,55,243,208,157,95,91,165,110,191,165,47,127,245,102,127,100,245, - 58,58,70,87,146,207,57,148,221,58,94,94,98,93,23,171,12,18,9,70,128,91,96,113,186,78,208,168,50,176,58,79, - 44,66,166,106,57,166,171,13,62,252,135,127,106,221,163,251,155,43,26,141,122,179,177,104,182,199,102,122,165,225,233,8, - 190,14,60,222,99,153,88,128,162,6,213,247,204,225,222,163,255,237,79,110,244,254,159,127,87,8,91,53,112,50,248,126, - 129,102,173,202,196,161,99,236,254,234,67,230,192,35,123,76,77,9,249,147,191,253,107,114,231,101,27,113,43,53,242,229, - 158,84,200,168,53,134,58,174,48,108,219,184,142,173,255,223,255,155,63,255,171,239,89,243,213,143,125,110,249,103,62,244, - 145,41,177,239,208,244,179,153,226,240,239,95,127,117,65,64,234,241,99,36,65,173,137,167,60,158,61,127,138,199,78,29, - 225,218,21,43,73,154,243,52,77,72,87,161,155,235,86,175,229,179,207,238,70,41,31,7,65,16,180,56,53,51,193,198, - 205,99,228,27,49,218,21,88,145,178,30,70,91,48,134,218,252,34,58,140,233,27,25,166,80,42,209,168,24,154,139,45, - 16,33,126,54,79,198,207,130,84,104,44,113,28,17,53,234,36,65,19,235,8,156,76,14,161,60,140,21,237,8,238,118, - 44,135,84,8,44,24,139,116,61,238,185,251,30,158,120,236,9,164,204,32,165,32,155,207,32,20,41,32,73,11,86,227, - 56,2,63,171,200,100,28,162,40,198,36,186,189,100,107,137,163,152,197,133,5,114,126,22,207,245,48,81,196,252,252,2, - 185,124,158,90,189,138,239,250,56,174,131,18,1,45,233,226,185,46,130,132,110,223,229,193,187,63,196,23,62,255,127,184, - 229,77,239,166,35,174,165,51,17,168,10,168,127,26,244,96,255,24,79,245,175,16,70,27,123,252,133,232,75,33,136,132, - 130,36,194,181,150,3,213,89,94,101,18,46,36,14,127,14,188,17,56,72,234,69,21,183,39,181,223,188,44,189,20,70, - 240,173,184,160,239,231,201,2,203,219,143,173,126,9,128,94,26,65,119,152,52,217,50,76,117,64,118,11,212,119,192,179, - 139,80,45,195,254,142,243,147,155,26,127,249,161,13,115,127,197,202,135,123,75,253,193,198,45,101,59,208,159,17,29,174, - 83,30,232,35,55,188,140,114,247,32,94,28,81,244,5,34,59,192,193,67,167,56,126,244,0,141,146,203,236,252,130,205, - 29,57,95,95,57,63,55,181,78,71,147,131,105,16,197,148,132,170,77,237,82,15,145,146,196,179,247,130,190,28,130,34, - 60,174,160,167,250,55,31,41,63,45,212,21,93,111,185,53,27,5,33,167,31,123,218,94,248,250,61,65,241,240,201,249, - 177,122,60,190,25,154,53,232,120,242,151,127,125,153,255,191,254,123,199,166,87,94,43,164,93,32,147,247,16,202,69,10, - 23,99,85,59,23,62,97,120,176,151,127,241,43,191,232,206,252,204,59,71,190,242,229,123,71,234,95,249,58,179,211,19, - 212,23,150,81,236,44,145,4,9,245,70,3,148,131,80,138,47,237,126,130,109,163,99,100,29,159,36,105,161,116,204,173, - 219,118,240,236,133,115,140,87,234,40,41,8,195,144,233,249,25,172,35,200,40,73,160,4,137,146,88,29,227,41,7,172, - 192,2,173,90,157,233,11,227,244,13,15,81,236,236,38,172,212,168,86,22,152,175,84,210,197,87,44,137,209,32,5,210, - 88,60,199,161,88,236,38,155,43,160,73,3,28,219,126,176,96,117,250,103,210,120,25,41,21,79,60,254,20,81,148,224, - 184,25,132,84,72,7,144,22,215,19,64,130,78,82,71,183,32,108,17,197,17,142,147,73,237,65,180,190,104,186,6,16, - 132,1,58,73,200,21,10,212,27,117,102,103,102,25,28,24,68,72,65,38,147,65,74,73,20,4,216,36,0,82,23,131, - 171,175,216,204,71,62,243,73,123,240,247,126,253,194,45,94,166,208,137,136,19,172,206,183,51,198,102,162,144,215,75,41, - 173,49,198,55,198,10,251,141,224,51,23,54,217,216,92,224,125,115,147,252,86,28,114,167,73,216,108,45,3,207,123,159, - 186,207,187,145,62,159,19,250,65,57,75,2,94,143,139,41,54,151,0,232,197,32,247,147,237,143,165,243,46,176,59,161, - 218,7,135,154,112,182,9,207,248,176,108,196,176,98,217,84,117,5,83,15,143,54,160,187,9,158,150,66,170,82,209,9, - 189,140,87,211,113,113,206,147,185,8,71,121,113,28,220,22,132,11,34,136,26,142,53,81,65,155,105,7,14,39,112,50, - 134,243,110,90,25,55,27,208,234,128,186,128,214,211,96,63,6,60,0,250,55,97,60,17,226,254,162,181,170,241,215,127, - 59,113,242,99,31,31,115,132,16,157,141,86,109,5,204,122,112,74,167,9,203,181,28,140,244,93,152,190,242,200,207,191, - 231,242,125,111,123,195,178,235,126,226,93,106,205,154,49,92,39,64,100,36,42,159,65,74,175,221,96,42,172,209,244,229, - 242,252,196,219,222,193,59,223,240,22,158,121,244,81,190,252,185,59,89,190,97,37,171,214,108,32,182,233,174,87,94,249, - 140,207,47,178,255,220,5,174,26,25,193,177,9,149,70,147,114,161,196,91,174,185,129,191,248,234,151,48,194,144,203,120, - 140,12,244,19,155,4,199,145,100,28,149,242,52,142,147,2,134,49,36,73,130,227,186,52,235,117,198,207,158,161,119,112, - 132,76,103,39,29,74,48,55,53,65,18,181,82,133,183,214,88,11,137,177,168,92,14,199,203,130,112,48,86,98,72,23, - 139,133,181,169,159,52,169,1,155,148,233,37,153,36,73,10,8,72,252,76,150,66,190,72,83,202,118,76,147,32,142,45, - 81,108,72,76,186,221,239,186,46,73,148,18,239,82,74,146,36,193,247,125,76,146,198,122,87,106,21,138,249,34,139,11, - 139,20,139,69,242,185,2,90,27,28,199,197,201,8,130,184,129,235,150,105,180,52,190,245,184,124,199,21,162,246,232,3, - 185,245,173,74,171,19,188,6,244,199,208,251,223,32,122,255,252,68,156,205,20,116,165,123,72,202,48,178,66,63,55,188, - 86,82,49,93,91,224,134,233,227,68,223,52,85,250,167,120,17,119,0,215,180,129,200,254,19,251,63,56,63,8,15,66, - 183,251,218,61,16,91,88,92,9,213,6,156,179,176,55,130,14,13,189,121,40,21,193,193,88,97,23,171,66,67,78,66, - 183,133,46,1,142,72,189,202,38,85,106,92,21,3,139,81,58,18,159,143,160,53,15,73,23,152,22,169,195,98,134,116, - 195,127,233,109,57,11,81,100,237,241,30,168,249,176,119,172,25,244,164,77,7,45,155,38,131,76,59,48,23,65,104,161, - 75,194,241,13,245,214,153,217,191,254,232,149,15,126,229,222,245,15,223,126,71,247,142,183,222,33,215,109,26,65,84,18, - 28,39,75,54,87,38,147,205,164,182,111,66,160,77,21,28,151,93,215,95,199,182,203,183,112,230,252,25,246,29,220,71, - 161,51,143,209,17,113,93,35,4,60,116,228,0,155,187,251,192,64,236,74,162,86,139,109,67,163,236,88,177,146,39,78, - 30,98,229,216,8,91,214,175,79,39,227,158,32,231,102,144,198,208,50,26,29,155,116,148,174,210,216,29,132,32,168,55, - 24,191,112,158,254,225,81,114,165,18,157,194,80,153,153,78,101,12,142,3,198,16,145,128,235,226,120,89,180,85,169,143, - 180,48,169,254,199,74,108,234,68,157,166,112,96,0,69,127,255,0,74,165,127,151,36,22,99,12,142,114,240,51,30,142, - 82,40,149,69,57,62,249,66,23,202,113,241,51,25,146,40,38,12,195,52,231,204,113,112,92,23,225,56,132,129,197,74, - 73,179,213,36,155,201,50,63,63,79,33,95,164,179,195,35,73,18,188,140,143,227,103,8,2,131,163,4,73,43,98,197, - 224,50,38,95,125,91,215,251,238,127,40,249,209,249,133,100,23,220,146,128,73,224,193,159,131,211,155,38,79,4,159,136, - 154,230,129,242,16,195,78,6,169,35,148,77,249,65,7,251,79,18,108,190,213,185,177,253,235,103,191,203,106,104,105,216, - 249,66,64,102,127,88,1,104,105,130,22,181,127,63,0,230,35,208,250,21,104,77,164,137,170,103,22,83,253,172,176,109, - 240,112,193,77,192,183,144,117,64,68,16,89,104,212,32,30,2,83,77,61,124,226,205,96,159,4,142,181,53,20,29,47, - 80,70,183,109,103,109,111,90,29,157,109,193,164,3,174,74,57,0,109,32,9,32,89,3,166,15,56,11,141,22,84,18, - 56,219,3,7,123,199,39,47,155,248,171,191,222,246,196,103,63,181,102,239,107,95,213,179,253,45,175,87,171,55,172,32, - 9,38,168,26,131,159,41,146,237,200,33,10,185,118,230,87,140,231,43,214,174,91,199,202,213,154,237,235,54,242,166,55, - 190,158,143,124,232,99,60,249,212,51,236,62,190,159,67,43,86,177,105,108,25,113,220,34,1,188,48,224,214,157,59,57, - 120,234,16,171,215,172,96,160,167,11,97,3,80,18,225,56,120,198,160,181,67,100,108,58,209,146,138,36,138,145,164,173, - 85,24,71,204,205,78,147,205,46,35,83,44,211,227,231,169,204,205,210,172,86,17,90,227,229,114,148,251,250,17,78,134, - 37,27,75,113,241,109,151,86,57,75,138,104,107,210,102,172,88,204,97,109,130,209,18,207,243,200,102,51,52,37,40,9, - 81,20,34,133,139,69,80,234,236,70,58,138,56,138,200,102,179,196,113,140,214,26,165,84,90,169,73,121,145,23,66,164, - 45,89,28,197,76,76,142,35,133,160,84,42,209,106,74,6,6,71,72,10,1,34,8,136,234,17,141,36,98,120,120,136, - 210,27,223,236,220,249,236,177,209,35,7,158,44,190,182,217,236,44,65,201,194,125,231,172,57,54,54,119,161,22,55,107, - 118,117,190,155,185,234,36,65,18,179,81,8,250,237,15,103,202,196,171,219,215,199,233,151,43,237,187,245,38,138,115,243, - 204,61,179,7,233,121,208,174,16,83,45,149,133,40,38,250,30,78,224,156,31,196,39,209,182,201,106,128,65,176,14,68, - 127,0,252,113,187,133,115,129,63,7,70,160,50,3,236,39,141,232,185,162,253,241,31,219,147,1,159,139,33,128,223,192, - 65,125,43,194,220,1,150,129,249,91,8,126,25,2,213,254,89,91,128,25,210,165,198,101,109,128,44,195,226,126,216,31, - 195,249,24,158,29,130,77,195,115,149,157,83,127,251,137,29,207,124,254,171,107,142,190,225,182,158,245,111,125,181,187,114, - 205,90,146,102,196,66,117,1,145,115,201,117,116,145,45,150,144,202,193,152,8,33,160,163,167,200,237,111,126,45,55,189, - 238,102,14,238,63,194,103,62,246,247,156,219,189,159,245,118,8,33,12,137,128,40,106,177,186,187,135,203,86,172,98,221, - 230,245,120,133,44,178,25,33,148,2,165,80,66,224,42,23,235,88,172,11,113,172,193,145,8,157,102,139,121,74,224,9, - 145,146,192,158,143,113,93,202,67,163,100,59,155,136,56,193,201,122,8,199,35,209,2,229,40,140,142,145,194,166,244,15, - 50,245,38,146,22,97,204,197,59,97,162,99,44,38,181,246,48,49,25,79,160,51,18,209,212,40,149,250,25,107,12,185, - 114,9,39,227,161,16,184,174,139,159,205,18,180,90,237,133,216,24,199,203,224,56,110,186,110,34,36,81,16,81,169,86, - 208,70,51,206,56,153,140,143,239,101,9,234,77,108,62,38,215,161,40,117,15,147,13,13,141,100,134,142,216,208,187,235, - 26,198,215,45,239,248,204,163,143,94,251,234,19,71,11,253,208,23,192,215,250,97,207,191,105,85,231,163,86,213,24,224, - 66,251,117,206,192,15,85,5,180,116,252,246,175,43,218,215,5,75,96,241,29,226,33,230,129,207,190,230,86,110,253,139, - 247,49,98,52,221,83,147,56,174,228,136,84,56,24,6,50,62,61,129,166,231,175,62,72,183,16,20,30,120,152,137,103, - 246,124,67,48,196,203,105,0,157,127,10,79,234,82,117,212,106,127,44,69,52,47,137,190,158,4,150,50,238,159,31,106, - 247,114,9,195,214,243,166,27,75,158,212,223,172,164,205,167,178,130,56,134,153,69,88,172,192,25,23,246,245,192,83,125, - 11,149,203,170,31,248,228,246,103,63,245,149,181,123,126,228,166,190,45,239,120,131,179,105,229,106,104,105,42,141,73,234, - 153,25,242,133,34,133,114,23,210,247,1,131,214,45,148,35,216,190,125,19,59,118,94,193,189,95,254,60,207,254,221,157, - 44,235,236,69,39,9,6,77,220,108,240,218,107,175,167,123,243,102,18,29,227,96,113,164,72,163,119,132,197,113,21,82, - 186,237,40,30,131,20,14,38,1,109,45,153,124,129,82,87,55,202,203,96,68,59,198,71,72,220,108,17,149,181,152,196, - 64,34,80,210,1,13,66,56,128,193,202,84,246,96,76,123,13,67,210,142,39,2,180,69,161,210,93,181,56,162,90,173, - 224,245,141,162,45,8,71,161,172,73,205,253,51,89,92,225,145,241,4,198,164,36,112,54,227,35,164,160,22,133,88,171, - 83,0,138,116,218,24,73,136,147,152,102,171,73,146,36,184,174,199,208,192,32,218,196,100,101,142,108,174,68,100,13,89, - 223,163,51,59,12,197,132,70,165,197,138,158,126,146,183,190,205,127,108,207,158,203,183,220,125,87,231,170,36,234,76,160, - 83,194,83,29,48,62,10,225,89,248,161,143,59,94,58,183,181,193,231,2,16,89,251,130,23,251,125,82,242,176,82,124, - 162,148,101,199,96,31,119,36,9,228,124,252,229,203,16,210,50,166,20,214,106,132,227,177,44,219,193,178,63,122,47,18, - 139,174,207,209,251,145,143,193,227,79,131,235,96,58,74,72,235,178,99,235,14,68,154,197,242,195,3,64,223,170,109,19, - 63,0,143,193,73,249,171,216,135,217,10,84,26,112,46,3,251,243,240,244,182,106,237,138,234,135,62,119,213,163,247,62, - 177,254,203,183,221,80,188,254,213,55,137,213,43,135,41,169,12,141,185,57,26,243,21,178,29,93,100,59,75,72,191,136, - 72,210,84,83,237,86,185,252,134,87,240,236,87,31,198,54,83,99,144,136,4,17,135,20,115,5,162,201,121,154,11,117, - 148,167,41,229,178,184,74,97,132,64,184,18,29,130,39,37,74,164,36,178,245,124,188,108,150,76,190,3,161,92,172,0, - 217,22,52,98,116,170,243,65,180,45,72,12,2,157,42,193,5,88,155,90,146,24,97,48,50,13,128,182,109,112,19,104, - 50,25,15,129,197,65,129,181,212,155,17,101,45,209,56,88,233,226,181,127,180,151,201,82,200,228,136,117,3,207,241,176, - 94,134,168,221,134,229,50,62,137,142,241,114,57,18,99,8,195,16,107,45,9,9,142,118,112,179,46,51,115,211,56,174, - 162,175,175,15,89,149,68,42,71,190,3,176,17,210,228,32,235,210,211,81,38,104,54,169,87,155,100,174,187,81,29,237, - 237,91,179,248,249,191,207,111,173,84,251,124,24,136,224,129,81,56,57,2,141,14,48,179,255,12,128,40,211,254,117,117, - 179,69,156,36,212,129,74,251,243,79,9,201,111,43,197,61,158,67,36,21,125,82,226,39,58,29,98,104,131,49,49,82, - 66,164,12,214,106,60,35,48,42,4,66,116,146,96,149,160,244,51,255,130,235,127,238,23,136,177,36,214,66,163,194,143, - 190,253,29,92,121,197,46,126,235,143,222,135,251,183,31,33,8,130,111,107,56,232,112,233,124,79,42,180,98,90,21,197, - 13,152,173,67,197,131,115,49,28,47,66,227,138,241,137,210,39,246,61,187,218,121,251,155,157,125,199,78,225,74,24,234, - 235,101,100,104,144,122,101,145,74,109,145,66,161,76,161,80,70,102,60,84,226,82,204,22,216,120,227,149,156,251,194,61, - 116,228,92,76,168,49,86,18,88,141,188,48,203,252,133,41,250,215,14,97,17,184,25,15,35,210,85,136,200,137,16,82, - 224,23,20,210,113,17,174,151,110,246,91,121,209,58,35,69,151,54,202,144,122,69,199,34,37,129,211,225,187,70,152,246, - 215,90,213,94,64,77,37,123,50,141,64,73,199,191,89,47,101,229,148,33,140,99,180,38,21,132,90,157,2,149,149,96, - 28,130,40,68,155,164,29,145,108,200,23,10,56,97,72,181,90,197,245,50,72,157,78,200,60,99,169,215,235,88,107,113, - 93,151,32,10,48,85,131,159,241,89,88,88,160,84,42,145,113,61,230,231,231,112,28,69,169,92,38,136,67,92,225,18, - 134,17,126,33,79,38,87,32,12,66,202,155,54,139,153,129,158,225,123,62,253,247,165,93,39,78,246,116,194,64,19,30, - 184,10,246,1,51,42,29,120,252,80,182,97,255,144,211,176,108,8,163,116,170,9,156,22,146,91,51,62,139,58,161,0, - 20,172,109,79,2,237,139,191,243,106,131,105,214,254,1,23,100,162,128,213,171,86,242,193,247,255,41,51,191,244,139,204, - 252,241,251,89,248,224,71,49,173,214,11,254,116,121,9,62,190,55,156,149,38,85,10,23,149,100,205,166,149,113,73,136, - 57,13,39,45,156,93,180,4,87,190,242,122,110,121,213,237,220,241,250,55,179,126,199,229,156,188,48,197,157,95,185,155, - 19,39,207,32,173,67,115,113,158,11,103,142,48,57,113,154,160,50,139,9,106,92,126,227,117,168,190,46,90,145,193,117, - 50,104,12,218,104,220,70,200,153,61,7,73,34,77,173,25,208,10,99,164,116,177,66,225,248,57,220,124,17,167,88,66, - 100,243,224,100,48,109,127,35,33,213,18,149,136,21,162,93,253,144,122,69,27,129,163,21,50,17,105,116,128,85,96,28, - 172,149,169,49,91,170,45,111,127,127,250,125,133,114,39,94,214,71,170,52,220,208,117,60,16,26,217,38,128,116,148,160, - 112,81,174,194,113,20,74,41,92,215,37,12,3,132,16,248,190,79,171,149,110,80,105,109,240,50,25,124,223,191,248,152, - 16,208,10,90,196,73,76,162,19,78,159,60,197,252,252,60,97,24,50,55,55,71,189,94,187,168,101,74,172,166,21,70, - 169,239,134,114,80,40,58,186,250,112,223,245,19,197,7,111,190,113,215,241,76,230,45,46,252,152,129,87,39,176,106,13, - 100,71,254,9,143,222,95,238,141,114,137,182,72,218,124,145,252,62,92,11,81,24,98,26,139,244,174,89,197,150,247,255, - 111,86,61,121,63,215,255,236,187,209,126,134,228,155,8,236,75,0,244,61,122,97,11,215,110,165,244,23,191,65,199,215, - 223,199,201,95,251,9,62,150,246,220,158,128,210,98,185,84,216,250,186,219,157,184,85,35,142,99,70,71,151,243,198,183, - 189,157,91,94,243,90,38,166,23,248,179,63,255,32,71,14,159,38,235,23,48,113,200,212,212,89,230,166,206,209,89,42, - 50,118,249,118,154,77,141,171,124,12,224,68,26,7,48,243,77,206,236,63,65,189,209,98,110,122,134,185,137,105,130,70, - 11,199,91,90,56,109,3,133,77,39,88,130,52,27,222,144,242,48,73,219,15,218,146,170,168,149,213,56,58,74,53,63, - 8,18,36,186,237,196,8,233,254,151,112,74,224,116,32,156,34,80,64,73,31,109,210,189,48,99,192,26,141,181,6,163, - 65,73,23,136,48,218,146,201,102,113,92,15,209,254,58,99,82,49,98,46,151,67,169,148,173,75,18,141,53,134,142,142, - 14,178,217,180,104,183,198,162,28,69,43,108,17,4,45,140,78,56,119,246,44,73,146,10,25,167,166,166,9,131,16,129, - 68,73,7,137,32,10,67,28,169,80,66,225,58,25,58,243,157,12,189,246,77,238,161,159,250,233,181,247,12,15,189,166, - 9,239,116,224,13,30,108,207,64,231,111,129,204,241,195,181,224,249,98,222,175,223,111,225,162,5,116,16,18,53,42,244, - 175,91,205,235,254,252,253,44,127,226,126,214,252,234,191,161,176,115,219,69,224,185,212,130,125,23,199,180,73,234,210,255, - 243,47,136,223,118,43,145,54,184,74,17,158,28,103,52,213,16,117,88,24,74,6,122,74,67,107,87,96,226,38,160,136, - 162,22,17,134,193,193,1,182,110,187,156,255,241,187,239,229,243,159,189,155,155,110,122,5,175,187,227,70,214,108,94,65, - 216,106,82,57,119,150,45,187,182,49,241,240,51,152,200,226,40,133,147,24,34,215,144,23,25,78,61,117,16,191,183,3, - 183,84,32,50,1,97,16,208,170,53,200,117,116,224,186,30,202,115,145,34,165,211,141,16,8,156,116,149,130,148,7,18, - 194,164,122,31,218,58,37,82,165,143,112,188,20,112,144,128,70,7,13,230,102,43,60,187,247,49,142,28,57,194,209,19, - 199,169,84,106,28,61,122,146,102,43,193,207,56,56,42,105,147,214,138,32,0,147,104,92,39,65,8,75,161,80,166,88, - 238,32,8,26,120,153,12,82,73,226,40,194,113,20,229,114,153,106,181,138,209,134,140,239,224,121,30,97,54,36,73,146, - 139,130,71,173,53,213,106,21,155,203,33,149,195,233,51,167,88,189,106,53,126,214,103,97,110,17,37,93,84,94,161,28, - 7,19,39,32,13,158,227,166,109,32,22,153,24,134,215,110,161,241,158,213,93,247,126,225,179,215,238,120,248,161,238,101, - 214,14,68,112,207,182,212,76,111,250,42,184,100,75,255,253,186,78,130,144,136,144,242,250,53,116,254,254,239,99,103,39, - 248,179,233,169,75,0,244,114,80,253,249,228,119,63,233,86,242,248,31,124,20,241,135,31,7,173,113,114,25,114,198,178, - 28,60,3,253,17,12,251,91,54,229,187,123,186,48,205,22,105,60,160,193,145,134,218,194,34,73,28,80,44,148,56,120, - 232,60,31,254,232,151,248,252,231,190,196,101,215,109,227,71,223,248,35,92,181,115,39,133,129,46,198,46,95,207,249,199, - 14,162,146,20,40,194,56,198,119,125,50,145,160,118,118,150,161,237,61,196,113,11,172,165,58,59,75,109,126,17,229,58, - 160,210,145,186,163,36,142,151,69,121,62,158,231,225,185,46,74,201,148,10,34,181,221,176,34,109,205,194,102,131,218,204, - 2,23,206,79,50,49,62,207,131,143,238,225,200,177,115,140,79,157,231,212,233,99,52,90,1,202,73,223,54,89,63,79, - 46,87,194,81,146,40,10,8,227,38,89,225,130,200,131,53,56,78,68,146,52,241,157,44,158,235,163,164,68,88,112,149, - 11,14,184,142,139,231,198,116,118,116,210,106,181,112,164,67,208,12,40,20,10,180,90,45,146,36,65,41,133,227,56,68, - 97,72,144,196,20,50,30,245,122,141,169,169,41,186,186,123,8,90,49,70,27,250,7,7,241,179,89,50,94,134,56,12, - 193,88,50,153,12,74,57,36,38,70,9,129,151,47,211,241,174,127,225,31,94,187,97,235,236,39,63,214,185,165,86,237, - 143,161,95,192,67,255,17,206,84,161,53,115,233,109,254,253,3,162,48,194,132,115,80,200,210,95,94,117,9,128,94,44, - 223,182,84,170,6,221,69,196,181,27,80,218,48,215,126,242,150,3,178,61,61,144,142,195,212,147,199,152,157,175,16,64, - 193,194,138,166,80,203,54,189,243,237,57,229,56,36,66,97,173,69,160,81,54,66,135,117,226,86,29,19,69,224,68,72, - 33,169,198,134,175,220,245,8,143,221,187,155,107,175,187,154,55,191,237,181,108,217,188,138,153,195,231,17,115,53,66,98, - 76,148,208,116,35,138,110,142,233,125,39,176,89,65,71,119,145,156,155,33,227,103,81,66,96,226,136,56,136,16,114,73, - 152,232,34,165,139,227,56,184,109,0,114,92,23,99,12,65,24,50,55,49,201,204,169,227,212,166,78,227,235,136,142,174, - 46,170,147,1,31,252,139,191,162,34,11,72,71,225,59,138,124,161,204,115,121,209,32,132,38,142,66,130,32,100,97,113, - 154,14,20,88,31,33,13,158,151,106,132,48,144,201,228,176,218,16,133,17,174,235,144,245,211,132,184,180,210,18,248,126, - 22,185,180,162,17,37,20,75,69,106,213,218,197,10,72,72,73,20,199,52,91,45,178,94,150,233,233,105,124,207,167,80, - 44,209,108,212,153,153,158,97,96,100,20,33,52,94,198,67,34,72,116,132,148,160,156,20,132,132,176,136,80,179,252,154, - 235,229,252,216,138,177,199,255,238,3,165,45,199,143,246,20,161,59,134,251,11,112,120,13,84,138,96,47,5,55,127,31, - 79,162,73,18,141,231,94,2,160,23,77,48,119,237,92,5,63,125,11,167,119,172,34,142,147,23,236,159,109,62,71,249, - 61,127,65,117,166,34,61,232,49,176,198,172,95,55,180,252,218,43,68,208,172,3,42,157,120,91,129,213,22,97,4,7, - 14,28,228,252,249,115,56,174,0,155,96,145,248,210,39,136,52,95,186,231,94,238,185,255,126,110,186,237,149,12,121,89, - 174,232,30,196,183,224,8,65,172,35,60,153,26,238,139,4,142,61,245,8,61,158,143,182,2,63,159,167,216,221,135,223, - 145,238,118,57,202,65,154,42,96,48,66,210,136,19,90,173,58,173,234,34,73,216,162,90,93,32,151,132,12,122,134,53, - 195,14,121,175,139,76,161,72,166,152,167,171,203,39,138,29,132,80,8,173,211,165,84,155,198,246,8,33,104,181,90,100, - 188,12,66,89,154,149,25,60,4,161,1,33,124,242,66,96,100,3,39,155,101,100,120,37,231,78,61,75,43,104,144,203, - 117,147,196,26,207,115,201,248,89,130,86,61,53,63,75,12,89,223,167,218,38,151,93,215,33,142,19,176,233,106,137,144, - 146,48,12,241,253,44,26,195,249,137,243,140,58,203,144,74,176,88,153,71,184,146,238,238,30,100,46,135,146,50,173,180, - 68,186,80,155,113,61,12,26,35,32,105,54,233,30,24,70,255,187,95,239,220,247,137,15,95,179,242,235,247,116,13,192, - 64,12,95,237,135,167,223,7,115,185,84,164,112,233,124,159,207,37,0,250,78,0,84,206,177,242,55,223,78,97,199,42, - 28,11,241,124,125,105,10,253,15,201,61,33,57,143,37,1,47,3,195,13,88,237,92,113,69,103,174,171,19,130,26,200, - 182,157,131,117,8,91,134,56,178,8,225,18,90,139,176,94,234,179,108,19,12,49,214,1,215,129,88,107,190,252,149,251, - 209,38,130,155,111,229,142,181,27,104,132,53,116,20,17,37,13,172,7,11,103,166,216,212,157,165,91,47,18,197,134,160, - 57,195,98,237,60,21,105,137,98,1,26,242,158,70,235,24,132,196,24,131,82,208,145,243,232,202,185,100,59,193,179,46, - 33,9,129,114,208,78,30,145,43,19,213,27,36,42,139,138,45,74,90,180,1,99,82,0,18,237,134,84,107,67,172,45, - 174,155,65,68,33,34,73,136,84,145,122,224,80,84,6,109,2,2,58,200,229,251,200,250,62,142,227,226,58,146,172,159, - 67,39,233,184,189,213,170,147,203,103,169,87,91,180,146,136,124,190,192,212,204,20,65,216,74,205,207,172,33,227,186,196, - 90,163,141,165,25,180,200,250,62,137,73,24,31,63,207,200,208,8,249,98,129,218,226,44,185,172,143,82,233,22,189,178, - 110,10,100,66,181,157,52,221,116,191,77,9,162,48,0,41,232,121,231,187,114,199,135,134,183,206,125,226,227,229,245,81, - 152,159,7,103,5,60,81,134,185,16,180,250,103,52,37,187,4,64,63,128,199,91,49,64,199,174,245,80,105,164,201,16, - 124,139,119,164,35,241,166,23,217,120,126,134,253,144,179,48,90,135,145,149,175,185,53,231,180,219,47,41,82,247,63,105, - 53,166,109,73,225,251,62,153,76,134,40,1,41,69,106,229,209,206,113,183,128,163,20,56,18,18,143,71,158,221,203,174, - 177,21,120,128,107,72,205,200,200,112,238,248,105,114,45,232,89,110,41,120,154,66,162,233,83,146,4,151,216,180,72,226, - 4,69,38,37,161,29,133,227,121,233,191,101,12,88,13,137,37,116,125,76,174,3,223,203,144,241,114,248,249,2,181,230, - 34,97,164,177,194,71,155,182,72,13,153,122,253,8,145,114,58,194,162,117,128,235,100,105,181,2,162,56,192,136,50,21, - 221,192,247,52,106,209,18,75,129,240,179,32,60,194,168,65,54,107,113,148,68,39,169,124,192,81,30,113,148,144,205,101, - 169,84,43,184,142,147,90,223,11,73,28,199,72,41,105,180,90,169,37,145,76,249,32,107,12,25,207,35,20,33,179,243, - 179,105,101,41,139,84,22,22,112,29,7,87,185,36,50,78,167,45,142,69,74,217,110,69,83,98,91,202,116,89,55,170, - 69,244,188,226,6,103,118,112,112,213,254,15,126,192,221,50,53,237,89,40,238,134,39,94,7,231,207,64,216,184,116,25, - 92,2,160,127,12,242,199,2,255,225,240,57,242,111,255,159,237,139,239,219,16,108,2,8,18,78,44,212,132,73,55,244, - 87,200,177,177,190,161,93,59,132,14,67,116,98,176,194,34,164,66,0,113,156,198,221,44,44,204,147,196,26,219,94,198, - 20,136,180,221,17,6,172,192,24,11,66,227,8,135,179,115,21,158,188,112,134,155,150,175,34,14,170,24,9,42,148,12, - 100,75,28,57,126,150,229,43,150,83,246,154,248,82,35,66,11,73,130,114,219,91,238,90,161,68,146,122,60,199,33,56, - 14,82,57,168,92,1,215,203,64,182,76,156,205,164,73,176,6,66,147,86,79,218,90,148,112,144,82,161,173,69,24,157, - 174,122,0,190,239,183,219,81,75,172,35,170,139,85,220,36,194,201,100,72,156,14,90,97,3,234,211,148,186,7,137,202, - 125,8,225,97,76,189,29,131,220,194,115,51,24,99,145,56,180,90,1,253,3,93,56,142,75,165,86,193,115,93,162,56, - 68,170,244,249,114,93,151,36,73,136,227,228,226,90,147,163,20,158,239,81,169,84,112,84,202,109,37,218,32,133,32,231, - 231,8,140,65,250,105,84,184,54,26,199,49,40,153,142,253,149,82,24,107,80,66,160,91,1,229,101,43,136,126,254,95, - 143,238,251,240,7,95,189,230,196,241,238,28,244,41,184,127,59,156,116,160,230,94,42,132,46,1,208,247,227,44,245,249, - 9,233,242,36,22,116,71,158,241,31,185,138,133,235,55,227,198,9,147,201,119,96,3,60,23,142,156,103,230,247,63,67, - 0,153,44,140,6,176,62,185,106,87,111,247,72,31,81,216,192,81,109,245,133,0,163,53,73,28,33,133,192,243,188,246, - 184,184,13,64,162,173,57,54,242,121,44,84,170,157,49,74,114,215,222,103,184,106,120,57,217,172,143,209,9,194,104,178, - 34,131,34,203,185,169,144,174,117,62,166,217,66,198,2,233,132,184,133,44,20,58,49,38,3,218,34,173,70,74,129,227, - 185,72,223,71,171,12,137,148,36,194,1,225,96,69,130,32,6,41,169,214,154,52,234,77,92,223,193,42,7,129,76,221, - 17,17,8,37,72,18,147,106,114,172,70,11,77,117,161,134,215,168,113,228,232,126,190,254,236,125,76,157,59,77,148,127, - 146,155,239,248,89,250,139,5,138,197,50,177,142,136,162,0,172,37,151,203,131,149,228,243,121,130,32,32,10,67,186,58, - 59,152,157,157,65,199,49,38,142,113,189,12,113,18,183,129,39,125,129,172,16,88,1,65,20,81,173,215,112,149,199,204, - 236,44,66,64,185,212,193,92,98,112,28,143,193,193,65,162,56,253,191,248,89,15,129,65,72,69,18,235,139,45,115,90, - 57,41,140,209,200,254,97,17,254,155,95,233,127,236,99,31,190,113,211,99,143,116,15,64,95,8,247,70,176,231,231,97, - 190,4,102,242,18,102,92,2,160,239,25,25,15,108,219,181,142,205,221,69,186,194,152,226,80,23,211,55,108,225,102,207, - 101,98,160,19,25,166,214,3,223,241,248,30,162,210,196,79,127,102,65,192,170,10,172,236,186,225,218,172,227,8,116,144, - 182,46,44,45,142,26,67,18,133,56,40,58,203,29,233,218,65,156,70,1,89,107,177,86,60,103,79,1,233,132,77,10, - 140,167,56,51,53,205,67,135,14,242,234,203,47,35,172,46,160,140,129,48,98,89,103,63,11,103,23,176,43,251,16,109, - 19,121,169,66,12,46,153,108,23,38,155,71,27,131,176,26,129,193,96,137,218,160,107,149,192,90,147,250,157,144,238,132, - 105,35,105,133,49,219,119,172,231,192,193,99,180,106,6,63,151,79,125,161,69,42,102,140,163,4,221,230,86,98,27,179, - 103,239,93,76,157,58,196,98,165,130,146,154,108,214,165,57,255,56,159,252,192,89,150,13,172,38,138,82,71,71,219,222, - 130,15,154,1,126,54,143,16,130,124,46,155,146,197,94,134,124,46,143,49,154,140,231,81,15,154,44,9,31,4,224,184, - 46,218,104,162,56,198,247,50,52,27,77,188,76,170,251,153,155,155,195,113,92,148,227,50,55,59,75,119,119,55,89,149, - 218,128,184,142,76,247,221,108,2,66,166,147,53,241,60,208,23,2,27,71,184,142,67,199,187,127,42,255,100,111,239,229, - 43,239,252,92,215,6,75,111,29,242,235,224,201,16,102,22,190,117,200,234,165,115,9,128,94,26,248,12,116,21,248,87, - 255,225,141,172,29,234,166,22,167,187,74,54,78,24,176,22,147,68,47,108,248,251,2,39,171,44,247,43,203,33,16,111, - 132,206,22,172,136,203,229,222,101,87,110,151,54,142,192,36,8,153,102,179,99,83,151,108,107,12,70,8,252,76,106,69, - 33,180,65,182,243,183,82,140,50,207,245,130,128,181,26,109,64,185,89,30,56,122,152,171,182,110,199,117,92,116,28,99, - 147,24,215,117,209,161,195,190,3,211,236,220,186,130,36,94,76,147,37,52,196,205,4,229,45,201,12,219,252,146,53,41, - 207,34,117,234,120,212,254,207,10,36,72,197,108,181,198,186,45,59,248,236,47,254,42,15,125,253,1,62,243,233,47,240, - 200,227,79,48,61,61,155,174,116,136,244,255,35,69,186,160,42,5,196,225,44,211,179,139,248,170,140,159,45,147,201,58, - 100,85,1,226,26,141,234,73,10,165,30,226,8,48,26,107,192,38,134,70,189,134,21,6,173,99,114,126,17,41,4,171, - 86,172,224,232,177,163,132,73,8,22,60,207,5,225,98,77,250,28,104,163,145,66,16,132,1,25,207,35,142,99,178,126, - 26,63,61,61,61,157,182,139,90,115,226,216,49,70,199,198,200,102,179,40,41,200,249,153,246,243,107,47,62,183,66,164, - 196,186,84,2,48,8,99,241,129,177,215,254,136,123,168,92,88,155,124,226,19,222,246,40,206,135,105,248,228,195,155,224, - 204,187,33,248,219,75,216,113,9,128,190,11,122,135,0,216,91,206,241,200,131,251,137,155,209,119,178,75,249,246,252,143, - 171,40,158,159,227,149,224,52,83,151,198,97,239,138,171,59,70,214,175,33,138,67,162,168,69,198,207,97,172,139,144,2, - 99,211,181,3,229,58,184,174,131,148,18,41,68,106,99,33,190,177,245,122,110,196,102,112,141,69,187,25,206,87,170,60, - 121,248,48,183,108,221,66,171,85,1,13,73,20,147,203,229,56,121,230,12,189,3,29,12,150,2,164,78,64,91,76,80, - 195,77,124,28,79,97,52,88,218,91,241,8,208,54,213,199,72,129,65,128,112,81,46,44,212,22,232,90,182,21,63,231, - 115,251,235,110,231,213,175,186,133,147,103,79,243,133,59,191,194,103,63,115,39,199,143,159,161,217,76,87,63,148,235,34, - 99,133,75,142,76,33,143,167,92,60,199,193,87,25,28,89,194,45,130,227,8,114,25,129,117,115,52,72,39,128,74,57, - 100,125,15,35,98,36,26,109,210,231,37,155,203,210,221,213,197,133,201,113,148,146,132,73,76,20,133,40,169,144,202,185, - 8,32,66,136,180,146,65,18,4,1,74,130,14,2,38,38,38,88,54,186,140,36,78,24,191,112,129,174,238,238,148,195, - 91,106,251,218,207,174,49,9,82,181,95,15,13,74,9,176,2,97,65,132,17,91,110,184,77,44,244,12,44,123,252,175, - 254,50,187,177,86,237,85,80,94,132,175,254,71,56,161,33,108,94,154,144,93,2,160,151,123,44,176,239,212,52,242,143, - 238,252,174,109,25,52,80,78,171,170,172,132,145,89,88,230,222,112,77,33,155,245,9,170,77,116,16,33,179,37,44,2, - 71,74,130,56,73,167,96,206,243,114,167,236,18,215,163,17,66,126,67,11,38,132,196,8,77,198,74,180,21,68,158,195, - 151,119,63,197,229,171,86,83,114,50,52,117,147,172,85,96,4,29,165,97,246,236,57,67,247,53,35,228,141,64,146,16, - 55,154,104,55,192,233,44,145,40,23,35,36,82,39,8,97,144,10,72,156,212,149,82,25,12,160,173,75,66,134,124,169, - 64,28,199,24,18,164,53,172,94,179,138,95,249,15,255,150,119,255,228,187,120,248,225,71,249,216,71,63,197,3,247,63, - 68,171,213,32,227,122,196,65,72,98,193,235,44,180,195,84,61,148,35,200,248,46,249,98,145,140,159,37,12,2,124,64, - 219,0,233,74,164,74,53,62,249,206,78,226,150,65,152,84,39,53,56,52,196,236,252,28,205,48,160,157,74,125,177,130, - 115,29,7,173,77,10,28,214,98,140,166,86,171,226,103,92,242,249,18,205,48,96,110,97,30,41,211,240,196,106,165,130, - 171,20,214,164,156,85,169,92,198,242,60,159,35,33,218,228,123,186,123,102,173,193,90,8,171,117,122,183,236,80,103,255, - 237,175,15,220,245,161,191,45,222,112,252,136,219,1,98,6,238,250,87,112,34,130,214,225,75,24,114,9,128,94,42,240, - 44,192,255,207,222,123,199,89,118,223,245,221,239,95,57,229,246,185,211,103,103,123,209,54,173,122,177,154,37,119,185,202, - 13,8,37,33,129,0,126,72,131,39,161,132,36,15,36,36,144,74,66,66,28,74,32,4,176,41,46,184,55,92,100,201, - 234,171,174,149,86,219,251,238,236,244,91,79,249,149,231,143,115,103,180,54,205,96,9,21,239,239,245,154,151,118,71,187, - 51,103,239,156,243,185,223,242,41,156,2,126,128,111,186,203,250,75,143,4,42,80,23,176,105,57,174,76,95,246,186,107, - 20,244,33,183,72,235,113,69,201,129,116,30,151,231,136,193,59,50,8,132,20,197,140,199,14,222,149,165,196,15,38,226, - 43,96,4,133,113,188,207,13,62,84,156,238,119,249,232,93,119,243,247,223,248,38,66,151,98,113,96,37,97,20,211,239, - 84,121,250,217,62,235,215,150,169,55,60,42,239,35,58,179,184,216,67,185,4,57,216,94,31,35,83,84,37,38,144,67, - 24,47,176,54,3,21,146,187,18,41,154,80,123,180,47,200,139,86,40,50,3,222,180,169,15,149,120,251,123,110,231,205, - 111,125,3,15,222,247,8,31,252,221,63,228,161,7,31,37,138,67,74,81,137,32,136,72,211,28,143,32,42,5,24,231, - 17,40,36,18,147,91,242,204,162,148,64,105,89,16,6,131,128,74,84,193,135,130,220,230,56,60,81,28,177,121,203,86, - 30,127,226,113,20,25,90,234,162,85,146,174,208,153,5,33,198,20,192,157,166,41,129,214,24,227,72,243,20,132,164,159, - 37,164,54,167,159,244,9,195,128,86,171,77,225,40,154,227,128,90,163,134,84,18,55,88,48,40,169,17,82,23,44,174, - 11,218,178,94,123,153,117,211,107,104,254,248,63,173,60,252,209,143,94,127,197,151,63,175,134,189,143,13,124,165,4,251, - 183,192,82,5,252,69,29,217,69,0,250,166,42,149,73,10,13,215,142,231,177,124,86,192,19,32,231,138,66,104,58,219, - 185,99,100,227,206,93,216,212,146,244,59,8,233,138,42,198,23,27,163,94,175,11,222,161,68,145,12,97,141,89,157,251, - 60,199,50,94,49,79,24,84,65,120,140,42,102,53,101,35,80,42,230,107,7,158,100,219,206,77,188,97,199,165,244,150, - 90,8,227,176,57,172,25,154,224,228,241,51,124,224,171,79,112,235,171,119,113,199,117,83,216,164,199,252,236,25,98,29, - 81,206,45,54,201,88,204,12,102,104,136,145,53,101,130,64,35,188,4,165,153,157,159,71,72,69,183,211,197,171,25,234, - 141,26,82,87,112,94,33,149,194,225,73,147,28,137,224,198,91,111,230,85,55,221,196,129,125,251,249,202,151,190,202,51, - 207,60,195,220,220,18,74,4,100,169,37,233,91,42,165,50,161,87,68,198,147,24,143,49,142,60,205,80,113,9,107,29, - 100,142,37,215,37,40,85,208,81,8,162,152,243,76,76,140,50,58,210,228,212,233,110,81,149,12,44,69,140,205,65,20, - 91,49,47,32,140,35,140,49,56,147,99,58,150,48,138,152,95,92,160,223,79,152,28,155,196,26,67,179,217,196,123,79, - 169,92,66,105,69,16,40,226,114,92,172,227,157,35,203,51,132,176,3,198,53,104,173,7,111,4,158,60,203,168,40,73, - 237,111,127,79,233,228,244,248,117,230,247,63,80,155,204,237,68,79,138,207,143,35,30,250,53,231,230,43,224,22,120,101, - 229,182,95,4,160,231,241,40,10,95,103,65,17,18,118,252,121,158,41,165,160,34,168,183,96,172,113,211,117,213,122,163, - 129,107,183,240,214,160,66,129,84,2,225,5,46,203,200,211,180,136,151,246,126,96,71,81,188,227,66,65,144,91,25,64, - 23,174,132,172,154,181,163,36,18,65,104,138,90,174,87,141,249,208,253,95,99,247,186,45,108,40,197,44,119,91,104,23, - 146,229,142,169,181,27,105,239,123,154,95,248,149,79,32,126,244,157,212,134,234,220,125,239,62,226,44,229,71,190,235,38, - 134,71,3,226,126,196,51,71,231,105,68,109,42,227,13,50,93,66,232,136,131,7,159,162,185,118,43,222,11,22,102,206, - 211,91,156,163,212,104,82,105,142,82,173,84,10,95,34,95,120,10,101,105,23,240,236,216,179,149,75,118,108,227,220,153, - 179,60,244,208,163,124,229,139,119,113,238,244,108,17,76,24,4,148,42,37,172,205,8,203,37,114,60,229,64,23,179,111, - 40,230,58,78,128,41,82,53,34,165,137,163,136,32,214,92,126,249,30,218,189,22,110,169,69,154,24,210,36,91,229,4, - 33,4,65,84,48,116,196,32,230,71,56,143,233,247,9,131,16,37,36,75,75,11,56,107,145,82,210,239,247,168,155,58, - 81,20,130,244,88,107,168,86,171,72,41,144,97,136,179,30,231,138,24,162,149,159,197,10,113,209,123,240,221,140,145,215, - 191,49,58,63,57,124,89,247,215,254,111,125,211,242,98,121,9,175,55,194,67,85,152,237,129,41,93,196,148,87,30,0, - 125,171,206,117,9,133,153,188,164,176,164,204,95,128,235,139,139,55,191,81,7,35,91,46,223,173,36,96,50,131,183,25, - 74,23,43,102,37,21,153,45,230,22,82,73,156,119,232,32,24,168,203,47,92,189,251,63,245,13,60,126,16,56,232,49, - 20,179,26,25,132,204,183,219,124,224,11,159,231,159,221,241,86,156,42,24,214,74,20,38,242,223,247,198,55,241,95,126, - 111,150,159,254,165,207,33,34,232,38,57,161,81,28,88,106,177,123,199,4,71,143,44,115,234,200,44,127,247,221,55,242, - 222,219,47,195,36,243,232,234,40,235,199,199,120,228,153,253,116,83,197,182,29,59,49,198,50,127,110,134,246,210,34,181, - 122,131,218,80,131,168,92,69,6,33,86,120,172,119,164,38,69,34,153,88,59,206,29,27,238,224,181,175,123,45,143,63, - 246,36,95,250,226,157,28,63,114,140,36,55,84,170,117,84,168,177,222,147,103,6,99,220,96,123,101,168,196,101,164,119, - 144,59,172,51,232,82,5,41,2,166,214,172,99,235,37,219,185,251,174,175,17,170,128,36,179,160,6,100,1,231,49,185, - 41,12,213,100,97,65,43,133,24,48,206,29,89,158,211,106,183,240,206,17,134,154,90,173,86,204,216,36,76,6,147,184, - 208,208,235,118,169,213,235,133,188,68,20,145,67,193,96,213,239,157,199,13,126,47,165,198,25,73,214,74,41,95,114,185, - 92,248,7,63,182,57,251,205,255,169,183,207,156,143,60,52,143,193,253,13,56,190,5,146,228,34,174,188,178,0,40,191, - 106,43,187,119,175,35,252,163,175,145,165,127,53,248,176,20,9,25,215,3,163,47,212,245,1,79,8,17,119,188,31,213, - 245,198,232,212,13,87,107,156,197,101,25,206,228,56,95,2,81,112,115,140,205,201,77,134,180,6,165,195,1,35,167,168, - 118,132,144,120,107,89,33,37,174,14,94,133,0,161,144,182,72,109,74,5,32,37,42,7,77,200,67,71,14,242,91,95, - 249,10,239,186,246,90,148,51,72,163,201,101,78,173,164,248,238,55,190,129,95,248,208,23,104,231,61,100,73,145,89,205, - 231,246,158,225,179,15,157,70,6,37,162,192,243,31,62,242,101,234,53,197,229,27,70,153,61,177,200,153,182,227,145,189, - 79,241,203,191,254,33,182,238,220,205,187,223,253,110,94,253,170,203,8,69,74,107,110,158,197,249,121,42,245,58,245,225, - 97,42,141,6,129,214,184,193,63,194,58,75,106,218,132,21,197,77,183,93,207,171,110,186,154,131,7,14,112,223,221,15, - 243,181,59,247,226,241,148,43,49,46,246,180,187,93,202,141,152,176,20,145,38,9,222,43,2,29,32,101,72,174,37,113, - 92,34,183,112,233,165,87,242,212,83,79,211,107,181,105,14,213,200,242,28,33,130,98,16,237,252,234,155,128,146,18,239, - 92,17,83,173,60,233,128,240,24,230,41,51,51,231,200,243,140,181,211,107,73,251,125,150,151,150,145,82,18,132,30,209, - 233,80,138,75,128,28,180,93,32,69,161,204,119,190,144,204,56,114,188,18,4,82,144,167,25,181,141,155,200,255,201,143, - 173,127,246,183,126,227,246,245,135,142,78,148,97,84,194,157,167,224,224,20,180,215,95,92,144,189,124,1,72,0,121,163, - 194,210,27,174,96,230,138,77,152,177,6,183,106,197,231,119,174,227,183,191,244,56,31,253,218,211,228,105,206,115,89,151, - 127,246,113,20,121,222,55,12,90,176,244,5,122,1,159,5,209,246,190,9,172,173,108,217,212,28,222,52,141,181,6,147, - 119,11,93,151,208,131,135,195,144,244,186,224,236,128,241,60,96,227,14,134,209,120,183,218,126,121,127,1,40,249,194,185, - 112,229,239,32,5,94,120,148,3,229,21,46,138,248,236,19,251,104,150,154,220,182,117,19,89,146,162,51,75,191,103,216, - 56,58,194,119,191,246,10,126,247,11,119,147,57,5,58,35,20,49,24,141,15,114,140,78,57,179,232,249,177,247,127,133, - 225,102,133,110,39,101,177,221,38,115,22,21,132,156,252,218,131,60,242,200,19,188,241,182,27,121,215,59,223,202,174,221, - 59,9,53,244,187,61,58,237,54,81,185,68,115,116,132,70,99,4,175,36,214,219,66,217,142,45,60,138,156,103,199,206, - 75,216,121,217,101,220,254,246,183,240,229,47,124,145,189,247,61,200,236,217,89,134,202,117,92,167,133,75,3,164,183,164, - 38,165,60,52,76,181,90,47,50,169,180,0,231,41,5,17,239,121,199,59,57,124,248,89,158,120,226,9,162,114,137,165, - 229,22,97,28,145,13,88,210,114,16,249,147,101,57,30,79,54,72,96,245,56,58,221,54,181,106,13,99,114,58,221,22, - 229,82,153,229,229,101,148,82,52,135,155,88,107,73,210,148,40,140,7,175,125,209,26,15,56,163,3,141,158,197,11,135, - 247,2,169,21,89,158,32,106,227,200,31,253,137,177,187,255,240,119,94,189,235,129,251,135,214,195,104,15,190,252,42,120, - 236,10,88,72,193,70,23,49,230,229,1,64,57,48,178,123,61,122,231,58,90,151,109,228,245,113,200,201,209,58,34,55, - 8,99,73,115,203,244,112,149,159,255,222,219,248,123,175,187,156,234,151,30,71,126,237,105,236,159,83,17,57,138,16,194, - 179,131,141,215,11,241,118,36,129,118,113,237,81,73,136,245,125,239,119,174,123,219,219,199,100,185,140,233,246,240,46,65, - 137,0,208,197,128,217,249,85,63,100,6,156,151,40,12,137,226,136,86,183,187,26,123,188,34,205,88,253,62,82,146,187, - 65,219,229,61,184,98,107,230,5,228,206,226,60,200,64,243,249,71,246,178,113,120,132,201,106,68,110,122,4,68,180,231, - 123,188,113,247,30,22,151,58,124,244,190,135,16,97,8,34,35,84,93,80,224,92,97,89,177,216,207,152,235,167,68,90, - 34,117,128,34,2,169,209,58,36,113,57,127,252,185,187,249,220,157,143,112,219,173,215,112,199,219,223,192,158,93,91,168, - 148,98,156,49,204,30,63,193,114,121,137,161,137,9,170,181,234,192,243,87,161,131,16,132,162,211,233,179,124,254,12,179, - 199,207,176,182,82,133,117,235,56,221,77,169,135,49,177,82,132,8,186,121,194,162,135,185,153,57,186,75,109,198,54,111, - 33,8,36,105,150,99,109,78,24,106,190,255,251,190,143,143,125,252,227,124,249,43,119,2,30,107,114,180,208,171,131,107, - 103,115,226,48,36,51,6,169,21,74,74,76,150,23,0,222,106,83,12,174,60,83,83,147,68,97,206,242,242,50,14,71, - 115,120,152,74,69,145,101,57,229,178,94,5,33,6,111,16,206,186,98,254,230,67,112,133,246,77,106,79,154,56,74,81, - 157,202,59,223,19,155,55,189,254,234,195,191,248,31,27,91,242,108,196,66,53,132,7,159,130,153,61,96,194,151,216,67, - 191,79,202,213,88,171,111,43,0,74,128,141,19,67,252,236,15,188,129,70,28,98,7,15,85,131,34,139,107,221,244,8, - 86,73,82,99,25,118,30,219,251,250,154,37,51,142,204,164,76,13,87,113,223,123,27,188,238,114,26,95,126,2,113,247, - 62,220,5,64,180,18,45,123,30,88,203,11,231,247,187,242,3,108,65,213,123,191,149,56,222,210,124,219,235,171,18,75, - 150,165,152,220,13,86,236,186,216,222,164,93,178,126,175,24,184,202,66,12,89,138,53,229,114,9,63,200,137,89,1,32, - 107,221,170,254,85,136,98,85,239,133,192,27,139,240,14,137,194,121,143,8,20,210,58,188,55,44,187,156,15,221,123,55, - 223,123,235,45,12,199,18,155,231,160,36,173,185,14,223,121,221,13,44,47,182,248,220,254,131,184,178,4,111,209,54,192, - 88,80,202,18,72,80,14,228,64,29,39,40,252,155,17,16,149,202,248,146,198,163,120,248,209,253,156,58,113,134,93,219, - 54,114,203,205,215,113,217,229,187,24,106,12,145,217,140,133,153,25,210,110,74,165,54,68,218,233,49,115,242,0,199,15, - 28,96,230,228,9,226,126,159,114,98,112,78,210,64,49,57,189,113,176,66,79,200,77,142,202,12,205,80,179,182,92,99, - 46,77,153,57,124,24,61,220,164,50,62,78,230,45,206,11,78,159,62,201,79,252,228,63,33,205,219,124,233,75,119,35, - 69,165,160,38,136,140,40,14,169,196,53,58,221,14,90,10,188,45,242,230,65,160,85,17,1,237,188,35,205,51,150,150, - 150,169,85,235,8,4,189,110,159,48,234,162,164,162,82,9,200,243,156,48,140,6,250,48,199,74,136,136,243,2,114,9, - 42,196,147,35,29,84,194,144,78,107,137,209,106,153,239,251,233,127,166,62,181,110,253,246,189,63,246,99,149,43,186,189, - 138,4,213,129,175,46,195,236,8,188,36,82,88,87,172,69,126,41,8,200,40,66,59,95,241,0,180,178,72,206,128,145, - 177,6,191,250,99,119,176,126,98,168,48,154,186,96,78,99,160,248,92,246,156,115,255,159,91,45,25,7,38,133,225,42, - 35,223,115,43,63,248,218,203,80,95,126,2,238,222,135,72,115,202,20,17,181,103,120,97,27,113,89,128,156,16,48,226, - 96,115,112,217,158,53,205,203,182,8,159,27,112,41,185,145,72,157,82,81,10,188,34,239,247,17,198,34,80,24,28,126, - 197,255,199,56,172,43,66,6,87,164,2,82,62,39,192,47,214,243,190,16,203,242,220,127,5,130,64,72,188,240,56,47, - 201,133,227,208,226,57,62,255,248,227,124,199,245,55,19,136,20,200,201,156,193,119,3,190,247,213,111,96,222,165,220,115, - 228,32,58,172,32,115,65,136,199,34,17,82,16,170,1,120,123,135,240,30,233,50,74,58,100,124,168,73,110,114,132,16, - 140,141,77,17,149,74,156,154,79,249,228,103,239,229,190,251,30,229,170,61,59,216,126,201,70,58,237,22,237,185,46,237, - 217,46,102,185,79,144,101,148,176,172,169,104,148,86,36,78,226,50,75,106,12,221,165,46,206,187,194,31,218,164,69,155, - 3,216,180,79,83,8,106,181,26,11,189,148,238,169,179,232,161,17,42,245,58,231,103,23,233,245,230,249,169,159,252,127, - 88,156,159,101,239,195,71,8,75,101,124,224,41,87,99,66,95,8,116,157,119,3,98,165,34,205,114,50,99,232,167,9, - 121,158,34,148,196,26,75,28,197,76,140,79,33,165,160,221,106,19,4,33,82,104,84,173,134,181,133,231,145,82,43,222, - 73,133,59,54,62,199,32,200,189,65,89,69,37,12,57,53,59,203,235,223,250,90,92,214,229,109,127,255,7,248,125,45, - 215,126,242,239,255,240,107,223,105,221,9,7,79,206,192,124,11,220,139,61,16,18,131,89,232,191,14,67,238,148,154,186, - 51,47,9,81,219,11,10,64,110,0,44,149,102,149,205,175,187,156,137,155,119,225,203,17,157,110,250,252,212,127,3,32, - 154,24,174,97,191,231,86,14,189,254,114,110,253,195,175,177,243,209,195,0,172,249,27,120,1,123,16,28,131,113,11,235, - 135,94,251,186,166,142,171,248,100,25,155,38,120,111,138,76,46,89,100,16,228,121,134,181,69,24,160,29,16,221,60,43, - 186,172,1,24,15,124,130,254,172,90,235,66,113,170,117,5,143,104,69,84,169,156,67,11,137,11,35,30,58,122,144,241, - 198,16,119,92,118,13,174,215,162,143,225,140,93,34,50,1,223,119,213,141,196,157,156,7,79,159,192,198,101,148,15,17, - 214,227,188,199,42,129,86,133,69,170,181,6,231,114,242,212,50,115,110,142,56,148,132,74,50,111,78,49,57,53,65,189, - 90,161,169,20,213,126,206,137,251,31,135,99,103,41,41,133,75,114,74,174,0,70,169,36,198,58,218,185,135,52,71,90, - 135,177,22,99,29,153,207,200,172,41,146,58,132,7,45,80,229,18,149,114,131,70,189,1,65,192,194,177,19,44,204,204, - 34,77,151,233,250,14,36,1,71,143,156,224,250,235,246,240,175,254,229,63,229,39,127,242,223,176,255,192,9,234,67,99, - 52,74,195,88,99,16,84,233,13,50,168,60,158,48,12,81,74,209,207,82,4,144,101,25,222,58,206,156,57,131,115,48, - 58,54,70,104,45,189,118,135,44,203,49,206,80,171,214,169,84,42,171,213,167,247,162,72,232,144,186,48,52,179,69,74, - 108,146,37,84,107,21,46,185,100,43,38,203,9,189,164,50,58,202,130,84,177,178,174,44,64,71,20,113,226,238,69,126, - 208,235,192,191,15,52,127,168,53,53,138,153,226,43,106,6,228,47,120,145,61,69,252,46,59,215,177,118,231,90,198,111, - 217,77,216,168,144,37,25,100,230,121,111,62,141,177,96,44,253,225,58,63,243,67,111,34,253,185,15,242,244,249,165,23, - 244,37,22,131,170,110,73,16,134,158,241,69,88,51,114,235,205,37,133,199,152,12,211,239,34,113,40,21,163,116,128,247, - 22,147,167,5,104,120,135,148,69,128,173,214,130,56,14,87,163,108,87,212,217,95,255,157,10,209,164,64,192,128,211,178, - 242,103,11,41,130,3,225,9,148,66,58,65,174,224,11,143,61,194,80,28,115,203,142,29,200,180,133,72,29,121,218,39, - 182,154,247,190,234,213,52,158,126,156,135,79,31,165,235,10,143,105,97,4,210,41,2,87,172,178,5,158,32,140,40,7, - 33,81,28,83,173,68,140,55,26,76,84,235,76,148,171,76,15,141,80,46,197,200,64,97,133,67,57,143,76,243,130,81, - 237,13,185,243,128,66,234,136,126,55,37,21,150,196,103,232,40,160,50,90,165,54,50,78,169,89,163,57,49,78,117,104, - 136,176,90,163,218,28,162,92,46,83,169,148,209,97,200,77,173,46,79,63,245,12,79,60,246,4,39,143,159,167,22,55, - 57,123,102,134,94,111,43,107,166,70,249,133,127,247,207,249,231,63,253,139,204,205,166,3,110,133,39,75,83,148,146,88, - 231,208,186,104,169,188,119,72,138,100,144,94,210,39,14,66,148,86,44,183,22,169,86,43,40,41,105,181,150,41,85,43, - 69,180,144,43,140,203,74,165,18,74,169,194,187,9,81,196,71,231,14,44,232,72,50,59,115,158,75,182,111,165,222,168, - 97,156,1,169,184,247,11,95,98,71,158,207,122,56,235,161,29,131,123,49,1,200,15,182,191,255,88,7,252,143,64,81, - 161,224,139,188,84,236,102,181,80,223,130,24,65,74,86,254,190,6,42,151,111,66,150,66,244,45,187,177,149,24,49,61, - 194,26,41,241,89,142,233,190,240,236,8,153,229,44,70,1,235,55,79,210,56,191,244,130,127,191,22,240,8,34,2,223, - 12,54,108,104,214,247,236,146,152,156,60,233,99,6,201,12,222,151,65,106,172,205,72,147,94,97,52,54,0,24,231,44, - 74,105,148,214,131,77,23,23,12,161,87,139,157,1,40,13,214,204,95,103,140,54,0,31,239,113,90,32,188,39,180,130, - 80,132,244,69,202,239,63,240,85,114,109,184,117,227,86,84,219,98,8,200,164,71,59,203,219,118,238,225,198,75,182,178, - 104,19,210,126,177,173,114,12,146,36,6,241,205,165,48,42,18,53,148,162,28,86,8,156,34,80,2,103,50,2,97,240, - 89,23,111,53,90,106,188,150,248,40,32,32,66,100,142,126,150,179,220,239,211,241,45,214,111,219,204,216,218,81,202,163, - 21,234,245,10,149,90,140,142,2,84,160,137,74,85,74,213,26,81,185,134,10,162,98,219,132,39,199,211,24,170,115,243, - 173,183,112,243,205,55,113,238,212,57,158,120,252,25,14,60,251,52,135,14,157,96,251,182,141,108,219,182,149,127,243,175, - 127,134,159,255,185,95,98,102,118,17,98,137,212,186,104,193,188,31,204,128,32,12,195,162,133,28,56,34,58,239,73,179, - 156,115,231,207,227,61,108,222,180,165,104,7,251,69,102,189,53,57,173,214,50,206,123,106,213,106,33,135,65,226,173,67, - 73,9,40,156,181,228,54,225,234,107,47,7,60,161,14,217,127,240,8,207,124,252,19,230,125,112,220,194,33,13,75,245, - 193,140,243,197,60,95,144,138,223,213,154,0,255,146,99,106,107,51,119,254,91,40,3,4,56,199,145,127,242,118,110,202, - 51,130,245,227,116,181,42,18,150,60,248,44,255,27,103,67,104,231,217,255,134,43,56,176,247,96,49,176,125,1,223,89, - 98,96,220,251,178,135,145,112,203,214,161,161,169,113,92,178,68,210,235,146,103,25,82,41,52,26,33,4,73,210,37,75, - 250,72,10,73,65,161,245,26,172,214,87,124,120,46,104,189,86,128,198,251,1,39,104,133,22,61,16,78,14,28,134,86, - 127,14,210,121,156,176,24,41,138,12,83,173,233,248,156,143,221,127,15,83,81,149,45,19,83,164,73,15,103,12,185,201, - 136,195,136,102,20,209,240,1,42,168,226,130,128,92,21,32,134,243,152,44,69,82,124,47,233,37,248,140,92,21,98,88, - 165,4,50,0,173,3,194,160,132,150,154,204,89,82,233,88,204,61,243,2,206,217,148,182,75,72,178,46,75,157,121,174, - 10,134,217,50,53,65,92,142,201,242,148,52,201,177,253,20,33,66,234,245,128,72,6,5,209,82,106,172,179,8,169,138, - 170,33,77,16,192,228,218,49,38,55,76,114,211,242,13,28,126,246,32,207,30,58,129,240,134,29,59,118,242,19,63,245, - 15,249,255,126,246,223,178,216,235,145,229,22,41,53,72,129,177,150,64,42,162,168,68,179,57,196,210,114,11,99,115,172, - 241,228,121,78,160,53,173,78,139,243,179,231,24,29,29,195,121,8,130,238,160,237,114,116,41,194,22,203,229,74,97,215, - 33,11,187,146,80,75,206,158,59,195,214,237,91,152,90,55,69,158,166,200,184,194,39,254,248,19,108,63,113,124,110,4, - 158,78,224,72,31,250,127,60,24,246,190,88,51,160,42,240,159,2,205,146,128,202,75,113,13,159,30,125,246,91,255,42, - 227,117,42,66,224,211,28,159,190,184,163,45,151,27,234,27,199,153,188,110,27,203,247,238,127,65,1,40,4,169,165,168, - 230,206,143,235,230,112,69,73,143,119,166,240,44,70,96,156,163,44,11,73,64,175,219,42,230,63,190,40,199,133,4,33, - 10,63,157,80,235,1,25,81,172,90,76,172,180,87,43,230,100,171,237,217,170,107,98,17,203,190,194,158,46,100,98,18, - 163,5,214,21,32,18,137,128,212,102,252,225,125,247,242,206,91,110,102,107,115,24,233,28,38,10,200,180,68,100,14,97, - 5,169,80,120,3,202,22,58,52,37,36,210,5,8,173,87,149,250,198,59,34,33,9,195,34,250,199,8,193,114,158,243, - 236,249,25,90,253,62,105,32,201,227,128,32,174,162,194,26,178,222,164,108,42,212,228,48,253,190,225,206,187,30,224,190, - 251,247,114,249,21,151,177,125,219,54,70,70,134,48,121,70,123,169,67,191,123,140,114,173,70,169,86,163,90,175,161,195, - 16,164,196,123,71,38,61,69,253,97,193,164,196,213,144,61,87,95,193,214,254,37,28,218,255,52,15,61,250,8,227,163, - 99,188,251,59,223,198,175,188,255,183,177,126,32,252,85,1,165,40,70,8,65,158,229,140,141,142,16,232,128,165,165,37, - 210,52,197,25,143,113,142,94,191,207,169,51,103,136,227,18,163,195,99,152,44,167,211,110,175,254,12,236,192,132,191,82, - 41,3,18,233,100,65,127,200,51,110,190,229,70,114,107,64,41,78,159,62,203,227,31,248,160,249,30,56,156,195,227,14, - 78,255,79,48,159,124,177,159,240,32,36,148,138,242,138,156,231,165,6,64,66,61,15,99,32,99,95,244,33,219,215,129, - 131,117,76,188,246,114,166,30,60,64,108,220,11,242,238,179,226,41,52,7,82,128,94,74,83,221,203,218,4,120,18,107, - 81,113,140,116,150,168,84,198,153,140,164,215,43,252,119,156,67,106,133,27,112,160,165,210,132,97,225,197,44,132,94,5, - 155,21,48,130,129,47,180,95,177,140,125,78,167,228,87,53,99,69,236,178,178,128,183,24,105,139,4,119,227,80,50,228, - 88,210,227,255,124,233,203,220,176,105,59,87,109,222,204,84,165,76,32,32,215,6,35,28,194,57,20,30,159,231,132,74, - 227,124,142,14,10,101,184,80,122,80,81,72,156,146,28,95,110,113,236,208,97,150,140,97,161,223,199,5,138,209,169,9, - 26,149,6,54,243,136,92,130,233,17,42,77,164,21,198,42,130,32,102,116,122,10,25,6,28,62,182,200,129,3,119,51, - 49,218,96,207,165,219,88,51,57,140,146,158,206,226,121,58,11,179,180,162,152,82,181,78,181,57,76,185,82,33,212,193, - 192,56,3,44,186,176,6,17,150,168,164,184,236,218,107,217,190,123,55,167,78,28,229,202,252,42,246,92,246,0,247,61, - 240,16,82,69,104,161,73,179,140,56,138,139,193,179,135,225,102,147,114,169,68,183,223,163,221,43,236,102,187,73,31,235, - 28,71,143,29,199,89,201,154,169,73,100,36,105,181,90,24,107,168,84,138,90,83,105,73,92,138,9,101,192,169,83,167, - 216,125,217,78,70,199,70,233,231,125,170,213,33,62,241,177,223,99,253,51,79,204,143,192,83,25,60,149,195,210,20,248, - 247,240,226,144,237,34,224,30,41,57,174,36,218,191,116,73,217,175,72,49,170,207,12,193,166,9,22,174,217,198,254,251, - 159,125,65,128,127,80,1,249,186,243,109,5,199,151,191,248,133,195,31,188,241,117,155,198,234,13,113,166,164,74,205,43, - 246,68,107,174,190,92,236,186,118,13,209,112,25,99,115,220,64,107,36,173,69,200,24,239,51,180,202,10,107,10,21,124, - 67,235,245,28,8,201,193,122,94,2,94,174,12,159,221,215,189,163,121,81,216,189,202,66,201,129,195,227,133,196,121,129, - 208,154,101,39,249,204,254,125,124,245,232,1,118,142,141,115,249,212,90,214,77,140,83,46,151,8,181,38,116,2,97,13, - 206,122,180,214,16,134,244,157,101,169,223,99,118,97,145,99,115,51,156,92,158,39,183,30,21,197,56,161,200,173,165,42, - 171,72,25,98,157,196,107,72,76,78,40,161,84,9,139,217,150,113,24,160,223,206,104,84,98,42,186,142,12,60,231,206, - 156,231,248,241,47,49,52,92,225,138,43,119,179,97,253,52,181,114,136,49,57,11,243,231,105,45,204,17,149,202,148,199, - 70,168,150,107,148,75,53,132,18,88,145,98,189,197,122,143,77,19,164,128,205,219,182,178,105,203,22,174,186,250,58,62, - 251,185,207,243,155,191,245,127,121,252,177,125,120,36,18,79,160,66,150,150,150,72,210,144,48,138,105,54,135,9,162,136, - 126,175,143,71,146,152,148,124,113,158,44,55,244,210,46,107,166,166,136,227,152,165,197,37,242,204,210,28,86,164,73,66, - 24,133,180,250,203,72,13,55,223,124,19,206,90,34,29,115,250,212,121,30,249,205,223,202,239,192,31,204,97,175,135,19, - 215,65,246,134,23,241,25,56,43,4,215,135,209,115,109,250,69,0,250,27,110,197,172,99,232,245,87,176,254,225,67,168, - 220,62,239,85,144,2,22,193,159,132,249,146,20,119,111,74,211,220,61,252,204,6,15,245,10,76,44,127,230,158,201,103, - 66,53,126,248,250,43,71,174,252,169,31,175,142,111,223,36,122,102,22,235,52,113,10,50,116,56,45,64,36,131,97,178, - 64,122,119,129,254,75,174,130,80,209,183,13,124,158,145,69,237,228,60,98,176,13,43,64,106,64,54,241,30,225,124,65, - 58,19,96,241,104,83,36,107,248,80,145,56,203,3,167,143,179,247,212,113,154,97,133,169,70,147,201,161,49,214,84,203, - 12,87,75,212,107,67,100,166,207,241,153,25,78,44,204,114,116,113,150,142,40,134,172,129,40,242,182,116,146,3,25,90, - 41,98,165,48,253,62,11,221,46,94,64,20,197,140,143,143,19,148,11,51,51,75,225,225,147,154,132,133,158,39,10,3, - 164,132,90,115,132,166,30,35,207,83,246,62,116,148,135,246,30,100,227,186,81,118,108,219,88,164,99,152,140,94,119,153, - 243,201,34,101,25,51,90,110,82,30,31,161,92,175,160,148,198,51,240,215,150,146,196,230,72,33,104,140,84,248,222,31, - 248,30,222,126,199,219,248,212,39,63,205,239,254,223,15,242,228,147,251,233,27,139,117,142,118,183,131,214,133,24,182,214, - 168,81,42,149,232,245,122,88,231,48,194,51,215,158,163,125,184,205,252,252,28,155,55,109,97,120,120,152,110,167,131,214, - 138,74,41,70,24,199,233,153,83,188,243,221,239,96,104,164,70,154,100,148,170,53,62,244,187,191,206,182,39,30,62,51, - 10,15,36,240,112,11,22,62,51,40,88,95,140,83,1,126,55,8,56,73,193,253,185,8,64,47,198,201,12,126,227,4, - 242,71,223,202,154,247,127,26,242,231,127,241,216,7,74,208,203,157,223,39,224,140,46,102,126,229,88,48,86,246,172,153, - 202,236,166,252,238,189,59,14,221,255,247,46,219,123,199,235,54,237,252,225,247,68,235,39,183,145,36,139,72,221,66,136, - 18,74,12,161,85,4,184,162,130,17,69,122,198,10,17,110,117,45,63,48,172,119,190,104,187,164,82,95,103,170,190,194, - 7,186,112,139,38,87,62,47,37,129,82,88,99,11,251,213,48,194,11,232,144,115,176,53,195,254,185,211,72,233,9,164, - 36,210,49,74,200,194,188,203,122,172,20,232,56,90,77,39,213,170,200,55,43,151,43,68,113,140,113,150,147,167,79,19, - 199,37,198,199,39,24,105,142,96,115,203,236,204,44,113,28,175,234,245,162,40,30,236,44,86,248,75,57,214,22,60,29, - 173,3,132,16,28,63,50,199,129,103,142,49,60,82,101,231,246,205,108,218,184,150,161,64,98,178,140,179,217,121,92,111, - 137,122,28,81,175,84,24,106,142,16,68,85,242,129,161,91,110,7,196,186,44,71,7,146,239,249,219,223,199,219,223,254, - 46,30,221,251,24,95,251,218,125,124,225,11,95,230,192,161,99,244,147,132,32,10,152,155,93,40,30,0,165,138,156,54, - 239,80,66,225,242,156,153,153,51,100,105,159,203,47,191,156,145,145,113,242,60,163,221,105,211,237,119,216,184,105,3,59, - 119,238,32,207,13,97,24,114,248,196,49,30,248,63,191,145,127,63,236,207,225,254,18,28,59,5,217,223,126,49,239,253, - 48,68,42,93,204,125,46,2,208,139,119,68,146,49,127,249,102,178,31,125,43,27,223,255,105,196,243,12,66,26,232,22, - 221,88,79,67,63,0,150,64,214,60,65,8,165,150,96,88,121,177,109,58,207,110,46,127,248,179,183,126,245,193,71,47, - 189,228,39,126,108,232,134,215,95,67,175,107,7,3,77,129,51,5,229,95,14,252,160,221,138,6,98,208,146,173,216,77, - 92,104,211,186,2,60,43,195,106,121,65,53,116,97,43,183,226,105,227,7,131,43,233,197,170,127,142,212,18,99,45,178, - 172,81,66,32,45,24,36,198,175,204,47,67,74,186,200,143,151,10,226,74,9,111,29,165,114,133,48,138,200,178,12,188, - 39,51,57,213,160,134,150,146,110,167,179,250,61,3,173,139,7,92,22,210,143,64,5,104,45,139,239,53,96,25,39,73, - 138,14,52,113,80,162,57,60,133,195,210,89,94,228,179,95,184,151,102,57,224,150,203,118,49,185,110,140,242,196,8,153, - 23,164,237,54,115,237,22,203,115,115,148,42,13,106,35,35,148,107,197,247,206,93,97,248,111,129,110,183,69,20,135,220, - 124,219,141,188,250,53,175,230,71,254,193,63,224,222,123,31,230,163,127,252,97,238,249,218,221,164,105,70,20,70,196,113, - 68,158,164,244,147,4,231,61,222,21,18,142,86,123,137,125,251,246,177,109,155,97,100,100,140,126,191,199,240,112,131,183, - 189,237,205,224,29,89,106,208,181,144,79,125,224,119,184,250,240,129,99,117,184,191,7,251,2,104,189,19,120,138,63,61, - 243,125,33,225,192,3,35,192,7,148,226,159,43,77,224,95,30,98,124,245,163,111,185,230,149,140,65,200,220,144,172,27, - 163,191,126,140,161,71,14,33,158,71,82,252,50,48,63,88,135,43,10,233,199,97,240,195,96,110,133,36,135,37,7,231, - 114,56,83,130,214,250,229,142,220,255,213,123,26,231,70,199,106,27,47,221,69,232,11,207,228,187,238,126,128,99,39,207, - 34,6,98,157,21,95,232,213,56,154,193,44,200,57,55,208,39,125,189,80,245,27,65,103,229,215,95,71,106,84,18,47, - 7,105,139,198,162,17,84,163,50,177,10,9,133,70,152,66,218,81,12,155,1,45,81,113,128,197,146,216,34,157,162,86, - 169,33,164,32,77,19,58,157,46,253,94,15,132,96,100,120,152,90,165,86,180,70,222,23,219,62,32,138,162,85,66,95, - 1,176,158,104,144,131,22,69,17,66,72,180,214,40,169,176,206,98,156,71,5,17,149,114,141,250,208,48,253,133,101,204, - 233,89,78,31,58,68,167,213,166,17,86,168,13,213,32,16,228,182,24,236,247,151,151,232,245,150,17,18,202,165,26,82, - 72,36,32,10,50,19,198,89,146,44,33,42,133,236,218,189,157,55,191,249,245,220,116,211,171,24,30,110,210,233,180,201, - 147,140,230,240,8,65,16,210,239,245,113,110,197,255,71,18,6,17,173,86,139,209,209,81,192,241,93,127,235,93,76,77, - 142,131,135,40,8,120,250,208,97,238,253,167,255,108,249,245,237,206,87,114,248,84,31,158,222,9,201,8,48,14,140,81, - 144,0,199,6,191,127,161,63,246,42,201,63,14,34,114,254,108,171,97,33,64,13,136,173,43,213,180,82,197,27,66,16, - 40,182,93,178,149,219,110,187,141,64,235,130,157,63,208,38,66,225,101,37,131,129,182,223,63,63,43,39,21,86,95,249, - 0,180,10,66,235,199,72,166,71,105,60,114,248,121,3,161,229,98,11,198,32,114,144,14,133,58,126,18,216,58,184,249, - 142,64,22,193,2,48,99,161,179,49,55,254,236,87,31,168,60,99,178,198,37,55,92,33,165,15,185,235,174,123,57,120, - 248,40,98,0,38,43,244,255,21,32,185,16,100,86,254,255,159,85,13,21,22,18,254,235,51,197,6,21,149,23,69,154, - 59,222,35,7,10,203,220,22,41,167,94,60,247,103,133,150,232,80,23,214,164,120,132,119,104,41,16,174,48,0,203,141, - 25,196,240,20,128,40,133,160,90,173,82,46,149,9,244,192,169,144,130,252,87,42,149,208,90,175,138,58,181,46,182,124, - 5,248,20,198,97,122,224,229,236,188,65,234,34,128,81,8,129,14,66,74,66,161,150,58,12,151,42,204,157,56,203,201, - 253,135,56,183,52,143,174,151,41,85,170,68,74,131,119,164,105,135,110,167,67,191,157,130,49,4,90,19,69,1,171,92, - 5,37,16,194,96,93,15,176,172,93,183,134,155,111,186,145,27,111,184,145,237,219,183,211,239,247,72,146,62,214,153,130, - 57,237,4,90,6,228,198,144,36,61,188,201,121,247,187,223,206,21,87,237,128,65,36,80,88,42,243,191,126,225,23,217, - 114,231,93,7,198,225,179,33,220,181,31,230,126,0,120,255,224,227,127,0,7,129,47,3,159,166,160,95,4,64,243,5, - 186,207,127,58,8,216,43,20,241,159,215,17,92,4,160,23,25,132,54,140,147,172,29,165,241,232,17,132,115,207,27,0, - 137,11,0,168,69,225,57,189,117,101,27,1,124,28,92,0,157,42,204,120,33,102,167,156,203,179,135,159,172,63,124,250, - 196,208,182,215,223,166,31,121,120,31,79,238,219,143,80,23,182,96,69,98,231,133,192,115,97,69,115,97,160,222,133,31, - 127,250,166,27,124,222,249,34,73,85,8,132,82,88,1,70,128,21,2,43,5,97,28,17,14,0,76,10,129,242,130,72, - 40,68,110,136,229,74,52,51,40,165,136,194,16,147,229,148,202,101,132,148,88,99,168,148,43,40,161,80,74,209,104,52, - 40,149,74,88,107,169,84,42,88,235,6,179,30,189,26,127,180,34,176,181,222,129,42,72,131,82,250,2,248,84,64,16, - 134,4,129,98,105,126,150,10,138,166,138,8,132,100,118,97,129,243,11,45,250,25,116,146,156,70,115,132,48,8,144,94, - 144,246,251,180,91,139,116,218,45,156,51,68,81,68,168,117,193,107,18,30,188,45,76,225,140,193,88,203,80,179,206,174, - 221,59,185,245,214,155,217,115,217,110,202,229,98,91,54,55,191,136,16,146,40,10,177,38,225,59,223,115,7,111,127,251, - 27,73,122,11,72,47,168,87,235,220,255,216,227,124,246,103,255,117,255,246,36,185,207,194,231,42,176,223,9,145,255,170, - 82,76,3,63,2,188,9,248,126,224,106,224,243,131,22,105,106,80,17,189,16,231,83,82,241,184,148,127,46,219,249,34, - 0,189,84,64,104,221,74,37,228,94,112,0,154,7,126,163,248,188,123,15,116,219,48,155,75,185,52,226,125,172,159,61, - 54,246,200,153,51,213,67,185,212,199,142,159,64,72,113,65,11,245,167,65,230,27,103,60,23,126,254,194,57,209,133,109, - 218,133,25,90,43,119,97,33,128,245,104,161,80,40,66,161,80,20,159,119,214,19,40,141,68,146,231,150,204,88,156,144, - 196,229,242,64,246,225,168,86,170,200,193,48,58,12,2,130,32,32,142,34,148,146,228,121,70,28,199,212,106,85,140,177, - 3,208,41,230,88,90,7,5,165,96,48,181,16,74,34,6,67,115,41,5,10,77,32,66,156,144,24,239,144,145,66,85, - 35,252,82,155,138,0,161,5,37,17,19,82,97,98,221,86,206,39,57,15,62,254,52,210,72,42,81,68,169,22,162,180, - 36,79,83,146,126,143,246,242,18,38,205,9,132,64,171,16,169,10,223,231,98,192,47,138,65,184,203,144,26,214,111,90, - 203,141,55,189,138,55,221,126,59,91,54,95,194,210,252,34,103,207,158,225,166,87,93,197,143,255,216,15,147,167,139,96, - 115,148,144,232,176,196,175,252,187,255,192,165,15,63,122,116,29,124,33,128,175,61,4,179,191,43,21,135,227,146,248,77, - 107,185,213,123,70,6,85,112,23,248,42,176,133,194,30,230,133,114,230,252,152,122,249,1,208,183,93,44,143,234,38,180, - 174,216,196,241,31,125,11,27,222,255,25,68,254,55,19,168,82,46,64,200,127,12,90,239,113,238,201,28,106,107,2,61, - 162,62,123,119,248,137,122,109,109,80,10,3,147,101,5,176,32,240,190,96,224,202,11,218,178,11,129,71,107,189,170,156, - 255,198,1,245,159,2,222,213,135,188,16,105,226,11,177,176,116,30,133,67,88,135,87,106,85,68,236,115,87,128,3,160, - 116,0,74,174,182,94,74,106,130,32,64,169,34,125,52,75,83,2,29,144,36,9,165,184,132,214,138,52,77,72,211,180, - 16,122,42,133,247,130,44,203,73,146,132,32,8,208,90,19,134,65,241,239,92,105,135,69,49,73,243,78,16,149,34,172, - 183,32,61,149,177,81,146,133,14,121,110,136,69,70,100,37,73,63,99,97,102,158,181,87,238,161,149,24,172,136,176,132, - 60,246,212,126,70,134,26,172,95,55,141,240,130,180,103,88,236,205,210,154,59,79,169,54,68,125,116,146,74,165,178,250, - 58,20,129,140,30,164,163,159,180,208,82,50,54,222,224,123,254,238,119,113,199,187,222,198,125,119,223,69,123,105,142,3, - 71,15,49,82,47,209,172,55,136,202,53,62,240,193,63,66,253,209,71,58,55,192,137,4,142,155,162,186,85,223,139,183, - 239,77,19,191,222,89,186,20,130,207,139,190,172,223,198,91,176,63,31,132,210,191,113,16,26,36,103,240,105,224,59,160, - 229,225,145,60,55,245,105,76,253,54,19,15,237,151,97,83,73,133,244,133,133,201,96,169,245,117,21,205,115,225,133,110, - 117,229,126,97,149,115,33,0,93,88,49,201,65,98,132,148,5,168,136,193,12,200,225,177,24,130,32,40,218,160,193,106, - 57,8,66,178,52,69,7,10,99,114,170,229,18,206,121,50,103,9,162,66,185,111,141,161,221,110,19,40,141,22,10,188, - 164,215,235,83,173,86,17,162,112,23,140,99,63,72,251,240,171,177,67,118,85,205,47,16,190,144,91,40,89,128,159,147, - 30,161,5,46,207,145,74,16,160,9,157,194,78,79,211,59,115,142,97,33,73,69,70,213,90,206,45,156,166,218,94,203, - 214,233,181,180,150,231,217,126,229,53,148,71,154,236,123,252,81,206,157,122,130,169,241,49,214,173,157,70,135,138,126,218, - 162,179,60,71,119,160,120,175,53,139,205,89,16,197,3,6,127,49,124,87,74,226,69,78,158,47,16,215,20,175,127,251, - 107,49,73,194,241,99,199,120,230,137,39,57,113,98,158,196,30,227,127,252,231,255,225,254,89,97,183,90,115,176,205,192, - 242,102,56,42,156,59,231,112,173,164,176,46,243,23,193,231,226,22,236,47,104,199,44,201,250,81,146,117,99,212,31,61, - 140,176,127,245,178,242,155,105,193,78,3,95,24,108,41,174,0,62,3,236,46,90,179,100,20,18,15,147,75,129,222,113, - 79,16,14,173,26,143,249,175,39,25,94,88,201,60,231,25,237,255,84,229,179,82,233,92,88,45,93,248,241,245,105,171, - 98,0,72,2,37,139,217,77,173,86,43,42,22,87,228,198,107,173,6,118,20,121,81,53,88,91,248,47,11,177,202,221, - 41,149,98,164,144,4,65,72,24,22,237,88,173,86,195,24,67,191,223,71,41,73,28,199,197,182,107,144,193,181,178,5, - 91,189,14,85,72,116,133,148,148,162,98,132,170,131,194,196,204,216,156,64,23,100,199,186,214,4,145,38,208,10,149,24, - 178,32,96,100,122,154,110,167,79,88,210,236,220,185,133,53,227,147,52,26,67,156,157,61,207,189,123,31,194,8,207,244, - 154,117,133,87,146,77,201,210,132,94,183,69,175,189,140,201,82,162,149,175,39,20,82,42,112,133,246,12,1,206,228,120, - 111,24,30,29,102,219,246,173,12,53,71,152,157,95,196,40,201,99,179,11,242,72,107,185,46,97,93,19,182,70,176,206, - 64,195,129,232,64,222,1,227,193,141,83,240,197,190,10,108,186,216,130,253,233,25,208,255,243,230,171,191,109,209,87,100, - 134,254,186,49,146,181,99,127,173,153,208,55,3,64,25,133,53,236,235,128,155,128,215,0,87,2,107,192,47,10,161,148, - 16,235,231,2,125,197,93,81,52,94,216,119,20,55,134,251,51,222,63,47,36,27,94,72,58,252,198,13,217,10,224,92, - 184,166,247,43,119,224,5,159,135,98,168,28,4,1,81,84,36,83,224,158,179,170,202,243,252,185,121,141,16,168,129,110, - 80,14,4,158,90,43,226,48,162,92,42,35,101,1,52,65,16,124,29,96,73,41,87,179,207,86,190,215,55,94,183,146, - 18,169,116,145,243,165,53,90,43,172,115,120,201,192,210,86,66,160,49,173,14,195,97,136,245,25,97,102,72,90,61,212, - 88,19,89,169,113,254,236,121,54,78,79,81,27,169,177,216,91,230,247,127,255,35,254,254,223,254,80,254,216,159,124,213, - 30,234,180,148,42,69,76,140,142,82,46,151,17,206,224,242,140,164,215,97,105,126,142,164,215,65,74,77,24,132,133,79, - 211,224,7,106,125,1,150,198,26,28,158,106,181,198,246,93,59,120,211,91,222,44,118,191,229,109,106,118,235,246,210,231, - 218,253,241,175,204,205,111,236,153,108,211,56,108,170,193,100,0,85,1,162,11,121,0,249,44,248,71,128,141,23,1,232, - 79,207,128,38,38,38,94,54,120,241,66,181,212,246,205,55,96,190,244,56,225,190,111,45,174,112,197,34,227,194,27,96, - 35,240,11,23,252,126,199,5,189,239,97,48,161,247,125,19,5,206,13,98,120,86,103,60,74,14,18,82,159,3,20,117, - 1,251,249,194,10,231,66,160,249,70,55,197,231,42,158,194,33,80,12,188,94,87,190,222,74,85,149,37,105,225,43,228, - 45,185,181,196,113,188,250,178,135,97,76,150,37,148,203,17,74,23,132,201,96,112,45,74,235,1,232,20,21,79,24,134, - 69,64,160,16,171,243,22,231,28,229,114,153,52,43,28,33,117,16,20,195,231,193,133,25,87,248,236,228,185,193,5,97, - 209,18,250,34,31,76,42,141,115,144,5,33,182,20,147,246,51,116,172,17,145,167,153,88,22,14,31,165,126,233,165,204, - 182,150,56,126,242,4,179,251,186,252,187,159,248,41,191,227,145,39,91,63,14,103,37,36,119,254,250,31,76,252,247,15, - 126,124,116,244,134,43,131,55,220,254,70,110,188,114,55,99,205,42,206,27,146,52,37,109,119,56,215,61,74,80,174,48, - 52,220,164,54,84,71,69,49,129,150,216,188,216,70,122,33,48,214,147,166,61,132,16,92,178,101,138,75,127,252,135,249, - 161,31,252,62,238,189,255,193,240,19,31,250,232,244,175,126,225,243,19,151,156,56,185,237,38,184,98,2,30,15,96,239, - 89,120,188,15,199,190,23,218,7,94,58,62,96,47,157,25,80,24,134,47,151,107,245,47,220,23,86,200,231,1,212,11, - 65,5,252,44,240,79,225,207,21,2,230,20,65,137,63,225,189,247,96,149,49,70,72,141,25,0,14,23,144,249,86,77, - 199,248,122,210,225,74,43,243,141,159,91,153,15,93,56,59,90,169,128,132,120,78,200,170,68,49,68,214,74,81,173,86, - 87,205,182,210,52,93,5,193,32,8,232,118,187,24,107,193,187,98,230,19,132,8,160,239,60,195,205,38,149,74,5,147, - 23,128,83,46,151,87,1,111,229,250,87,6,214,174,184,217,176,198,224,188,71,5,1,38,207,65,136,2,180,156,37,140, - 66,156,47,172,107,81,2,57,40,216,28,133,206,45,43,149,105,27,199,132,14,232,121,143,207,13,165,249,54,173,83,167, - 104,14,53,249,157,223,251,48,159,253,253,15,154,239,59,63,159,222,10,173,20,142,59,152,191,3,230,111,233,244,183,61, - 244,39,247,142,125,248,43,247,133,31,216,185,69,190,229,29,111,17,55,191,234,106,54,76,142,162,149,34,115,57,73,210, - 102,230,84,155,133,185,136,122,115,152,90,189,73,20,215,48,190,104,73,133,0,169,139,64,73,99,251,216,110,66,41,82, - 220,254,198,27,120,211,235,110,224,208,177,127,170,63,242,161,15,79,126,241,211,159,27,93,247,216,227,151,236,236,116,174, - 24,134,7,26,112,87,0,143,77,194,185,114,81,20,95,60,43,0,228,47,142,202,120,62,94,131,112,48,239,249,183,20, - 100,196,191,236,43,182,1,3,46,4,87,206,140,209,202,96,84,177,14,183,182,80,186,75,33,7,91,46,40,244,97,254, - 235,170,158,11,183,98,43,45,149,187,192,162,99,5,152,164,148,24,91,228,207,23,218,44,177,10,94,206,58,242,126,74, - 189,81,35,12,3,74,165,136,110,183,95,8,73,139,80,44,82,147,19,170,194,5,208,218,132,114,169,76,181,90,98,104, - 104,168,104,159,2,137,28,204,145,86,218,172,149,108,245,149,225,55,23,108,239,140,41,18,73,181,214,104,253,28,123,90, - 74,137,70,144,217,156,168,28,23,222,217,214,96,28,72,47,17,97,192,49,151,33,90,30,180,39,183,57,97,187,205,204, - 99,143,179,254,85,215,81,171,14,83,93,88,238,93,9,157,54,4,22,38,34,8,45,148,70,192,191,13,220,205,198,243, - 208,147,135,236,211,79,254,119,243,133,177,33,185,254,230,107,130,247,220,113,135,216,190,117,35,181,122,165,152,115,101,57, - 115,167,79,51,119,118,134,90,189,201,208,96,104,141,42,108,79,156,181,104,41,7,105,181,134,44,105,225,17,108,89,63, - 198,79,255,212,63,98,246,135,254,142,190,251,203,119,79,28,250,131,15,15,143,125,234,51,211,235,178,108,189,133,225,58, - 124,41,40,110,147,231,221,189,230,132,16,124,94,74,162,151,217,222,77,95,196,224,111,97,144,61,120,1,203,192,239,3, - 191,53,152,3,125,83,253,239,115,173,154,143,140,177,161,247,244,40,188,52,86,30,216,149,42,167,152,191,200,231,82,64, - 47,168,124,86,54,75,23,174,227,197,64,114,113,97,251,182,98,249,90,128,128,194,89,183,250,224,59,239,72,211,148,94, - 175,75,20,133,84,42,101,22,22,22,11,16,9,20,105,154,21,32,87,76,131,190,174,178,202,141,65,34,209,58,88,157, - 37,73,41,139,54,234,2,64,52,198,224,6,243,158,149,107,14,130,160,152,177,24,51,240,20,95,177,25,113,88,99,81, - 97,1,186,89,106,8,101,64,28,71,44,215,107,252,201,221,247,177,165,92,162,84,10,176,222,226,45,124,229,143,62,68, - 180,102,154,242,230,237,165,223,58,125,202,212,148,10,250,121,190,45,200,51,43,173,113,147,222,186,141,144,55,65,93,5, - 193,109,16,204,205,46,229,159,248,227,47,166,31,104,103,225,219,238,120,135,172,5,158,141,155,214,51,50,82,39,10,53, - 185,201,232,46,157,167,187,52,71,189,57,76,99,100,132,82,185,134,212,26,235,5,43,221,110,241,227,114,88,215,199,164, - 142,70,89,241,246,59,222,72,239,246,55,4,15,126,226,115,155,190,248,190,127,216,120,125,167,157,133,112,252,17,152,75, - 161,255,124,62,120,49,240,39,66,114,94,8,94,110,217,244,223,246,0,228,129,72,73,30,84,146,57,254,108,13,205,159, - 247,194,157,165,208,127,245,129,95,229,175,94,91,251,98,162,139,242,222,175,12,7,157,181,88,191,162,118,151,120,111,113, - 206,15,120,65,254,207,229,4,5,90,99,173,35,179,41,184,175,31,151,121,231,86,245,86,197,223,187,160,234,27,128,88, - 154,166,56,103,201,178,12,41,19,194,48,36,205,50,148,86,148,227,24,188,39,233,39,69,72,98,150,17,13,196,168,54, - 55,12,53,134,6,3,242,66,130,177,242,245,86,42,177,114,185,24,82,155,60,95,53,81,211,90,127,93,219,168,180,198, - 91,135,113,133,234,62,237,39,3,43,211,2,124,115,147,161,140,32,170,84,89,123,227,53,36,79,31,163,18,104,84,4, - 65,47,97,107,86,38,157,235,114,199,149,215,4,217,149,215,12,103,70,144,228,150,110,150,144,184,54,39,90,139,254,104, - 55,53,203,115,11,44,206,207,243,182,172,231,95,131,15,255,46,248,47,124,229,158,124,230,242,43,213,134,91,111,208,15, - 238,125,148,102,179,196,174,93,219,25,31,29,198,228,133,60,163,179,180,64,187,181,72,165,58,68,115,100,156,32,174,160, - 244,115,206,141,120,7,162,208,240,121,44,214,244,137,133,226,213,239,125,23,31,255,216,167,135,143,127,248,143,182,109,133, - 53,195,16,206,64,127,246,175,112,175,253,101,167,2,220,163,95,158,143,242,183,61,0,5,74,210,109,117,249,254,133,54, - 135,94,12,0,116,30,161,240,74,73,164,215,224,4,94,184,1,232,20,182,173,5,109,71,252,185,43,120,231,139,249,141, - 240,224,132,28,232,187,184,224,255,23,155,45,53,144,118,172,240,129,164,44,196,160,94,21,153,92,248,162,85,11,130,162, - 98,169,148,203,24,99,200,179,140,74,165,138,119,158,60,45,6,201,231,207,159,103,124,108,12,45,53,253,126,151,56,46, - 97,109,78,191,223,93,173,12,86,218,176,110,183,139,28,180,103,43,109,151,25,16,27,87,255,77,206,225,114,143,213,26, - 179,50,243,202,29,65,24,144,123,67,63,237,145,230,93,84,185,66,88,110,224,119,239,96,254,236,25,154,89,74,179,84, - 163,30,164,88,44,198,88,60,1,78,121,188,4,89,142,208,97,9,53,57,41,188,44,5,29,239,57,221,235,241,216,147, - 143,219,108,255,227,217,171,33,120,131,181,250,171,191,244,203,233,145,74,32,174,127,235,237,234,231,255,213,191,226,212,47, - 189,159,55,191,243,173,220,254,166,55,178,97,106,2,157,165,100,54,161,215,94,162,215,94,34,46,149,169,52,134,9,226, - 50,97,169,134,14,138,71,201,228,30,47,5,194,91,156,203,41,137,136,225,45,27,57,5,149,237,69,66,143,254,183,192, - 195,207,235,122,70,18,73,73,153,151,31,241,241,219,26,128,60,80,137,67,126,243,179,15,114,232,204,220,139,118,25,66, - 12,36,9,185,27,108,127,28,97,20,15,34,101,190,222,110,227,27,231,86,43,15,112,150,21,38,235,74,107,124,158,35, - 7,131,95,9,127,106,118,100,76,65,62,92,221,168,249,98,104,92,138,99,164,145,171,179,155,44,203,138,234,42,12,177, - 206,210,104,52,232,180,59,197,32,217,57,90,157,54,227,163,99,116,58,93,178,44,167,86,171,161,117,80,248,74,43,69, - 167,211,193,90,75,189,94,39,138,99,202,23,108,197,46,188,30,127,129,207,245,133,28,40,147,231,228,89,182,218,190,9, - 20,50,181,132,161,194,106,73,180,118,18,211,110,49,179,208,98,56,44,19,90,139,201,186,8,219,67,9,6,255,254,16, - 155,129,145,2,71,70,37,210,92,90,41,177,254,218,107,212,93,101,229,245,99,143,154,219,156,87,183,122,252,190,255,244, - 43,221,127,241,91,31,168,150,206,204,38,63,236,236,210,131,255,249,183,74,255,243,247,63,86,222,244,246,215,68,183,188, - 245,118,118,109,216,136,179,69,234,109,175,219,163,211,238,34,164,162,92,169,50,52,60,76,92,107,12,6,238,131,159,13, - 197,155,67,150,246,40,13,8,16,226,121,54,42,147,80,252,220,121,121,178,174,181,248,38,6,176,94,136,87,36,0,5, - 74,114,126,169,195,175,124,252,158,23,251,82,68,97,77,33,73,243,108,176,249,178,95,183,126,191,208,120,236,194,141,88, - 33,43,176,72,245,156,220,66,172,204,89,46,96,76,127,35,41,49,207,243,213,25,204,202,124,103,69,201,94,171,213,240, - 222,211,233,116,200,178,98,254,179,242,255,148,86,197,60,202,88,250,189,62,105,154,49,52,52,132,177,197,26,62,8,10, - 131,177,44,203,8,195,112,181,101,76,211,20,165,53,81,20,173,126,223,149,107,88,81,213,139,32,40,18,63,6,169,31, - 22,86,171,55,49,232,29,51,151,97,41,252,137,164,128,160,62,132,13,74,156,57,55,79,61,205,9,130,136,72,43,148, - 183,8,111,139,167,61,136,8,61,4,222,146,134,142,52,55,52,156,224,77,55,222,166,127,119,126,81,76,30,63,154,238, - 128,238,206,126,178,212,56,117,46,105,192,137,38,254,216,110,208,189,211,11,235,246,255,234,71,182,253,218,135,62,191,97, - 252,246,215,69,111,127,215,59,216,181,121,35,18,75,154,116,192,102,244,151,231,232,46,207,19,86,134,168,214,170,84,135, - 234,232,48,196,91,71,47,203,232,236,223,239,47,131,118,6,61,1,246,223,82,240,197,190,85,187,212,50,112,191,84,252, - 162,210,168,151,169,232,67,39,165,242,95,8,60,65,158,17,89,59,88,133,190,114,54,102,43,213,207,175,127,250,254,23, - 179,250,1,16,218,58,167,115,235,173,64,104,165,48,3,34,226,133,91,172,11,43,134,149,7,248,194,85,188,86,186,0, - 145,85,169,131,127,14,136,6,9,15,43,132,192,21,146,224,202,223,245,222,19,68,17,146,194,42,35,77,83,196,96,61, - 190,2,122,121,158,175,242,123,242,44,39,142,34,154,205,38,105,150,50,51,151,16,40,141,51,150,48,140,104,54,203,116, - 187,93,172,181,12,13,13,81,169,20,6,102,43,213,207,115,4,199,231,24,217,43,215,185,250,206,254,13,215,30,234,0, - 165,4,137,183,164,38,69,101,80,139,74,32,53,190,18,163,55,213,233,44,204,211,95,92,32,76,44,85,52,35,213,58, - 145,214,160,52,62,235,19,121,131,18,30,167,138,8,160,82,14,187,119,95,169,62,114,234,36,255,208,26,91,129,100,10, - 191,15,184,179,15,143,74,200,53,172,191,26,174,222,62,223,185,254,238,15,124,124,215,255,252,228,159,76,172,123,211,107, - 195,219,239,120,27,187,119,108,36,150,96,178,132,220,102,244,91,243,116,150,102,40,45,86,89,187,126,19,165,210,16,79, - 28,61,65,250,208,195,189,13,112,58,133,153,12,50,1,12,125,139,55,141,2,122,192,31,234,96,53,212,242,101,9,64, - 139,163,227,127,209,251,50,42,203,16,199,15,83,81,154,106,20,21,171,217,139,213,207,243,141,65,133,127,179,181,200,149, - 182,228,2,87,196,213,85,246,224,172,0,193,202,92,200,88,75,150,103,148,227,210,234,223,231,207,40,201,173,181,95,71, - 62,52,198,20,45,214,160,10,209,58,160,215,235,173,206,110,194,48,252,58,80,200,178,172,112,47,140,99,194,32,192,56, - 135,25,84,72,65,89,19,14,192,107,121,185,181,186,142,95,1,62,231,28,225,192,7,104,5,120,130,32,40,4,173,131, - 86,111,229,123,58,107,49,214,226,173,45,102,71,82,22,57,97,74,17,138,194,167,40,136,53,214,184,194,168,222,56,4, - 158,225,13,27,17,155,54,211,106,183,56,115,226,56,159,190,243,43,92,177,121,11,187,166,167,25,174,213,200,136,145,73, - 6,202,145,75,143,119,41,87,111,216,204,3,155,182,198,31,59,122,176,247,110,107,235,17,76,8,40,171,66,175,119,92, - 192,225,12,14,68,240,212,91,224,154,155,91,189,171,30,253,208,167,182,253,241,231,191,60,246,241,27,175,41,95,255,166, - 215,113,205,158,61,140,52,106,64,27,233,37,189,78,135,94,187,71,80,26,229,253,255,241,151,217,50,191,56,171,225,89, - 3,167,114,72,119,125,139,237,146,167,144,246,252,11,29,240,172,148,148,95,206,0,244,23,201,15,132,16,24,33,216,55, - 119,158,208,123,174,153,156,166,30,69,171,67,194,151,123,245,243,27,159,121,128,163,231,22,94,244,203,177,66,8,39,165, - 80,30,172,53,8,41,86,3,9,87,230,49,43,60,153,11,213,241,43,109,145,16,130,64,7,132,65,56,112,31,20,44, - 181,90,36,105,178,250,103,87,248,54,223,56,83,242,222,147,36,9,161,14,8,148,94,101,91,175,104,192,210,52,45,228, - 11,131,207,25,99,80,90,17,199,49,73,146,32,7,127,206,24,75,187,221,38,73,82,148,210,12,15,15,147,166,41,73, - 146,16,69,17,149,106,117,149,39,116,225,28,107,101,48,141,128,204,24,88,201,70,27,208,10,156,115,88,99,176,74,34, - 188,165,174,52,10,137,183,158,92,128,177,25,101,25,18,7,1,253,110,11,39,5,165,106,137,203,110,188,142,153,229,121, - 62,253,135,31,92,122,168,86,209,217,186,245,213,87,109,187,148,219,54,108,2,219,199,5,142,52,119,228,121,198,27,111, - 121,141,252,108,84,105,250,220,149,166,142,62,91,190,62,239,165,85,88,246,208,139,225,204,60,28,140,97,198,195,254,18, - 60,122,11,92,117,77,171,183,231,233,207,221,181,229,107,95,184,107,242,163,219,54,85,119,220,114,179,184,241,198,43,217, - 186,101,35,81,37,226,248,92,139,255,253,239,126,146,214,7,254,168,117,19,60,154,194,163,17,204,236,1,103,249,214,34, - 186,106,192,71,164,226,215,180,38,126,153,235,237,245,55,243,184,134,74,145,36,9,123,103,206,112,205,196,154,151,61,8, - 5,74,50,187,220,125,137,84,63,224,149,20,102,144,199,190,210,130,173,156,231,136,133,114,53,177,211,185,231,126,191,2, - 64,165,82,9,29,232,213,53,249,138,126,235,194,170,105,5,92,190,145,45,29,199,49,12,86,231,113,28,99,140,89,229, - 243,36,73,66,150,101,171,85,138,16,130,126,82,172,227,123,221,238,115,178,139,82,137,82,41,166,217,28,161,84,42,175, - 126,191,21,64,188,112,139,247,156,164,196,13,218,61,57,248,40,180,95,43,219,58,187,210,98,42,133,196,33,241,244,77, - 94,132,57,170,112,224,68,233,201,92,74,181,86,98,106,106,130,109,27,54,50,57,62,78,185,28,115,229,213,187,249,103, - 143,61,232,174,127,246,96,251,232,179,79,199,159,61,114,84,61,178,126,147,104,148,34,122,121,215,39,121,207,118,50,39, - 95,117,253,205,242,159,252,227,31,86,111,254,142,247,86,62,252,145,79,85,62,243,207,126,252,198,239,94,94,232,89,200, - 186,112,207,56,156,186,15,22,215,64,123,4,78,59,120,42,128,173,87,193,206,43,28,123,142,62,123,116,231,221,207,30, - 93,251,137,15,124,184,220,216,48,173,171,99,195,114,225,216,73,179,246,228,217,243,223,9,15,123,248,140,135,71,66,104, - 111,124,158,238,153,223,209,26,67,65,128,125,133,3,80,49,190,87,82,146,90,251,178,7,161,11,171,159,35,103,231,95, - 2,205,23,3,134,113,225,137,140,179,5,33,111,181,109,242,3,23,65,143,16,138,21,73,156,181,102,181,34,82,74,21, - 51,163,129,190,42,140,34,98,91,72,30,86,102,40,23,146,26,87,102,44,23,182,117,74,107,162,32,92,213,128,93,56, - 35,42,170,167,149,245,127,33,82,93,94,90,34,10,67,70,199,70,49,166,216,144,85,202,85,226,56,94,117,67,92,249, - 58,0,206,219,85,194,30,40,172,117,200,65,108,178,247,14,99,115,132,20,88,87,84,117,129,14,144,206,15,0,78,17, - 73,79,20,72,140,82,244,83,67,158,230,140,12,85,152,94,51,194,182,29,219,216,180,125,51,81,169,136,146,206,109,74, - 47,111,177,110,253,8,59,223,125,199,240,167,254,227,47,219,255,98,77,247,157,182,191,116,239,129,167,105,67,84,3,166, - 192,30,17,68,95,242,95,27,254,251,255,224,45,162,119,226,253,220,241,234,75,248,204,85,219,26,31,253,202,3,55,222, - 1,202,67,156,194,23,119,192,201,113,48,1,44,204,193,114,2,199,203,240,88,14,15,108,133,93,219,96,107,222,239,79, - 183,247,31,26,207,246,67,13,206,85,224,217,12,30,1,30,11,225,204,231,192,206,62,15,131,231,95,15,66,190,58,88, - 187,243,237,0,64,171,55,169,16,47,123,16,10,148,228,196,220,50,255,253,37,80,253,200,1,32,42,231,188,114,6,227, - 37,88,139,210,133,77,134,117,190,16,66,122,0,183,106,82,182,82,65,88,187,226,52,168,233,39,253,213,200,158,114,92, - 194,187,162,154,114,23,180,50,23,174,189,47,156,237,24,99,40,85,170,3,50,227,0,12,7,171,246,48,8,80,170,144, - 216,22,12,103,69,146,244,241,222,19,199,49,253,164,143,247,20,145,205,81,12,136,85,250,192,74,139,24,4,33,73,210, - 71,135,146,56,138,113,206,99,140,69,41,143,84,69,88,99,160,53,121,102,200,93,159,40,10,16,88,130,32,6,95,24, - 154,73,41,233,247,123,116,146,46,211,235,183,113,217,149,87,176,235,210,73,154,67,18,69,72,234,13,137,73,208,94,17, - 34,137,116,128,142,52,239,125,199,155,184,235,127,255,150,56,63,187,112,126,18,238,122,7,156,0,170,22,106,30,26,151, - 122,54,29,62,55,115,233,71,62,252,209,202,143,191,117,138,118,251,52,127,247,125,63,192,151,47,191,97,234,19,239,255, - 213,87,191,57,75,76,6,231,170,5,240,180,119,3,71,192,222,83,84,51,157,75,96,38,135,103,162,194,113,117,172,2, - 99,213,34,63,242,188,129,51,227,48,235,160,253,24,216,127,241,188,220,192,33,82,169,87,4,248,252,149,1,232,149,0, - 66,97,24,240,236,161,67,4,103,231,185,134,23,135,59,145,3,235,10,0,114,30,242,178,148,121,5,225,164,144,82,201, - 16,111,61,94,8,4,69,91,226,188,43,204,213,97,96,105,186,146,152,250,28,49,49,205,178,213,121,141,28,56,24,22, - 182,30,174,72,85,85,10,86,140,205,190,193,95,122,165,82,113,74,81,138,99,122,189,222,160,106,241,180,187,221,162,170, - 137,34,164,42,230,81,73,146,160,6,109,185,119,80,169,214,88,88,88,164,20,198,171,121,101,245,122,189,168,148,150,151, - 7,2,219,18,56,137,53,14,200,9,2,133,195,98,93,78,16,104,164,15,80,65,76,183,215,34,233,165,148,203,133,65, - 126,28,133,244,122,29,146,92,48,181,118,45,183,223,188,155,157,59,182,83,137,99,108,178,64,150,245,232,199,160,100,76, - 77,14,227,115,199,252,249,57,14,30,61,194,211,207,236,231,238,251,31,33,201,145,22,102,45,220,99,225,222,160,160,8, - 197,22,154,33,92,247,247,50,155,254,193,175,255,201,213,223,243,213,241,202,223,249,222,157,124,215,119,220,192,77,215,190, - 153,127,121,238,224,240,129,63,248,244,158,61,112,99,15,22,53,28,59,12,73,21,242,157,144,204,21,233,39,253,95,131, - 126,6,51,215,66,16,13,186,162,37,200,230,32,255,106,16,184,207,72,197,130,27,36,226,126,43,15,171,82,104,165,94, - 81,46,139,127,45,34,226,133,32,116,245,196,20,141,40,126,89,128,144,7,114,60,151,126,97,47,159,132,23,53,182,214, - 3,45,48,61,88,172,88,63,55,153,154,116,127,160,75,2,95,8,30,157,69,42,139,195,226,68,134,20,1,160,159,99, - 15,15,88,109,43,131,97,6,9,170,105,154,210,237,245,208,97,161,100,247,30,114,155,23,22,172,43,149,208,160,197,91, - 5,161,129,236,220,230,134,174,237,98,108,1,50,214,59,116,16,96,156,165,213,237,16,5,69,164,78,16,20,155,42,173, - 52,81,41,38,208,97,177,129,27,172,247,251,253,62,81,20,97,173,45,140,225,195,16,103,60,46,7,235,13,65,168,209, - 129,68,74,141,201,13,89,102,16,164,4,2,130,64,98,93,136,115,138,126,63,37,142,45,219,47,217,202,158,203,47,99, - 106,253,24,97,212,71,164,51,244,211,24,194,18,65,60,74,144,37,156,57,113,130,47,127,249,94,190,116,247,221,28,217, - 255,172,239,159,62,237,242,86,151,27,44,173,239,86,122,46,18,242,73,227,221,193,16,142,29,131,52,2,49,5,97,2, - 179,35,96,126,36,237,155,255,249,196,241,171,14,189,118,199,80,126,250,113,76,247,126,242,236,188,127,6,134,119,194,107, - 203,48,12,28,113,176,32,96,113,35,156,222,10,167,247,194,252,113,72,26,66,184,159,10,163,172,3,249,15,228,153,187, - 196,57,150,148,226,95,198,101,132,41,94,255,146,82,223,242,61,243,74,147,142,255,181,153,208,43,32,244,200,204,89,174, - 126,153,84,66,58,10,88,126,234,56,159,187,247,41,190,213,77,196,183,122,28,176,6,242,6,44,74,239,231,107,34,207, - 188,84,37,107,93,193,109,241,224,68,113,203,121,10,79,26,37,2,172,179,171,36,197,149,70,206,11,6,214,167,197,170, - 60,73,18,170,213,234,64,237,110,10,112,241,30,59,224,232,10,64,12,92,8,205,10,25,208,59,210,204,80,42,151,209, - 50,192,38,253,213,25,146,14,3,74,149,50,194,250,194,170,85,7,104,21,210,168,55,128,149,149,126,78,150,166,212,234, - 117,226,184,96,113,175,172,214,87,54,119,133,252,162,184,0,33,21,94,56,180,10,9,116,76,150,118,73,109,138,195,208, - 79,18,70,170,99,92,190,231,50,118,239,222,196,80,67,131,207,112,189,51,228,46,162,92,170,162,136,56,125,126,129,7, - 31,122,148,135,191,120,15,247,222,251,0,237,67,207,158,127,167,243,226,53,208,108,20,65,145,167,198,224,17,97,205,163, - 25,60,49,139,56,50,142,207,239,4,223,0,95,133,228,237,112,184,13,159,15,32,248,187,80,251,245,223,249,218,149,191, - 184,212,209,239,124,245,110,126,228,123,222,34,62,89,154,174,253,183,15,124,114,247,20,118,203,8,180,154,208,217,2,115, - 163,5,24,61,213,133,189,111,131,103,119,121,191,52,158,103,238,7,117,192,175,232,128,255,145,165,133,252,5,79,252,10, - 5,143,23,21,128,86,64,40,177,150,135,103,206,188,44,64,168,36,37,127,231,143,239,226,99,238,165,113,43,252,12,248, - 119,64,138,16,169,243,194,247,123,125,74,104,130,48,32,80,197,107,233,188,67,136,98,51,229,165,89,29,32,251,129,183, - 143,25,200,46,16,197,0,214,73,48,206,162,164,36,138,35,108,226,209,66,224,6,62,60,43,44,99,49,200,85,151,162, - 152,217,36,64,32,21,153,49,36,105,178,170,176,95,33,51,166,73,2,214,83,138,34,156,43,170,176,44,179,152,60,33, - 77,18,26,245,6,89,150,145,231,249,42,137,113,197,107,202,185,162,133,244,88,16,154,60,55,228,166,88,193,91,45,72, - 83,75,210,79,200,146,62,195,163,13,110,126,245,213,92,118,217,38,234,117,112,121,139,180,231,169,149,27,120,17,178,208, - 106,243,244,147,251,216,251,213,175,241,209,79,126,129,103,79,46,32,109,137,53,19,147,184,205,219,199,190,60,59,107,190, - 103,121,222,173,135,52,135,253,105,225,130,123,95,13,102,103,241,253,35,96,195,193,48,247,35,192,195,144,254,12,28,233, - 195,87,134,96,226,187,22,186,67,255,245,195,15,109,126,253,235,47,83,55,110,232,81,249,225,55,197,15,204,44,199,229, - 205,67,53,35,237,216,253,135,78,241,224,153,37,187,246,224,169,43,47,207,179,107,55,194,14,15,95,217,15,15,237,113, - 238,204,127,201,179,236,45,66,176,3,248,80,209,44,191,92,177,65,92,80,120,189,96,33,175,223,178,22,236,229,2,66, - 229,40,224,158,167,142,241,241,123,247,189,116,230,81,131,159,172,245,222,13,85,70,184,227,134,91,56,127,234,56,39,79, - 157,98,126,113,1,235,28,106,176,90,71,136,162,101,49,22,196,96,51,38,4,114,32,236,92,49,154,95,145,56,204,46, - 204,23,85,135,181,69,5,165,20,62,207,87,239,38,99,12,65,24,174,126,222,172,16,26,173,193,243,28,119,72,43,133, - 183,174,16,60,70,17,245,198,16,189,110,159,40,140,137,194,8,194,152,102,163,73,185,84,194,154,156,94,191,143,181,142, - 40,140,144,82,17,4,186,176,243,144,128,40,130,13,165,16,100,89,138,201,45,222,27,22,151,22,169,148,170,220,122,203, - 205,92,127,243,46,42,117,135,164,143,233,89,170,97,21,33,60,7,159,58,206,99,251,246,99,204,97,166,226,156,93,99, - 53,254,160,157,210,177,33,168,156,222,153,131,84,202,195,34,155,88,23,252,198,248,26,110,60,188,47,122,151,115,53,9, - 210,67,107,45,116,52,69,100,114,95,8,62,161,20,39,164,226,113,224,90,147,39,55,57,119,208,192,87,182,192,212,107, - 114,51,242,192,190,83,195,19,165,53,212,70,207,242,254,127,249,86,198,194,243,184,126,159,115,157,173,60,125,90,168,143, - 124,234,145,225,79,30,57,54,180,235,192,209,137,215,56,214,120,24,202,225,75,175,247,254,68,201,123,115,39,80,113,150, - 205,121,202,17,196,75,118,93,190,220,237,253,69,29,223,243,14,56,207,59,0,125,35,8,93,245,18,157,9,73,41,249, - 111,127,124,23,47,37,3,182,213,85,59,176,102,88,249,31,253,185,31,36,112,158,179,167,207,243,228,190,131,60,241,196, - 1,158,126,250,8,231,206,44,176,208,89,160,155,247,11,195,116,64,106,81,196,15,11,129,148,226,185,8,6,241,220,102, - 107,176,59,195,251,226,123,72,165,80,131,129,179,31,172,236,173,115,152,34,178,162,120,109,132,64,105,133,51,6,41,6, - 18,16,231,7,9,164,125,250,253,136,56,46,209,168,15,13,64,199,144,39,41,222,121,162,168,112,163,9,131,136,36,201, - 16,162,79,181,82,37,10,74,228,62,195,120,135,55,197,32,189,223,239,210,235,181,25,159,104,240,250,107,175,227,154,43, - 119,210,108,150,112,174,143,235,41,194,64,98,179,148,71,246,222,207,222,251,30,65,36,125,214,142,198,92,186,103,148,201, - 24,194,160,201,77,87,93,198,19,159,219,75,32,21,129,14,232,245,251,204,31,120,134,109,59,118,211,122,251,119,213,14, - 127,250,195,155,182,155,124,171,131,198,211,48,127,100,0,250,29,33,120,36,8,87,95,176,223,6,46,201,210,214,4,60, - 147,195,179,187,83,119,205,127,251,181,7,154,187,214,191,87,92,219,60,67,205,159,101,230,76,153,251,246,206,185,110,119, - 33,247,113,69,93,187,103,90,230,175,218,36,79,158,216,61,245,135,191,253,169,215,124,167,65,73,104,117,161,245,155,48, - 255,223,87,122,231,36,1,41,249,86,114,87,180,14,8,165,228,149,120,158,55,53,252,115,32,116,246,37,55,152,126,41, - 86,63,223,136,69,165,190,53,89,43,161,90,215,172,95,223,228,146,109,183,241,29,239,126,35,189,94,198,249,243,203,28, - 58,126,150,199,158,216,199,190,125,207,112,226,212,25,102,103,103,233,116,123,197,170,94,7,40,93,84,24,214,121,148,28, - 172,218,189,31,100,204,131,23,133,95,141,148,10,132,68,249,130,173,236,173,99,121,121,169,168,182,6,51,155,162,109,242, - 148,74,33,194,67,160,20,81,41,38,203,115,148,82,196,113,72,28,5,148,74,49,54,203,11,189,21,80,138,203,68,81, - 145,128,154,229,25,198,228,116,187,109,194,40,164,52,112,56,236,251,156,118,171,205,182,205,235,216,181,115,61,59,118,108, - 64,71,2,159,167,100,253,46,81,88,69,88,120,230,169,103,57,250,204,83,44,159,63,202,166,137,42,215,108,158,102,88, - 65,31,129,109,39,16,119,184,114,235,56,13,105,232,231,21,146,204,80,170,8,94,123,251,237,124,255,223,254,219,56,169, - 120,232,115,31,171,237,52,249,176,134,210,62,144,191,9,174,60,104,9,127,60,77,248,62,10,61,85,213,123,22,138,185, - 156,14,32,90,130,224,53,55,111,23,87,239,18,132,153,225,177,19,146,255,245,191,62,213,25,222,123,236,204,22,108,39, - 131,176,23,4,149,71,26,209,248,219,127,234,7,43,251,191,247,13,245,79,253,223,63,185,246,61,112,220,194,145,119,66, - 235,198,129,230,11,88,245,64,250,235,156,8,120,214,26,126,90,134,175,152,213,251,11,2,64,207,13,166,205,75,111,48, - 45,37,255,249,99,119,243,82,179,159,29,100,71,121,128,48,199,229,169,67,250,12,227,60,173,110,159,178,74,169,6,138, - 242,150,113,182,93,178,134,119,188,241,122,122,153,103,113,185,199,204,217,57,158,126,230,48,143,61,185,159,253,135,79,114, - 244,228,97,58,221,101,146,126,66,55,77,87,13,194,180,214,232,32,64,135,18,231,115,108,238,8,116,132,240,2,155,102, - 140,142,12,163,177,180,59,61,140,19,152,44,47,120,63,130,130,91,100,45,181,106,21,237,61,141,161,38,121,47,1,231, - 10,65,129,205,129,194,30,67,233,0,99,115,66,17,20,148,1,239,168,85,202,131,86,78,146,39,41,189,212,18,84,43, - 252,173,191,251,119,120,253,171,175,98,241,244,179,180,151,207,97,115,11,178,132,14,170,156,61,113,130,3,143,239,133,229, - 57,46,223,56,198,186,29,187,136,108,135,60,239,208,77,5,58,140,144,218,227,130,156,53,235,70,169,197,138,161,250,90, - 110,188,241,90,94,247,218,107,185,100,219,86,166,166,198,217,251,212,126,78,8,74,14,154,6,234,59,65,253,123,112,43, - 117,196,144,115,104,10,81,104,27,8,32,246,176,193,193,182,131,181,234,200,123,223,179,142,178,106,243,248,137,26,63,250, - 51,127,96,222,61,51,127,250,45,112,46,131,57,9,202,230,249,154,225,185,220,63,254,201,47,175,249,225,159,121,79,252, - 75,143,31,31,59,249,216,129,61,83,176,41,132,103,95,15,89,157,111,221,123,85,2,111,177,150,131,210,242,155,175,32, - 254,207,11,2,64,5,8,73,18,107,94,50,51,33,161,36,203,173,46,127,231,240,105,254,22,47,238,234,253,27,183,96, - 235,138,119,224,60,130,190,233,206,219,133,222,105,182,143,94,70,63,53,24,23,16,226,193,165,96,139,253,149,140,37,37, - 37,40,85,42,76,79,87,185,241,150,93,228,230,29,116,251,134,153,185,101,102,231,218,204,205,206,179,180,208,97,110,118, - 145,67,135,15,242,196,83,143,49,59,127,142,94,43,39,75,66,156,205,232,185,148,74,53,30,196,225,8,100,32,105,12, - 213,201,50,7,222,19,69,33,81,20,22,121,240,214,210,235,39,40,175,177,61,195,216,240,36,54,207,81,104,132,83,164, - 73,74,46,28,97,12,113,37,68,40,64,73,74,213,42,30,65,110,44,66,132,76,172,27,231,85,183,188,138,43,174,190, - 154,230,112,19,103,251,184,74,147,172,211,33,10,97,105,126,150,39,31,250,2,233,204,73,182,143,196,108,219,53,68,228, - 123,100,221,54,125,93,69,69,138,168,98,177,193,16,157,4,206,156,237,112,190,167,248,161,31,122,31,59,118,92,205,244, - 250,41,234,83,67,52,27,53,234,181,26,181,99,39,232,70,81,216,79,250,227,33,140,70,16,156,129,188,53,232,82,175, - 133,85,251,210,62,176,4,141,26,108,159,129,45,126,199,198,242,214,181,195,56,99,249,195,63,121,138,205,51,243,11,111, - 132,51,125,184,211,193,163,190,16,171,190,102,23,92,245,216,177,153,106,88,169,197,239,248,225,55,203,131,63,122,112,98, - 26,63,145,64,105,14,90,125,158,31,243,231,18,240,3,38,231,247,47,240,120,186,8,64,47,19,16,82,129,102,249,83, - 247,33,206,46,80,127,137,189,248,75,224,71,160,229,224,240,68,43,61,254,197,159,253,207,99,71,222,246,198,96,237,101, - 151,49,189,101,51,107,38,155,84,130,10,206,148,16,190,87,188,243,187,0,239,37,194,123,92,158,161,165,160,57,164,24, - 25,31,65,134,235,64,86,128,106,241,158,110,61,203,115,243,204,156,159,225,244,241,147,156,59,125,134,133,197,5,22,151, - 22,57,112,240,8,7,15,30,165,223,205,9,196,40,82,25,202,129,193,26,75,185,84,42,152,206,229,10,90,199,248,33, - 65,185,20,161,164,160,217,24,90,181,103,53,38,47,12,208,188,199,102,20,13,12,26,29,133,12,141,55,25,30,31,102, - 199,158,29,236,217,115,41,107,38,199,208,10,200,115,76,190,128,144,154,201,233,13,152,126,151,175,253,201,39,57,247,212, - 35,108,31,42,179,253,146,181,52,117,15,210,22,97,92,33,168,213,105,59,152,79,60,179,11,17,199,206,205,179,212,17, - 120,93,195,196,13,202,205,38,135,15,31,98,219,246,181,172,221,48,129,73,83,114,147,80,174,196,196,113,232,252,50,101, - 89,176,158,245,135,128,227,131,155,94,81,100,116,101,69,155,35,43,208,20,176,105,6,198,235,155,135,85,197,58,206,46, - 88,14,239,61,216,251,91,112,198,195,147,192,231,66,120,58,131,97,15,211,18,182,145,137,94,167,103,217,181,125,130,211, - 235,215,214,237,137,147,227,10,170,15,193,121,247,60,154,143,85,188,231,173,214,240,81,165,137,46,2,208,95,13,132,174, - 154,88,67,227,69,2,161,220,57,54,125,249,209,213,160,192,151,218,121,12,150,22,224,225,245,48,58,250,196,209,185,51, - 79,252,218,244,113,21,12,221,63,61,217,172,110,24,11,118,95,125,169,26,90,187,46,104,108,89,175,171,155,214,211,156, - 154,162,28,7,196,74,128,177,24,11,121,90,184,41,138,164,131,84,41,82,46,35,84,33,157,104,140,72,26,195,35,92, - 178,163,9,110,119,161,53,203,45,75,203,93,14,30,60,202,145,67,39,201,82,79,146,246,73,211,62,46,55,132,81,136, - 7,180,46,17,148,234,228,22,112,14,147,246,65,72,194,40,64,202,98,125,223,235,117,25,30,25,97,253,166,205,148,235, - 85,42,165,50,35,163,195,140,142,14,17,70,65,65,114,204,19,114,103,201,16,132,74,162,163,18,249,82,139,71,239,187, - 135,199,239,254,28,81,119,150,119,92,191,141,122,4,157,158,229,124,94,165,151,151,56,191,208,99,190,183,68,39,243,88, - 57,198,82,94,195,232,26,178,38,112,222,210,179,125,230,22,12,19,149,17,102,230,219,172,179,125,16,69,182,89,179,217, - 192,53,234,42,155,57,95,45,193,120,31,42,191,3,173,234,224,117,207,40,76,193,84,241,95,113,2,2,15,37,1,106, - 98,44,64,100,158,115,231,19,162,153,197,246,58,88,202,225,176,131,19,37,232,100,80,22,144,59,240,125,107,92,102,202, - 212,42,150,160,86,14,129,161,8,74,29,16,191,8,254,249,2,11,1,100,121,14,66,62,151,219,125,17,128,190,89,16, - 58,205,213,19,211,47,26,8,189,148,207,233,98,88,121,80,67,191,12,79,108,133,41,97,243,9,119,226,228,100,126,226, - 100,57,189,251,145,242,18,140,207,73,57,121,118,98,108,124,97,199,182,70,237,242,75,163,137,93,219,88,187,101,3,155, - 54,173,103,120,184,73,41,174,33,133,192,186,20,99,83,242,172,143,115,16,170,24,41,52,74,4,152,172,208,120,153,172, - 131,119,41,91,54,142,178,109,227,40,89,154,145,228,9,72,135,207,13,43,89,238,65,92,103,106,211,118,116,92,1,163, - 193,40,208,2,148,24,176,25,87,212,108,114,208,108,12,118,61,222,227,141,199,153,12,225,138,73,70,16,133,32,115,206, - 30,62,204,157,95,252,10,15,63,242,4,103,142,159,98,251,250,73,154,18,126,251,147,79,208,233,91,90,189,46,34,170, - 224,130,58,34,26,162,52,212,164,57,220,68,42,69,234,50,140,77,17,153,65,24,143,42,135,32,83,122,249,50,139,173, - 5,188,243,120,103,9,116,68,164,20,163,55,222,24,62,113,224,200,228,171,113,219,37,76,157,128,217,93,131,139,156,3, - 190,60,184,242,16,220,24,44,43,56,85,130,229,212,48,153,101,57,11,243,243,100,89,38,6,149,140,5,92,225,51,128, - 22,16,166,160,109,185,92,174,212,170,120,221,193,24,231,11,168,198,103,3,144,123,62,89,64,10,216,232,28,39,165,124, - 197,120,41,235,237,215,125,255,95,250,135,118,190,234,7,94,222,255,202,183,252,244,243,240,22,244,194,16,202,230,193,111, - 129,238,52,28,122,22,78,54,10,141,82,213,65,173,4,97,0,113,21,38,112,110,211,248,217,153,141,253,179,51,107,231, - 190,242,181,169,115,48,186,175,82,26,90,90,51,94,141,47,217,16,213,182,92,34,215,93,186,135,77,91,55,177,110,221, - 52,227,99,163,212,235,53,4,10,172,7,161,81,218,16,153,20,163,20,221,238,50,253,36,37,75,250,56,151,99,173,195, - 24,139,205,179,2,95,148,38,51,125,122,173,46,37,81,65,72,139,84,249,64,28,43,112,214,32,132,71,72,5,126,224, - 130,236,44,48,176,214,208,234,185,192,196,52,229,169,135,30,228,83,159,248,20,159,252,212,167,121,246,192,81,134,134,39, - 153,94,179,129,67,39,159,198,165,9,65,24,144,89,75,158,24,188,235,208,28,73,89,187,62,160,81,30,161,155,229,100, - 157,22,82,116,113,222,19,251,18,37,221,192,102,14,173,61,129,43,234,17,225,11,78,212,137,163,135,57,125,242,60,187, - 174,186,150,15,127,244,19,35,87,183,150,54,150,97,106,1,246,255,22,152,54,69,60,242,123,41,34,109,90,224,247,22, - 18,139,103,134,224,248,249,179,201,150,174,117,186,82,18,68,165,216,38,105,55,174,192,90,9,19,14,18,9,163,10,198, - 150,160,22,143,143,212,167,39,154,28,63,118,142,116,102,174,39,97,182,15,221,119,130,255,199,23,51,247,94,220,10,232, - 226,249,230,78,13,168,131,61,6,189,59,160,167,96,113,22,196,99,32,42,69,193,29,55,160,238,97,36,132,241,13,48, - 181,9,166,124,183,191,38,59,120,124,124,249,224,241,137,51,220,53,118,66,136,230,61,81,84,203,214,175,47,169,177,97, - 61,178,101,61,83,91,215,203,203,118,109,102,108,98,140,198,240,48,205,161,97,170,113,137,122,189,74,181,86,34,203,250, - 180,219,203,244,218,93,132,19,104,237,112,206,14,12,226,193,59,129,24,36,138,131,197,123,135,31,176,154,11,242,163,67, - 72,141,64,22,149,17,142,180,215,102,97,118,142,179,167,207,114,255,67,123,185,239,206,59,217,251,240,227,28,63,187,132, - 138,43,132,229,17,82,99,153,61,123,130,56,138,9,75,53,82,91,200,62,42,245,18,120,139,53,150,180,227,153,63,181, - 136,14,219,68,97,76,88,170,224,194,12,143,32,245,41,65,20,144,91,139,164,132,233,105,78,159,56,195,236,185,25,146, - 36,97,98,108,138,160,52,130,109,14,171,126,107,169,82,134,138,5,245,243,192,177,193,235,254,159,40,24,209,6,248,73, - 232,141,194,177,97,56,80,189,247,153,43,230,111,223,58,62,62,218,160,182,102,72,204,47,117,101,29,46,205,225,53,2, - 142,10,216,162,96,247,41,168,238,186,118,103,60,210,28,227,211,31,250,34,122,105,113,94,192,153,26,180,38,46,42,47, - 46,2,208,203,237,136,193,59,178,2,95,3,255,191,128,219,193,46,64,126,51,116,54,193,57,7,7,90,16,59,168,9, - 104,56,24,26,130,177,49,152,188,202,251,41,155,36,19,201,193,131,163,173,3,126,125,251,158,251,39,62,14,245,135,95, - 123,121,227,150,171,183,115,250,204,25,162,184,74,84,170,17,150,107,140,78,174,97,124,106,13,229,74,153,56,14,8,180, - 164,26,23,170,119,235,61,181,122,131,122,179,129,8,229,192,59,68,130,144,8,28,72,69,183,219,165,215,107,113,234,216, - 9,150,206,157,243,51,39,79,249,7,159,120,74,238,59,112,136,217,147,231,124,127,118,209,170,86,175,119,14,66,83,10, - 227,70,173,76,106,5,88,139,80,14,41,53,94,120,82,239,233,165,93,148,201,176,174,224,135,15,53,74,180,211,37,12, - 61,70,154,67,152,220,226,130,0,85,46,225,28,228,72,172,51,120,145,177,220,159,229,236,188,102,236,116,149,161,230,48, - 59,118,78,17,4,17,227,169,101,253,166,13,162,127,252,72,12,84,5,4,255,230,130,215,219,83,172,225,37,176,17,204, - 83,136,153,53,248,253,147,179,11,39,239,253,227,189,35,111,251,161,215,168,87,191,243,186,177,47,30,254,68,242,174,212, - 6,99,240,118,15,109,15,141,253,48,218,222,62,93,126,243,13,91,229,204,124,143,19,31,185,167,255,42,56,145,195,233, - 16,250,209,197,219,249,34,0,189,220,193,104,69,54,145,20,31,190,10,118,67,145,170,144,92,1,203,17,156,217,14,114, - 166,224,171,149,50,168,43,168,105,239,135,71,97,207,180,144,175,171,70,225,149,207,148,101,245,251,47,27,87,233,166,136, - 158,177,44,165,158,185,36,229,236,217,3,28,58,184,143,249,133,54,70,123,124,32,144,66,210,79,18,148,86,108,222,188, - 133,241,137,137,66,212,42,29,169,21,28,56,126,26,209,109,229,242,228,114,110,103,23,242,74,107,174,107,78,157,79,226, - 229,180,31,56,223,159,0,53,14,98,24,178,33,208,147,80,250,96,40,235,255,7,166,3,11,161,42,106,169,32,44,177, - 156,230,180,230,23,64,158,69,135,33,90,6,196,145,165,189,176,72,167,221,98,114,98,146,198,218,245,244,18,207,240,112, - 132,245,9,190,163,72,178,140,52,77,16,10,194,40,70,14,53,88,78,187,60,240,208,19,32,61,111,122,243,107,216,188, - 97,29,37,229,137,167,70,196,113,24,222,0,19,10,170,18,22,30,24,188,198,155,129,27,7,211,171,57,96,10,191,224, - 225,137,9,120,228,177,47,62,59,253,145,117,83,147,111,189,121,157,154,123,223,237,27,126,227,55,190,84,190,177,151,196, - 101,200,14,197,98,88,93,119,201,200,119,124,231,107,75,91,166,199,248,226,167,191,66,248,232,35,115,21,216,239,225,228, - 83,144,253,48,133,19,217,197,115,17,128,94,17,71,14,192,72,20,115,35,18,240,21,176,91,192,238,131,252,36,116,46, - 133,185,46,200,114,145,139,126,44,241,174,63,148,36,85,113,102,97,108,169,213,85,165,164,77,89,9,226,178,100,114,56, - 226,202,75,154,56,225,49,182,137,203,99,146,158,167,211,109,23,246,24,66,160,116,134,74,79,23,158,212,222,209,11,135, - 249,224,71,190,148,223,126,240,196,177,29,48,43,224,148,132,101,93,16,138,151,129,150,4,35,6,131,88,15,83,33,92, - 95,113,178,57,57,62,65,218,238,98,114,83,240,139,140,65,74,129,86,10,139,193,25,139,5,226,74,141,13,187,47,229, - 240,193,195,156,58,125,134,36,201,24,29,29,195,227,73,211,4,173,53,181,90,13,169,11,211,251,70,163,62,8,69,244, - 116,243,28,235,50,142,30,57,193,214,13,235,9,117,200,229,55,220,200,129,63,250,88,93,88,51,166,160,218,1,121,15, - 184,0,56,5,236,40,218,95,12,176,31,210,237,176,223,193,151,111,117,102,205,199,127,247,206,87,255,210,177,29,181,27, - 110,189,90,92,250,125,183,140,223,249,208,147,195,59,154,147,249,141,215,174,141,174,223,51,42,17,130,15,127,250,65,158, - 250,95,31,105,189,23,30,205,224,33,13,103,95,3,182,126,241,150,189,8,64,175,244,10,105,229,244,6,160,212,25,110, - 250,131,205,134,93,58,63,107,175,109,119,79,84,181,126,56,52,230,138,238,153,214,149,109,162,168,28,22,218,45,105,5, - 34,151,184,229,28,1,4,206,17,200,30,85,105,104,148,12,178,92,48,161,133,112,3,235,12,137,179,146,188,30,115,221, - 134,166,217,112,240,68,47,128,167,172,20,95,180,206,159,116,208,11,161,107,33,233,22,193,208,94,129,80,176,93,194,88, - 207,178,115,253,154,77,196,74,112,244,200,17,58,221,46,89,154,225,133,64,75,13,14,188,5,111,29,175,186,246,122,38, - 39,38,56,127,110,150,164,215,47,116,103,67,67,148,202,21,26,205,26,245,122,131,48,12,240,94,144,101,57,74,6,104, - 21,32,132,70,5,10,111,224,244,233,25,150,91,29,180,244,76,175,89,195,147,97,16,250,190,25,235,67,115,59,232,255, - 8,217,138,51,207,255,11,60,58,248,245,187,192,189,19,22,246,193,131,26,134,223,149,25,185,247,75,79,237,121,252,208, - 252,216,174,107,214,234,155,223,124,165,170,52,135,181,79,13,95,190,251,44,95,123,226,4,242,161,131,203,223,105,204,3, - 17,124,214,194,35,21,104,109,0,54,92,188,69,47,2,208,183,211,113,83,19,44,252,192,247,50,188,126,154,143,252,246, - 31,224,238,123,200,190,93,208,50,208,206,123,89,190,152,27,166,26,49,105,175,143,196,163,40,188,168,133,87,40,43,200, - 148,47,108,223,125,48,136,193,25,152,224,83,248,66,75,29,82,25,169,49,186,99,93,176,240,197,199,101,3,150,188,231, - 96,9,14,244,33,17,224,215,20,196,74,4,48,3,242,68,209,242,204,220,234,205,204,153,78,107,104,242,170,87,149,135, - 170,77,22,22,23,201,77,78,102,114,28,5,243,186,211,110,177,48,187,128,179,142,44,73,217,181,99,7,195,35,163,84, - 42,85,116,80,100,95,25,155,208,79,250,88,55,176,166,149,122,160,247,76,168,86,27,68,165,42,253,196,113,238,252,121, - 238,186,235,46,174,187,250,74,238,191,239,126,150,250,125,37,96,212,193,72,0,186,83,152,205,83,5,222,116,1,0,181, - 128,115,96,99,56,157,195,23,21,44,222,12,87,181,142,159,189,116,230,248,217,173,7,84,80,127,186,81,169,45,90,167, - 77,43,177,219,124,222,121,3,254,145,10,124,34,133,47,215,224,244,221,96,211,65,251,252,170,139,183,229,69,0,250,118, - 168,130,134,223,242,70,26,183,221,76,84,175,97,146,84,76,13,15,249,33,240,206,24,43,133,200,109,175,103,79,37,37, - 174,220,115,9,174,223,66,249,28,235,44,120,135,82,18,229,29,214,131,68,161,181,92,181,0,89,177,252,80,74,33,188, - 70,212,37,211,87,108,211,251,27,149,198,37,203,221,77,185,247,123,114,232,89,56,103,161,55,13,70,2,243,141,42,98, - 215,70,39,239,123,106,209,195,145,117,48,183,113,238,252,154,92,7,229,230,208,48,181,90,157,86,187,77,16,6,131,88, - 159,12,49,54,73,111,178,87,8,95,131,8,173,131,129,149,71,66,150,103,196,113,132,64,144,13,162,154,181,10,16,97, - 225,85,148,36,9,185,113,68,253,132,126,214,102,124,188,193,198,141,27,24,159,152,96,253,244,26,191,8,153,129,146,132, - 178,5,245,143,120,110,19,118,225,249,18,112,5,240,17,72,167,224,168,45,10,203,39,202,176,99,35,92,177,193,230,235, - 174,88,88,26,77,11,32,115,1,28,17,112,103,14,119,213,225,248,207,67,246,137,111,24,114,95,60,23,1,232,149,59, - 164,110,212,217,247,246,55,211,125,235,155,217,150,36,120,239,105,59,207,142,64,115,165,16,116,189,79,74,176,56,109,252, - 242,209,99,167,39,237,27,174,195,7,2,47,13,129,26,228,194,11,240,88,180,1,37,3,132,44,124,36,44,30,55,8, - 6,76,7,126,67,42,207,152,110,14,241,7,245,242,200,174,94,186,125,60,55,42,47,102,185,79,90,56,180,23,206,4, - 208,146,73,154,29,58,122,150,42,180,135,224,128,18,28,191,172,181,188,225,107,231,79,143,150,154,77,149,180,179,65,212, - 50,228,105,74,191,223,39,12,2,192,145,246,83,162,56,162,223,235,145,244,43,69,245,99,12,81,20,144,101,41,2,49, - 8,106,84,244,122,125,230,231,231,209,90,83,42,101,196,177,230,250,235,174,226,134,27,174,102,168,86,248,16,110,219,182, - 149,3,149,170,179,221,142,18,160,67,16,215,1,179,65,72,62,136,164,6,138,106,108,64,146,237,0,219,33,95,128,249, - 47,192,210,142,98,179,245,132,128,33,7,163,162,248,112,18,78,117,225,208,90,56,255,31,33,255,196,197,219,242,34,0, - 125,59,12,163,37,16,215,106,168,95,254,207,44,76,77,48,209,235,147,196,49,86,41,68,171,229,127,231,137,167,57,224, - 61,255,16,250,30,63,55,10,173,39,79,30,243,56,35,164,119,40,99,81,94,22,188,65,4,74,134,69,150,186,51,120, - 81,176,156,189,0,239,192,230,41,161,20,133,133,173,115,108,27,30,97,121,98,93,229,39,23,186,219,94,27,48,246,234, - 212,109,158,118,254,42,233,253,129,4,246,37,240,116,150,230,199,55,156,155,95,152,128,252,12,28,55,158,199,54,165,189, - 109,15,28,124,106,77,239,234,107,170,81,8,214,130,247,57,120,75,165,20,22,238,140,170,204,210,210,18,103,207,158,197, - 218,124,53,39,205,121,71,191,215,45,140,236,189,165,181,188,76,187,221,65,74,77,185,92,102,120,116,140,184,18,115,237, - 181,123,184,241,166,27,8,66,129,119,6,139,103,108,205,26,49,51,54,90,237,119,59,149,10,52,129,248,111,9,217,186, - 87,107,102,133,64,175,12,247,133,160,159,38,171,175,177,162,160,62,255,30,216,159,131,37,15,45,11,50,40,200,161,161, - 7,50,72,246,64,118,28,220,177,139,183,230,69,0,122,37,159,128,98,215,126,28,120,24,248,114,158,19,255,247,247,35, - 173,165,7,188,15,120,167,16,252,215,52,67,29,61,193,247,131,114,208,80,48,18,10,21,157,93,108,139,204,59,148,42, - 30,46,33,61,82,136,194,224,204,155,129,255,52,131,225,115,33,173,112,194,23,90,46,57,176,65,115,158,106,213,115,245, - 149,235,248,204,254,131,165,195,81,163,244,39,50,29,191,50,207,214,223,108,237,37,187,172,189,162,238,121,54,133,71,12, - 236,157,135,163,14,22,44,236,45,121,191,249,182,163,135,71,254,200,166,91,231,155,35,177,203,29,65,16,82,142,202,104, - 37,137,74,37,116,16,225,40,92,18,17,208,238,180,240,120,22,151,150,57,55,115,22,53,240,59,170,84,170,140,143,79, - 48,50,58,86,132,22,106,205,80,189,198,21,151,239,33,12,21,144,35,148,67,0,19,35,77,122,107,55,132,231,142,29, - 107,108,131,181,93,24,218,229,221,236,118,107,253,169,11,42,32,6,32,116,161,101,139,184,0,240,123,224,158,1,183,9, - 204,229,208,203,129,125,192,26,224,244,197,118,235,34,0,189,18,43,29,53,248,200,129,135,128,95,6,142,80,172,143,73, - 18,120,228,177,213,63,191,56,0,169,53,192,111,128,170,195,154,30,220,164,165,186,233,161,90,48,189,239,124,143,133,118, - 194,186,50,248,92,224,165,4,21,129,243,56,145,129,0,233,229,32,56,112,197,5,177,176,129,45,174,199,147,251,24,35, - 36,187,166,107,12,37,22,167,5,115,26,245,105,17,14,127,1,221,188,50,79,166,111,79,211,141,215,122,191,85,194,250, - 30,124,193,22,46,168,135,114,184,115,155,177,35,239,62,121,50,252,23,231,231,182,46,73,45,99,1,101,95,38,172,6, - 4,177,64,26,138,181,251,248,48,97,57,226,158,7,238,69,15,12,243,165,80,12,213,154,140,143,143,179,113,227,70,198, - 199,199,87,141,238,179,44,199,59,75,24,6,104,161,177,54,195,81,68,92,87,171,21,154,235,55,201,199,249,234,208,46, - 216,100,96,179,135,179,151,102,105,251,75,20,86,28,223,76,187,43,191,97,238,118,225,231,46,158,139,0,244,138,57,126, - 240,67,73,6,15,199,255,6,22,6,31,127,217,89,6,222,11,250,16,76,117,224,213,177,16,119,252,65,168,111,254,61, - 236,72,48,55,199,137,83,103,217,176,107,109,49,244,21,133,188,66,10,89,44,204,133,3,235,87,99,148,189,16,72,33, - 46,176,36,47,172,95,173,205,153,152,24,165,82,138,232,11,192,56,34,47,72,201,196,3,81,84,123,84,168,218,219,109, - 191,249,221,150,114,232,92,71,120,206,106,56,105,138,124,244,53,151,24,63,125,117,224,38,254,68,209,200,77,78,223,38, - 116,151,123,164,243,93,34,89,12,154,159,126,118,63,198,89,186,253,30,34,145,40,37,25,106,12,179,118,237,90,38,39, - 39,209,90,51,55,55,143,247,131,156,51,15,222,103,124,228,35,127,204,238,221,151,177,118,237,52,195,35,117,20,160,149, - 230,242,171,46,229,87,62,72,253,102,216,185,6,110,152,131,147,59,224,192,15,22,94,76,95,87,101,30,0,210,139,183, - 225,69,0,250,118,4,30,63,0,158,47,1,63,55,40,241,191,217,179,161,0,160,82,38,196,250,16,110,18,222,191,229, - 127,135,209,109,31,13,228,8,94,146,167,57,39,207,205,195,101,91,16,178,91,0,138,16,43,145,96,224,197,64,219,229, - 7,96,35,193,23,15,183,240,224,10,89,59,206,121,214,173,157,98,100,180,206,177,249,101,2,10,206,144,146,162,136,241, - 9,34,62,150,155,225,237,222,172,189,21,182,58,24,61,11,39,171,112,62,16,60,161,189,191,242,170,220,108,249,114,16, - 52,144,18,239,40,90,60,29,20,154,89,41,56,114,252,88,145,119,95,174,96,237,202,160,92,112,250,244,25,206,156,57, - 75,16,4,40,165,8,195,16,107,29,165,82,76,165,82,103,97,33,225,228,169,5,154,205,50,235,214,79,176,123,247,78, - 166,215,108,224,29,111,124,43,7,126,232,168,254,191,127,248,123,219,222,215,90,190,182,6,15,108,47,218,195,60,185,160, - 146,81,60,71,74,188,216,82,93,4,160,111,139,147,15,110,248,50,80,1,126,1,248,234,224,255,93,251,77,180,6,51, - 192,15,0,187,10,150,239,142,208,251,215,57,120,221,199,75,149,43,63,22,139,17,107,50,148,137,200,172,101,223,193,83, - 184,219,175,47,36,93,66,12,4,254,174,248,74,131,141,216,10,223,90,8,57,120,240,139,100,213,213,105,137,51,148,99, - 69,163,22,194,156,35,80,69,112,33,222,128,213,164,169,231,93,239,253,110,17,156,56,84,239,223,251,181,161,16,234,1, - 168,25,200,182,121,206,59,56,59,105,109,187,12,62,149,66,56,233,240,72,148,10,112,182,224,79,7,90,35,132,196,120, - 143,10,52,214,89,150,150,151,49,253,156,198,80,131,122,189,78,173,86,163,82,169,18,199,37,202,229,50,72,73,84,138, - 209,58,34,77,4,207,62,125,154,82,216,100,114,124,61,165,178,228,231,255,245,207,240,131,7,247,71,199,239,252,210,240, - 229,133,46,76,253,18,112,248,207,120,93,35,224,141,23,31,142,139,0,244,237,112,222,77,33,64,45,1,223,55,248,248, - 171,156,7,11,200,168,44,195,174,42,188,245,172,224,45,255,167,92,218,253,181,32,46,121,103,80,190,224,252,122,1,7, - 14,159,33,51,30,137,7,87,4,31,10,236,32,190,65,32,6,182,26,43,109,13,12,76,237,253,115,21,129,115,142,56, - 150,52,234,49,74,8,130,160,132,183,57,121,238,169,70,37,222,247,227,63,192,123,190,243,187,248,147,127,251,239,195,62, - 68,10,74,77,144,83,133,71,78,23,88,28,242,190,87,177,206,116,33,208,222,226,172,199,75,191,90,69,57,15,222,90, - 164,80,68,81,192,248,240,36,235,166,166,105,84,170,212,107,53,162,184,72,99,245,64,16,4,120,239,72,115,75,24,150, - 80,90,83,175,87,217,118,201,22,182,109,221,194,190,167,158,225,240,145,131,212,155,195,28,59,120,144,184,120,41,228,95, - 84,229,164,192,191,161,96,73,171,139,183,232,69,0,122,41,156,215,189,128,63,0,199,95,221,59,216,82,236,148,255,65, - 193,109,217,80,134,55,158,144,226,237,255,169,84,185,236,105,233,149,50,109,132,139,240,94,35,149,65,4,130,227,39,230, - 152,95,88,102,178,38,138,21,188,119,56,225,138,172,120,231,89,137,133,6,135,144,131,49,235,74,37,228,28,194,21,195, - 233,176,172,24,27,174,17,42,141,183,144,102,25,245,106,147,31,249,123,63,196,59,223,115,19,67,13,205,182,233,233,220, - 20,224,40,50,16,187,129,253,133,139,96,167,38,72,34,103,157,87,69,58,42,20,241,63,198,185,34,181,195,67,41,42, - 209,108,52,217,181,107,23,107,166,214,80,45,87,240,222,145,231,57,214,88,188,240,56,231,177,174,216,118,149,162,18,227, - 19,147,172,89,211,228,234,171,118,35,4,60,187,255,41,102,102,230,168,86,135,248,195,15,255,49,115,167,79,249,38,194, - 88,188,141,192,95,79,225,11,244,103,101,118,61,53,152,7,133,23,111,253,139,0,244,82,56,175,127,137,93,143,27,180, - 108,145,16,101,188,223,217,22,220,242,191,170,181,221,251,4,74,231,30,79,9,43,50,188,43,188,252,132,146,204,156,91, - 224,212,137,51,108,188,98,29,125,91,184,25,22,98,11,177,106,30,38,86,36,175,162,0,31,111,61,110,80,25,121,231, - 81,94,80,14,67,166,166,70,233,118,30,166,20,72,46,221,115,25,87,94,117,25,141,122,141,102,99,132,201,169,113,246, - 251,126,222,43,170,12,57,68,65,238,235,128,40,131,172,120,196,168,208,249,113,124,36,112,72,100,33,173,16,16,232,128, - 209,145,81,46,217,114,9,107,166,166,89,55,189,22,129,160,159,244,73,173,67,106,93,52,141,82,226,115,67,58,96,70, - 215,170,130,13,235,135,184,245,182,155,112,38,231,216,177,147,76,142,79,179,115,199,30,158,120,242,81,190,118,255,221,236, - 12,117,214,200,178,37,160,149,130,249,135,252,249,142,133,154,130,45,109,46,222,250,23,1,232,165,112,174,123,9,94,211, - 192,178,163,166,97,243,211,65,180,249,113,108,232,51,135,245,113,97,24,166,52,94,166,224,21,82,4,36,253,132,19,167, - 206,227,175,90,11,62,7,4,14,3,34,44,160,200,249,1,15,72,172,14,156,157,119,184,66,147,138,214,10,239,53,4, - 33,67,205,58,245,106,153,239,120,247,247,176,126,243,6,114,155,51,185,102,146,161,102,5,103,115,116,92,97,48,85,18, - 150,98,163,103,33,244,66,12,133,80,90,111,93,239,33,29,84,157,7,229,65,120,135,84,69,250,170,86,154,229,229,37, - 146,94,66,187,221,102,168,222,64,107,77,84,142,144,82,16,133,1,214,58,80,138,204,230,56,239,89,106,45,243,232,99, - 251,112,214,176,107,215,22,54,109,154,162,82,174,35,101,196,254,103,75,140,140,76,17,47,119,140,134,89,96,126,25,204, - 201,191,164,197,242,131,121,144,189,120,251,95,4,160,23,251,76,191,4,193,39,7,206,123,31,199,48,124,88,138,70,99, - 98,138,106,59,97,110,118,17,35,250,8,47,145,212,80,58,67,136,132,4,203,211,71,23,200,165,2,215,67,16,23,187, - 103,167,17,94,34,164,29,12,157,45,120,139,16,197,0,88,138,128,48,16,72,37,232,186,58,123,15,180,104,140,172,225, - 167,127,250,199,144,170,142,115,33,213,74,133,52,239,144,89,143,146,30,19,202,192,21,69,141,110,23,12,98,74,5,214, - 196,66,16,189,38,235,157,251,92,216,168,38,65,165,44,179,30,18,139,117,138,229,86,155,36,205,88,88,94,34,77,83, - 180,86,72,45,169,132,49,163,245,33,226,82,137,40,42,81,169,84,137,74,37,26,205,38,205,161,6,22,203,236,242,18, - 159,251,220,253,220,253,149,199,185,100,251,122,118,239,94,207,244,134,53,188,254,246,155,121,231,99,111,227,225,95,248,69, - 43,160,21,66,119,30,236,255,230,185,104,158,63,235,100,20,118,29,53,10,191,160,139,231,34,0,189,168,45,207,75,13, - 128,6,251,43,7,100,77,155,102,54,77,89,183,126,19,235,214,173,167,155,46,49,115,126,129,78,59,37,79,83,84,160, - 80,50,228,233,103,14,147,244,37,129,45,33,209,8,233,80,72,156,8,112,88,36,96,109,62,232,194,4,58,208,132,129, - 166,155,123,14,29,155,227,201,103,102,88,232,69,68,141,105,140,212,68,161,38,75,22,233,46,11,170,149,53,104,145,16, - 136,58,93,21,199,182,88,238,53,60,68,39,161,83,7,35,240,253,204,35,246,120,228,143,244,58,79,254,102,197,93,149, - 196,34,200,19,137,246,197,171,236,125,97,207,90,252,90,224,12,116,178,30,121,63,39,140,66,172,177,32,36,185,177,212, - 235,117,166,38,167,104,12,53,104,14,15,81,111,52,232,119,251,236,123,230,0,135,142,28,96,100,180,206,117,175,186,134, - 207,125,250,19,220,14,139,1,204,247,160,183,13,252,251,191,201,7,164,51,168,148,46,174,230,47,2,208,139,118,142,191, - 196,174,103,133,176,88,21,162,155,195,204,30,47,230,245,226,210,244,227,179,79,210,104,196,76,174,153,100,203,166,75,8, - 180,32,237,119,88,110,167,204,207,44,112,232,232,57,206,47,100,108,24,109,128,237,227,101,134,243,57,194,150,240,214,225, - 144,168,160,76,138,164,159,195,249,249,22,231,102,206,114,236,76,151,197,126,128,46,13,227,43,49,185,146,148,202,101,146, - 52,33,77,36,198,12,102,73,153,7,235,104,197,97,220,130,177,113,216,24,194,104,13,22,13,116,173,231,24,130,115,192, - 206,203,181,72,74,185,205,19,17,7,222,231,120,231,8,163,8,6,22,32,141,70,131,126,63,161,92,174,224,140,69,139, - 194,34,68,135,1,90,43,66,231,201,179,156,131,7,15,161,165,162,82,46,177,231,242,203,24,25,155,64,139,128,44,73, - 8,84,157,51,103,102,88,56,122,156,221,136,89,131,63,13,116,142,81,108,187,196,55,241,58,91,96,248,226,35,112,17, - 128,94,204,243,95,94,98,215,99,128,49,224,31,120,223,13,224,244,136,245,51,147,222,154,185,32,210,237,118,155,229,103, - 59,184,92,80,175,133,76,77,78,176,105,235,86,110,121,245,109,52,68,198,3,79,156,96,97,195,36,181,74,64,84,146, - 4,65,68,137,162,95,234,244,115,206,47,182,57,126,182,197,249,165,140,110,30,96,9,208,165,117,136,90,72,46,13,173, - 222,34,218,164,180,250,45,188,21,144,137,34,129,79,131,166,2,14,108,37,16,167,161,118,21,236,202,96,23,112,62,130, - 94,7,14,43,207,19,61,33,214,253,161,100,251,178,242,101,209,55,132,50,196,169,98,160,12,20,110,137,65,72,110,44, - 105,146,16,71,49,66,20,219,50,173,52,121,110,8,195,16,188,99,180,89,101,120,120,132,201,137,73,74,149,8,169,60, - 206,11,130,82,5,39,52,79,221,247,128,255,206,126,119,121,13,254,132,135,147,25,244,254,3,112,146,111,110,203,213,5, - 110,5,110,227,162,252,226,34,0,189,72,103,221,75,176,37,44,1,11,144,141,195,233,10,226,200,173,214,93,249,180,204, - 71,141,112,88,43,144,66,145,36,41,71,79,156,224,196,185,179,4,58,100,203,212,52,71,142,214,24,170,55,80,90,82, - 46,69,52,135,70,9,17,116,90,139,24,15,72,69,230,4,137,51,232,168,76,165,86,67,137,5,44,65,161,13,243,17, - 206,20,137,24,38,233,19,12,146,127,58,253,46,86,120,2,33,25,91,183,65,252,110,173,217,188,178,189,184,117,28,110, - 238,65,55,128,243,18,154,66,136,94,46,232,156,80,58,244,97,5,37,28,214,22,2,8,235,44,74,42,162,40,38,10, - 2,112,30,225,60,54,55,244,243,156,82,169,132,146,154,168,28,51,49,49,65,189,86,99,168,209,160,217,28,70,75,137, - 193,144,123,67,154,36,212,202,53,70,199,155,44,60,60,107,111,183,98,57,192,207,121,88,60,15,230,125,131,1,243,55, - 219,86,245,41,12,203,236,197,86,236,34,0,189,24,231,255,188,68,175,235,36,228,7,224,140,240,126,223,245,38,191,254, - 163,165,112,244,180,9,16,206,34,149,71,200,128,220,231,228,105,130,49,134,39,158,125,150,103,15,41,130,40,64,133,138, - 90,181,70,37,170,163,162,128,48,10,152,24,159,68,75,133,205,60,90,104,42,101,79,191,221,163,50,236,209,21,141,18, - 17,129,42,33,92,177,150,215,178,80,206,219,204,97,179,4,21,105,142,30,60,76,103,185,207,252,218,13,149,163,207,44, - 70,27,225,218,0,70,92,241,12,107,229,253,90,9,161,206,93,230,227,40,10,171,134,110,167,131,203,139,73,139,117,142, - 126,63,41,248,62,182,32,73,214,42,17,227,35,195,140,142,140,48,54,62,78,185,92,70,8,65,20,69,132,97,136,195, - 97,188,47,88,222,30,134,155,37,94,115,235,141,92,113,217,78,246,239,154,214,159,124,232,222,230,219,230,59,99,14,38, - 214,66,244,86,200,155,127,141,215,123,255,96,30,148,93,4,162,139,0,244,55,121,222,248,18,188,166,21,50,226,251,96, - 217,195,201,9,231,103,174,116,62,61,165,227,72,248,46,206,25,50,35,33,16,8,161,48,153,65,160,232,91,79,47,233, - 33,140,163,211,239,17,171,101,84,84,38,140,42,232,176,74,163,90,71,88,143,12,32,199,18,7,154,82,169,134,14,66, - 132,119,40,85,100,135,57,60,120,133,113,10,37,28,19,195,35,28,56,116,138,167,247,237,227,181,175,187,141,255,241,203, - 129,123,8,22,79,104,61,229,188,92,103,181,150,21,33,92,57,64,46,161,117,59,170,134,161,75,81,222,131,85,56,71, - 225,196,40,11,167,67,147,27,194,32,64,41,73,20,6,84,74,101,134,26,13,162,32,32,237,247,169,54,26,232,64,99, - 173,33,8,227,85,7,199,169,201,9,110,189,237,58,46,217,58,141,20,150,235,111,186,154,167,254,209,251,234,135,126,238, - 63,239,188,4,174,204,225,217,99,112,164,249,215,216,45,236,24,84,159,103,185,200,146,190,8,64,127,131,231,170,151,224, - 53,57,10,95,227,65,10,69,38,4,182,42,165,143,131,136,110,210,41,18,75,157,7,227,16,210,162,101,128,49,133,221, - 134,0,92,46,177,94,18,232,18,181,48,160,18,56,122,243,243,140,148,107,84,26,53,148,10,64,74,226,161,6,42,8, - 200,250,73,33,4,149,26,132,32,8,11,20,244,214,161,132,103,238,252,121,164,150,188,238,117,175,165,90,21,172,153,26, - 13,207,93,115,203,229,95,61,115,60,156,154,92,167,174,189,226,90,230,44,72,161,169,212,74,220,184,116,134,207,124,242, - 19,136,68,18,171,8,21,12,70,194,206,35,4,72,37,49,214,32,148,198,98,49,121,70,175,219,69,107,77,181,90,197, - 230,25,137,183,84,42,101,180,86,244,147,62,151,94,186,155,55,190,225,54,154,67,1,206,119,81,129,32,235,119,120,239, - 251,126,132,223,253,220,87,214,245,239,127,248,234,0,30,109,195,185,195,208,9,254,26,149,140,184,160,45,63,199,75,111, - 67,122,17,128,94,129,231,223,188,68,175,75,22,109,129,159,7,183,224,157,168,199,37,182,148,202,246,169,118,87,9,153, - 35,2,1,46,66,122,131,215,33,66,245,17,89,134,114,154,76,10,82,219,65,228,41,36,26,235,202,172,153,154,64,201, - 152,40,168,34,20,212,26,85,2,93,162,159,244,208,218,33,116,128,84,17,74,122,2,157,17,8,65,154,90,38,39,167, - 216,188,101,29,155,55,77,115,234,244,49,198,71,167,24,25,25,99,120,100,93,105,118,110,158,157,107,215,177,102,184,78, - 47,43,172,99,227,200,147,14,130,14,51,233,49,94,96,242,124,224,69,45,176,214,21,50,11,33,200,83,135,23,109,210, - 180,143,33,35,138,67,74,165,152,80,23,154,176,21,213,126,160,2,170,37,73,179,161,49,166,139,214,18,239,11,185,199, - 80,179,204,238,31,127,95,229,228,119,255,200,206,109,206,93,106,224,169,3,208,221,86,24,63,254,181,78,147,98,25,176, - 27,248,247,20,12,199,139,85,209,69,0,122,65,206,31,189,68,175,203,1,13,176,35,48,223,176,156,152,232,180,58,253, - 114,117,180,26,196,136,32,34,174,134,196,186,138,182,146,118,183,67,43,179,100,42,64,228,154,177,48,227,93,239,184,137, - 237,107,70,233,217,18,103,90,57,194,149,169,54,70,136,75,21,84,160,9,227,152,78,59,33,38,70,0,214,88,140,109, - 81,171,86,24,170,15,17,70,138,93,59,118,16,87,34,230,230,103,249,204,103,238,100,105,97,137,55,189,233,117,100,166, - 207,252,252,28,89,102,9,130,18,201,32,215,203,11,48,182,136,127,86,74,209,79,123,8,61,16,205,14,56,64,98,96, - 134,239,189,39,203,50,242,44,3,231,232,245,82,164,10,112,192,232,200,24,198,58,242,60,3,4,129,214,236,125,248,49, - 214,174,159,224,242,203,183,35,101,177,206,199,65,158,165,92,121,219,109,60,181,115,251,164,219,247,204,118,9,147,33,156, - 121,166,224,115,126,75,175,191,167,16,20,87,46,206,133,46,2,208,11,117,190,239,37,124,109,39,33,63,4,103,34,120, - 102,93,183,119,110,36,10,70,71,118,236,164,147,245,176,174,143,237,59,172,140,73,236,60,86,122,84,73,97,179,14,183, - 223,176,153,159,253,123,155,137,84,10,229,6,169,108,98,41,225,228,24,186,60,73,88,153,192,137,6,157,174,225,247,255, - 224,83,204,205,45,115,242,216,97,254,249,79,255,191,28,58,116,152,251,239,123,136,230,72,147,153,153,51,68,113,68,146, - 88,164,8,145,42,230,240,225,83,44,183,114,218,157,30,149,106,153,82,57,194,59,79,158,231,8,37,145,66,226,133,160, - 214,168,179,116,182,93,180,92,131,217,207,138,53,170,49,6,231,28,222,23,45,89,24,6,24,239,56,122,226,24,75,75, - 75,108,88,191,145,141,27,55,161,117,33,205,16,194,35,68,192,87,239,188,135,233,233,73,214,172,25,193,56,131,24,24, - 240,215,26,13,162,87,93,85,93,220,247,204,244,16,140,151,32,88,15,185,184,120,123,95,4,160,151,250,249,249,29,91, - 191,181,86,73,10,122,189,132,67,199,78,174,38,156,246,6,239,160,1,127,125,23,62,75,145,111,254,67,133,33,226,177, - 181,130,179,99,237,206,142,153,209,80,215,74,17,129,170,16,170,18,105,234,24,31,242,44,247,115,172,208,228,181,30,83, - 163,107,8,114,205,222,199,78,145,5,150,141,107,107,132,13,141,170,70,104,175,200,243,148,74,217,48,180,174,70,179,17, - 240,129,15,126,17,242,148,7,30,188,143,61,151,95,205,210,167,238,164,159,229,180,147,121,42,165,33,182,111,221,77,167, - 187,196,114,107,137,71,31,125,156,115,231,218,68,113,25,17,44,34,148,69,135,33,185,183,164,105,138,146,18,235,29,185, - 177,168,32,192,121,139,214,154,44,203,96,80,25,173,176,161,87,0,41,183,14,235,115,132,23,204,204,207,34,148,164,90, - 171,50,210,28,37,12,61,198,88,148,22,156,57,59,207,222,189,143,243,174,119,223,142,183,14,63,16,211,134,129,100,250, - 150,87,169,153,223,252,192,240,48,212,13,4,107,249,139,229,24,23,207,69,0,122,73,156,31,187,255,179,223,210,223,47, - 151,75,220,119,223,94,110,185,245,157,171,159,251,238,65,217,254,216,96,142,176,226,126,250,87,121,71,94,81,197,183,33, - 13,133,56,27,59,78,78,119,251,189,195,46,173,135,185,32,119,125,124,45,192,235,128,106,125,152,225,177,6,97,92,129, - 60,195,233,46,198,78,112,223,125,207,240,197,131,135,185,100,119,137,218,80,7,212,12,167,207,156,36,77,186,236,216,178, - 129,127,243,255,253,4,27,55,77,49,50,220,96,100,104,156,123,238,185,143,137,137,105,208,37,130,40,166,89,213,156,63, - 187,72,107,185,195,249,185,89,188,128,135,30,121,4,80,236,218,185,147,165,86,225,96,152,231,22,131,35,75,115,178,52, - 37,203,83,180,214,224,41,204,200,212,115,96,99,173,69,74,185,218,142,57,239,87,171,35,231,138,225,250,201,211,167,233, - 245,82,46,191,116,15,235,214,173,71,107,61,168,162,44,173,78,191,176,154,5,148,84,32,37,198,231,108,189,226,82,230, - 154,181,154,91,108,55,83,40,125,165,136,150,126,65,206,27,47,62,54,23,1,232,249,58,85,251,173,237,58,132,117,148, - 221,215,79,8,110,43,230,55,84,129,255,10,156,31,252,186,207,115,62,65,249,55,1,72,10,120,24,76,15,102,180,243, - 135,174,108,47,207,124,117,126,182,174,70,214,160,93,68,63,237,35,101,128,86,101,210,110,70,156,27,226,72,112,170,53, - 71,223,247,152,152,108,32,207,72,74,19,163,76,111,220,76,175,103,57,112,114,14,239,20,79,63,123,134,179,231,186,172, - 157,30,167,94,21,132,186,196,194,210,89,30,122,244,49,78,159,63,199,184,24,98,98,106,140,36,57,195,236,220,89,42, - 149,33,54,109,222,204,179,7,247,243,192,131,247,48,221,29,193,121,69,210,179,40,209,199,88,135,49,22,155,27,112,48, - 212,24,98,126,113,97,80,233,72,130,32,36,203,50,164,44,92,25,165,112,40,165,177,174,168,140,242,60,71,41,85,152, - 232,75,197,242,242,34,243,139,11,76,79,175,41,116,109,58,196,139,136,32,136,17,74,129,43,190,142,160,240,179,30,25, - 109,34,170,149,42,139,237,241,16,42,103,64,156,42,162,164,47,2,208,69,0,122,233,158,11,227,90,254,90,0,228,253, - 159,250,26,43,70,100,43,118,15,45,224,43,3,16,42,81,48,117,71,41,72,111,127,225,215,6,198,192,183,97,209,10, - 177,127,93,150,31,158,154,111,109,156,31,153,10,162,40,34,176,142,146,6,157,27,50,81,168,219,51,23,112,248,196,34, - 39,103,151,216,176,105,8,189,183,69,127,169,11,137,35,150,130,169,225,33,150,206,157,102,235,230,38,190,127,156,114,216, - 163,81,83,216,20,186,189,20,227,44,141,161,26,179,179,51,132,90,18,137,152,245,235,54,80,169,85,185,246,186,203,121, - 226,233,251,184,251,222,47,241,244,211,251,208,170,138,223,185,7,173,53,173,238,50,198,24,194,64,67,110,169,150,203,68, - 113,140,77,0,239,17,12,236,95,61,197,38,204,250,34,169,195,129,212,98,144,146,225,177,206,98,93,138,22,154,118,167, - 77,146,37,4,161,64,168,16,188,98,121,185,75,158,231,32,36,14,129,146,10,165,4,214,89,150,189,11,37,212,98,8, - 143,131,248,217,23,104,118,252,211,23,31,155,191,124,52,113,241,37,120,233,28,65,161,77,154,0,190,8,28,5,182,3, - 123,254,146,143,75,129,203,129,0,223,75,225,217,80,240,192,119,47,47,28,12,14,62,109,246,31,57,202,242,226,18,42, - 112,136,114,142,174,26,116,41,64,135,101,156,141,57,188,255,8,219,71,21,35,21,201,98,199,18,148,170,148,43,37,74, - 33,216,108,129,157,219,198,56,115,232,46,204,242,51,76,52,43,56,159,163,180,160,181,180,204,200,200,16,185,201,72,186, - 125,230,231,150,144,42,100,211,166,9,46,191,98,51,165,82,132,146,101,112,33,206,164,180,58,139,228,89,142,201,114,242, - 44,39,75,51,140,117,40,169,16,222,83,45,151,169,213,106,68,97,56,112,201,231,185,132,14,60,90,235,194,255,200,217, - 255,191,189,55,15,146,44,59,175,251,126,247,222,183,230,90,123,117,109,221,93,189,47,211,131,30,204,210,192,12,177,11, - 6,33,130,32,77,82,166,68,195,33,129,4,69,74,54,35,108,81,98,72,38,195,132,21,150,195,225,176,197,144,130,52, - 29,148,40,155,146,76,64,65,90,129,85,32,9,96,176,204,0,179,47,61,189,77,239,93,189,212,94,149,149,251,91,238, - 226,63,94,246,0,8,1,3,96,134,164,12,76,158,142,138,138,232,204,172,170,124,121,227,188,239,126,247,59,231,96,116, - 94,52,166,17,4,65,136,117,133,43,163,31,4,164,73,74,110,50,150,110,221,228,206,242,90,17,43,141,195,106,7,86, - 160,173,163,107,139,248,69,59,176,224,31,98,72,64,67,124,155,202,104,21,248,220,160,89,125,237,123,32,175,147,14,61, - 226,220,45,141,248,242,209,180,251,213,191,209,106,172,244,182,26,92,190,241,50,23,206,93,228,230,237,37,122,237,109,186, - 93,135,113,154,209,160,196,75,55,218,4,85,159,233,168,205,230,214,38,205,78,147,64,132,4,50,166,229,199,252,238,191, - 127,130,243,151,215,153,240,50,38,188,30,41,45,140,77,8,114,159,74,28,144,226,104,247,52,123,22,231,216,119,116,47, - 111,121,248,1,68,232,168,213,107,56,87,70,250,1,202,47,230,122,250,253,4,147,107,116,154,99,181,195,104,71,41,46, - 19,123,62,229,40,24,156,98,57,130,208,7,97,113,194,96,156,6,225,6,22,172,134,220,228,32,239,58,56,10,148,10, - 25,169,141,81,10,107,24,93,228,153,42,101,200,18,205,210,213,6,74,21,75,92,72,176,100,32,60,66,43,173,43,10, - 75,163,192,149,138,10,242,207,253,107,136,225,22,236,7,186,26,130,194,80,231,171,20,230,245,63,69,113,90,230,190,195, - 157,35,7,222,3,157,147,206,157,239,195,243,7,123,189,147,123,43,229,217,139,8,181,186,177,196,78,179,196,214,102,13, - 188,6,50,72,169,170,58,47,118,251,236,252,181,26,7,22,119,113,231,220,26,221,213,179,116,243,189,140,149,170,148,168, - 48,58,162,8,186,91,160,199,136,199,171,44,63,187,66,185,84,97,125,189,69,73,167,28,61,124,136,249,137,69,14,44, - 78,115,234,129,123,168,213,203,128,102,110,102,2,103,18,162,168,134,114,146,70,99,27,207,11,200,146,12,173,13,189,94, - 15,99,13,158,39,208,218,160,133,37,203,50,58,157,14,8,129,49,166,120,159,178,120,167,58,207,64,184,194,138,213,57, - 36,130,114,185,202,194,204,28,81,24,98,157,197,243,36,82,21,179,205,58,55,220,185,179,140,179,135,94,73,251,80,190, - 162,219,92,102,188,215,105,1,155,29,232,253,44,184,15,51,156,102,30,18,208,16,175,250,33,245,129,255,7,120,43,69, - 148,204,93,147,172,111,70,27,120,59,184,16,58,73,161,60,111,151,132,176,66,250,202,137,30,185,145,180,58,61,172,200, - 208,46,99,211,180,184,157,106,254,241,239,126,145,191,245,254,123,120,231,67,251,161,26,3,77,164,55,193,187,222,249,1, - 22,230,15,50,165,110,178,185,125,145,140,132,67,71,70,153,156,156,68,246,124,42,163,37,198,103,107,236,158,154,224,212, - 91,78,48,49,81,198,217,14,66,195,7,127,252,199,248,228,39,30,229,169,167,159,38,10,2,218,237,22,213,106,141,36, - 73,73,211,140,36,73,16,82,48,57,53,73,84,46,115,103,229,14,150,98,230,199,1,158,231,21,122,48,99,94,177,232, - 16,131,198,51,22,172,113,4,129,79,92,42,84,243,206,26,114,173,145,158,135,64,160,148,160,209,216,38,77,19,124,79, - 96,172,66,18,211,90,90,33,110,117,219,2,182,29,244,119,81,56,30,14,49,36,160,33,190,7,252,52,240,19,192,19, - 131,187,118,192,183,118,80,13,176,14,166,94,88,143,54,234,190,49,70,91,223,19,49,198,129,181,109,180,177,56,23,163, - 2,139,245,53,159,124,244,44,207,188,120,139,221,187,103,56,116,120,140,67,11,83,212,107,109,234,11,33,75,91,207,179, - 122,227,50,89,175,203,242,102,204,244,244,4,181,186,207,248,220,12,165,114,141,217,189,99,220,127,114,150,209,233,58,56, - 9,248,160,51,198,167,39,248,231,255,236,127,229,23,126,254,111,115,249,234,18,189,44,101,187,181,131,29,196,237,36,3, - 151,198,173,157,109,148,231,35,165,194,225,80,210,67,155,98,0,209,31,52,156,139,237,150,43,236,98,1,207,11,144,158, - 164,86,174,18,120,10,37,7,30,214,131,92,69,229,43,132,146,8,225,13,46,142,68,160,145,100,172,222,106,210,3,95, - 64,41,6,191,199,95,156,197,198,232,112,185,14,9,232,135,13,201,96,91,246,78,224,89,96,135,226,196,204,251,166,173, - 89,9,180,131,237,0,54,102,250,173,190,243,227,200,90,129,24,244,85,144,10,103,2,140,235,33,124,31,75,153,91,89, - 206,202,173,45,158,91,234,17,184,171,40,207,65,52,69,165,62,198,226,158,89,142,239,153,39,40,69,108,53,183,88,223, - 218,225,186,189,138,146,17,60,99,248,220,103,29,229,72,49,59,63,203,190,125,139,28,61,122,15,179,51,33,187,15,44, - 242,214,71,30,230,220,203,87,144,73,194,198,214,6,113,24,147,244,19,250,253,62,97,28,209,207,18,154,173,22,210,83, - 131,137,103,129,211,69,211,217,57,135,26,76,71,91,7,74,250,72,36,129,23,18,135,33,161,31,130,83,148,203,37,162, - 56,194,104,135,31,201,98,230,40,213,196,113,140,231,21,77,109,15,9,120,172,145,114,14,198,143,195,180,134,242,93,253, - 214,144,128,134,4,52,196,247,8,67,161,196,126,25,248,53,160,1,108,125,211,227,191,10,246,175,67,223,65,183,158,219, - 76,6,2,161,114,156,17,88,235,33,132,69,73,141,209,6,163,66,156,144,248,57,196,158,163,54,82,161,82,153,97,98, - 215,36,181,177,17,42,21,71,111,167,207,185,11,231,89,93,91,102,179,177,77,179,185,137,116,22,233,43,178,212,130,246, - 17,46,39,174,88,164,231,51,90,155,224,239,254,242,207,243,139,31,249,48,207,61,253,44,22,104,118,90,196,186,68,191, - 215,199,58,135,167,20,221,126,151,92,107,242,60,47,234,27,103,177,182,168,114,140,49,4,65,128,239,251,197,228,52,69, - 142,189,51,130,122,165,198,216,232,24,66,72,74,229,50,81,185,130,148,30,65,24,19,134,1,202,43,198,30,234,245,42, - 158,95,2,231,112,169,98,237,218,10,127,242,249,47,176,0,210,129,151,22,38,144,194,127,229,220,109,136,33,1,13,241, - 61,33,7,222,11,60,10,252,51,96,134,98,34,186,15,28,43,66,119,50,5,189,58,46,19,206,33,132,1,225,144,162, - 140,19,41,214,36,40,1,206,106,164,176,164,38,71,152,18,19,81,133,242,72,68,63,111,177,115,169,69,171,113,135,78, - 163,73,39,181,164,182,143,39,3,112,17,34,16,120,65,113,196,45,194,24,79,122,8,149,224,16,172,110,36,116,58,154, - 151,47,92,228,244,75,103,200,45,228,198,224,229,26,231,123,36,73,31,41,69,17,52,168,53,89,94,76,58,69,81,132, - 49,26,41,213,43,83,208,214,218,34,185,213,82,16,82,224,227,73,15,171,161,82,45,17,132,33,97,28,33,253,0,49, - 232,138,9,225,136,162,144,99,199,143,131,133,139,231,175,114,250,249,179,156,127,249,44,243,147,7,153,226,139,29,96,51, - 130,238,24,184,128,161,136,116,72,64,67,188,38,56,138,38,234,223,1,62,62,40,251,19,32,130,158,7,235,39,181,219, - 156,205,211,217,155,24,229,91,64,152,65,12,188,68,8,131,20,26,235,4,82,56,66,149,147,52,239,208,182,101,178,92, - 225,76,137,82,181,74,125,122,138,78,71,226,59,77,57,14,112,78,17,198,49,35,99,163,148,226,16,63,18,84,226,49, - 38,198,166,200,109,70,189,50,202,47,254,194,127,193,191,253,131,255,131,237,198,54,65,101,12,144,228,90,19,197,33,214, - 26,180,30,68,66,15,100,22,206,21,249,207,190,31,144,164,41,97,24,17,69,33,58,215,69,106,171,18,4,65,64,41, - 42,225,6,178,140,60,211,4,126,81,37,1,120,126,64,181,90,193,138,132,82,20,209,106,237,240,135,31,251,18,215,175, - 44,225,203,136,95,252,165,95,224,137,175,127,157,165,223,163,237,96,93,65,183,207,95,156,187,225,196,112,121,14,9,232, - 141,64,64,119,19,50,182,128,83,192,20,112,186,24,31,218,30,15,131,246,131,165,48,189,209,77,74,86,170,162,242,81, - 69,195,215,90,240,60,31,79,80,104,165,140,132,176,140,8,170,76,78,140,16,71,49,129,31,82,42,151,145,162,208,89, - 5,161,162,94,169,50,179,107,134,137,137,73,28,14,39,13,158,240,80,8,226,146,224,145,135,239,71,216,46,173,110,78, - 92,25,33,51,133,61,172,181,57,73,226,80,170,176,227,112,20,138,119,156,35,80,30,105,47,65,248,30,126,20,227,71, - 49,206,8,20,130,114,88,34,183,57,185,179,36,58,167,28,151,145,30,72,233,104,55,155,148,226,152,82,165,130,51,57, - 59,141,62,78,100,228,229,140,79,253,135,79,83,138,75,188,253,221,239,226,161,83,135,9,227,18,238,209,62,1,100,18, - 82,13,230,189,124,247,25,171,215,243,217,12,49,36,160,55,84,37,180,14,236,20,125,213,178,47,68,252,114,158,151,190, - 214,151,37,127,208,233,16,66,97,140,123,197,248,235,174,221,133,4,130,80,224,156,161,92,41,225,123,146,40,10,8,131, - 128,192,87,72,169,136,162,144,74,165,68,224,251,197,105,150,148,120,74,18,68,49,161,10,169,87,75,28,62,62,77,37, - 86,124,229,203,79,178,111,225,94,222,254,240,187,121,244,241,79,225,251,1,86,23,106,119,165,84,49,84,168,53,82,74, - 164,82,228,70,227,121,62,115,51,211,136,129,126,203,24,131,53,134,192,15,232,38,224,140,38,12,67,170,213,26,213,82, - 137,145,250,40,56,208,58,71,98,73,91,77,16,29,250,253,62,219,166,207,187,223,243,54,62,240,193,247,49,58,85,197, - 101,109,176,134,104,106,156,185,169,41,161,215,215,221,247,18,203,51,196,144,128,222,208,149,141,25,124,72,187,40,74,154, - 18,223,26,21,156,2,71,65,156,7,239,33,8,182,161,156,20,102,91,71,34,231,30,74,60,127,98,203,6,56,12,190, - 39,9,195,136,110,183,251,138,202,28,4,214,22,19,200,89,146,208,100,7,33,4,181,106,141,44,203,25,31,31,35,46, - 197,72,225,176,78,179,211,106,80,142,74,4,126,128,53,154,137,169,41,132,130,169,201,136,131,251,22,200,82,201,179,79, - 159,69,103,57,247,221,119,148,185,133,159,231,133,211,143,227,132,36,85,26,1,36,73,242,202,239,191,75,132,206,83,164, - 24,86,183,214,241,157,0,235,240,252,16,148,96,164,28,226,17,146,181,13,58,213,244,58,29,226,32,160,213,106,146,166, - 41,165,94,137,76,103,88,44,113,24,80,45,141,16,71,117,118,205,206,50,58,91,67,247,183,49,82,32,156,34,8,66, - 162,169,113,225,214,215,69,34,165,192,14,71,16,135,4,52,68,209,60,29,144,75,31,216,11,140,23,167,234,126,8,234, - 223,12,134,159,75,224,54,192,104,208,17,216,117,80,83,66,212,183,157,219,19,192,108,9,102,29,28,234,195,177,203,176, - 248,25,231,38,115,44,146,162,250,81,74,49,49,49,65,154,166,228,121,142,181,208,235,246,72,242,12,223,243,200,179,46, - 253,110,74,171,212,33,10,183,185,117,243,22,190,239,227,251,62,113,92,98,116,108,132,133,185,57,234,181,58,155,91,107, - 204,206,142,112,248,224,62,230,231,75,52,183,55,184,118,169,199,72,117,146,227,199,15,82,29,243,216,189,56,202,169,251, - 30,225,107,79,63,131,31,22,39,89,189,94,239,149,247,92,88,108,0,72,20,2,157,102,120,126,0,14,242,44,67,42, - 133,116,146,241,145,17,118,207,237,197,89,139,201,52,82,120,40,165,216,181,107,154,241,137,9,132,242,176,194,81,41,133, - 72,25,163,115,88,222,218,192,184,62,218,43,92,151,60,167,88,156,159,231,214,160,240,169,84,171,194,53,155,195,133,55, - 36,160,97,181,3,133,26,126,180,56,30,142,238,133,154,129,81,11,147,41,212,227,193,103,101,192,106,232,118,97,219,66, - 170,160,228,57,119,208,194,67,43,112,20,41,199,111,213,170,187,26,39,79,142,239,126,251,59,188,195,205,166,252,242,239, - 253,139,65,165,99,233,118,187,56,231,136,227,152,169,169,105,70,71,198,169,86,43,180,90,109,182,54,55,201,210,28,165, - 36,198,88,38,38,38,25,31,31,71,8,193,216,232,56,165,82,137,145,209,58,66,8,210,44,195,152,140,118,103,155,61, - 123,223,74,175,189,77,210,117,28,62,186,64,165,86,193,201,140,92,167,148,234,227,156,58,245,16,143,62,246,85,124,79, - 210,75,122,56,91,88,108,216,111,138,98,86,8,164,149,248,161,95,24,145,57,135,181,14,207,8,154,107,155,244,194,62, - 211,115,62,115,51,187,144,82,226,43,69,16,248,148,43,101,164,82,224,64,105,200,123,25,81,92,194,23,10,229,2,164, - 243,9,188,24,145,129,240,4,183,175,95,38,105,236,184,0,108,144,36,246,16,223,16,1,15,49,36,160,55,20,238,78, - 50,123,192,75,224,111,195,136,15,115,33,44,90,88,20,176,96,96,174,11,99,41,120,10,80,96,21,180,125,216,12,5, - 105,28,69,229,164,159,204,239,204,206,28,204,254,171,159,155,147,11,123,228,76,125,130,189,229,50,89,175,203,187,75,49, - 31,255,216,199,217,222,217,65,74,133,49,150,110,183,83,184,4,58,75,158,231,248,254,60,167,30,58,69,165,92,45,44, - 44,40,230,112,188,193,132,178,214,26,157,21,196,36,164,194,247,124,114,33,209,54,225,220,185,11,28,63,190,159,131,139, - 123,153,158,142,192,43,38,108,180,201,10,159,103,107,185,255,161,147,148,75,1,137,205,209,90,23,91,75,99,64,12,200, - 71,41,180,115,168,200,43,172,93,179,194,55,8,41,200,76,142,31,68,196,165,128,208,247,233,247,250,196,97,132,147,10, - 223,47,114,226,115,173,9,130,8,63,10,81,190,135,23,23,199,249,189,180,79,175,101,72,147,46,43,55,110,112,231,153, - 103,89,253,253,63,104,237,190,179,114,221,192,182,78,83,253,171,195,101,56,36,160,55,114,229,51,11,226,131,80,217,130, - 61,62,220,39,225,254,46,28,219,169,148,23,178,67,123,199,163,251,78,148,107,71,78,4,37,63,166,84,46,145,246,58, - 180,87,238,216,213,149,101,221,104,181,92,98,80,87,111,222,82,135,222,247,62,239,248,219,222,33,150,87,183,105,111,236, - 208,189,122,19,155,167,228,121,70,28,149,193,53,6,149,5,24,171,139,74,8,65,224,71,92,191,126,157,213,149,85,14, - 29,60,196,209,163,71,41,87,202,164,105,97,155,161,117,142,231,121,248,129,196,247,138,35,115,132,67,121,1,121,98,232, - 39,9,207,60,119,150,253,123,23,8,60,176,178,136,242,81,158,194,232,156,76,119,57,118,124,15,19,83,35,92,188,118, - 3,103,45,131,248,46,148,87,84,65,74,41,100,16,98,125,15,145,101,28,83,158,59,172,84,190,183,84,182,143,26,237, - 223,240,148,10,203,17,74,74,60,169,16,82,14,12,235,65,121,1,129,167,240,124,69,169,82,65,202,0,47,240,137,3, - 159,180,159,240,167,159,254,18,219,43,55,104,127,245,139,122,241,241,39,239,236,109,182,159,5,254,204,193,21,32,29,97, - 120,90,53,36,160,55,68,185,227,8,162,144,221,129,79,158,229,76,2,199,65,25,152,84,112,111,0,111,111,194,195,75, - 243,147,71,43,63,243,51,19,199,62,248,99,222,222,147,135,9,203,21,154,205,14,237,141,6,59,155,29,182,219,93,58, - 51,123,81,38,15,246,197,37,158,126,242,41,174,108,231,196,205,62,222,197,139,120,94,21,163,193,58,133,242,3,74,149, - 18,83,227,19,220,188,121,3,161,36,32,145,72,148,80,69,206,86,210,197,26,135,53,134,75,151,47,210,238,180,216,189, - 123,55,51,51,51,175,24,201,131,64,9,137,177,57,18,133,117,96,140,35,240,67,242,76,115,229,210,45,110,222,92,230, - 208,225,5,64,224,164,196,57,81,168,218,173,101,116,162,194,193,67,123,57,127,249,26,129,167,200,180,198,9,65,113,16, - 47,113,210,99,26,120,176,215,79,222,150,235,205,195,206,173,214,178,180,17,109,111,143,236,175,215,247,255,47,229,242,88, - 224,251,228,14,82,163,137,131,10,202,247,17,74,81,169,214,112,56,2,79,17,74,69,88,170,224,132,38,105,174,177,249, - 242,6,249,205,149,124,242,210,153,237,61,27,203,87,74,198,60,101,225,177,28,94,168,192,74,2,230,129,225,202,28,18, - 208,27,130,127,146,132,99,15,156,100,233,63,123,23,55,63,243,103,92,6,21,192,116,14,143,4,240,254,51,146,71,58, - 31,120,239,222,247,127,244,127,8,14,221,123,47,141,173,45,46,157,187,204,213,203,55,105,108,247,72,181,33,213,144,234, - 62,89,102,168,84,66,46,95,188,204,167,62,249,71,244,186,9,187,23,231,241,164,34,112,32,68,76,238,43,82,154,8, - 153,48,59,51,70,240,66,128,243,4,185,51,4,25,72,2,82,211,39,239,25,98,47,194,218,20,227,52,102,217,176,181, - 189,77,179,217,100,110,110,142,122,189,142,239,251,72,63,196,106,31,163,53,224,240,132,197,104,141,211,150,220,120,156,63, - 127,135,253,7,23,17,50,47,230,145,133,4,5,78,88,188,48,228,240,225,227,216,79,125,1,35,61,82,37,177,18,170, - 6,142,89,97,223,150,233,230,3,253,254,157,133,60,187,162,224,98,238,220,149,20,26,26,246,239,233,245,126,236,17,193, - 67,87,54,55,162,242,174,24,105,37,189,230,54,196,49,165,145,81,68,183,139,236,103,208,107,131,238,89,215,221,209,213, - 205,181,254,194,214,102,123,180,211,109,84,90,173,59,10,46,89,56,173,225,180,129,107,93,104,229,96,134,42,248,33,1, - 253,224,117,138,95,243,235,29,202,247,249,92,24,112,95,241,63,117,3,15,89,248,169,143,73,222,51,246,119,126,105,242, - 239,255,227,223,164,219,94,231,11,159,253,20,55,110,238,208,110,129,192,129,44,178,176,76,174,89,95,95,35,138,74,108, - 110,44,243,248,227,143,209,235,167,56,41,217,105,117,200,115,69,224,28,34,239,80,246,60,2,127,140,52,239,179,231,224, - 49,68,240,53,210,212,224,2,129,81,6,231,122,88,13,89,174,49,174,77,20,248,104,13,89,154,211,15,19,148,148,180, - 90,45,198,199,199,25,31,31,167,62,50,74,28,151,17,66,160,117,142,186,187,205,234,91,148,15,75,55,111,209,108,118, - 168,215,67,44,22,196,55,196,165,8,193,201,55,221,67,232,41,166,149,112,187,16,118,183,148,233,35,90,111,28,205,147, - 235,37,99,46,230,112,33,131,139,22,150,20,108,196,144,165,112,201,215,58,255,112,171,125,167,215,237,207,245,183,215,199, - 76,24,134,185,16,194,58,135,148,210,73,132,8,172,37,74,211,60,72,211,166,103,244,154,7,235,2,86,44,172,89,184, - 237,224,102,14,203,211,176,179,1,217,39,128,95,228,91,199,25,134,24,18,208,255,175,33,74,175,207,182,92,4,62,171, - 183,111,243,123,79,61,207,63,128,192,135,125,62,188,235,179,240,246,234,223,251,149,201,127,240,27,191,202,141,171,215,248, - 202,87,94,164,223,55,40,95,96,85,134,115,18,97,171,24,151,147,230,109,234,213,10,198,88,46,156,63,67,171,221,64, - 170,8,139,230,250,205,37,238,187,255,17,212,104,153,40,48,4,34,197,237,180,8,101,64,109,126,150,127,244,143,254,59, - 158,121,254,12,159,250,211,79,225,2,1,58,71,80,38,10,21,34,75,200,50,131,211,125,4,105,97,16,102,52,173,86, - 139,157,157,29,58,157,14,225,218,26,181,106,157,90,181,74,185,92,70,122,10,43,0,89,184,43,110,108,111,177,190,182, - 201,216,216,158,226,116,203,13,196,163,88,208,154,197,253,251,248,201,35,135,242,159,184,177,212,155,108,119,151,125,99,206, - 225,220,121,13,47,167,112,217,192,114,79,136,102,197,247,147,11,158,111,30,74,250,108,88,123,117,196,185,158,112,238,217, - 178,205,166,43,121,54,37,122,189,210,160,133,228,238,222,23,92,209,208,207,5,108,3,171,6,182,51,104,4,208,201,161, - 215,133,254,4,216,125,224,250,3,226,17,195,222,207,144,128,126,160,8,40,42,189,190,31,32,235,4,255,242,119,249,123, - 183,151,69,6,19,62,220,127,11,30,156,248,200,223,156,254,165,223,252,135,60,245,245,103,121,233,165,203,116,123,25,16, - 162,240,16,50,68,231,25,142,46,97,232,97,173,67,9,201,157,59,183,232,118,59,100,38,67,170,0,33,12,155,55,175, - 163,154,219,16,180,192,53,168,69,41,39,142,204,51,191,231,0,99,115,135,136,199,39,105,172,174,242,147,63,185,204,51, - 103,95,194,151,96,16,56,151,83,169,84,49,214,145,155,188,232,7,89,203,206,206,78,49,115,99,12,198,24,194,32,228, - 70,118,3,107,45,227,227,227,76,79,79,179,123,247,110,194,40,34,205,50,250,73,206,202,234,38,135,143,238,25,76,88, - 187,66,115,38,36,96,217,53,62,198,125,202,211,83,141,237,29,7,143,167,240,105,13,23,34,216,172,67,247,113,200,43, - 74,33,222,249,30,236,252,110,158,250,250,99,212,94,62,223,115,112,195,193,173,42,132,14,162,154,84,190,21,66,8,163, - 95,225,15,1,244,193,88,72,51,72,98,208,135,193,252,11,112,15,243,141,184,35,201,55,38,159,135,228,51,36,160,31, - 44,200,215,227,242,235,179,178,118,147,223,252,151,255,154,143,64,148,192,225,28,30,217,60,116,226,224,207,253,198,175,169, - 39,190,246,36,79,62,113,13,99,115,60,15,132,208,88,171,112,70,32,148,68,121,61,44,22,129,160,219,233,210,106,183, - 104,236,52,0,131,167,124,156,235,48,26,231,132,233,69,222,60,57,202,190,153,128,241,218,24,206,131,157,214,13,46,175, - 53,104,232,29,30,126,211,65,254,218,143,190,135,231,94,58,143,47,125,172,211,72,207,32,125,159,192,243,169,40,0,73, - 224,135,180,90,173,87,44,82,181,214,68,81,52,240,232,129,181,181,53,54,54,54,72,210,148,137,201,73,162,40,6,33, - 88,91,109,96,173,3,103,80,210,199,57,112,206,98,141,198,143,61,250,187,38,252,68,200,173,192,217,23,36,60,51,15, - 107,255,70,74,247,246,19,111,102,227,194,75,200,44,163,49,62,65,82,171,211,154,156,98,230,229,243,220,4,115,13,204, - 135,32,107,67,251,183,172,161,193,55,220,32,7,213,15,191,9,116,129,167,129,69,224,71,128,165,193,247,97,94,251,144, - 128,126,240,241,75,31,121,29,87,217,99,102,117,157,95,185,179,194,29,24,173,194,61,107,130,19,39,63,250,235,99,171, - 235,91,156,63,123,155,94,218,163,20,71,248,170,168,180,172,203,208,166,141,18,10,167,61,228,192,21,48,73,50,218,221, - 30,105,102,200,116,70,73,194,104,181,198,63,252,200,125,188,247,68,149,216,211,108,172,246,249,202,217,62,59,193,4,170, - 94,193,90,203,243,47,60,198,98,188,195,91,222,188,143,145,145,17,250,205,62,82,21,199,234,89,174,169,214,106,72,9, - 158,244,81,202,43,60,155,141,161,84,46,83,169,86,201,178,194,203,89,12,254,85,171,85,60,63,32,207,53,206,245,9, - 188,136,173,237,54,105,146,17,132,114,64,62,174,16,171,90,240,163,0,87,45,75,131,107,201,162,55,211,254,223,193,157, - 149,146,131,135,142,32,174,188,12,89,134,52,6,97,12,106,144,29,47,191,169,202,113,20,105,33,235,223,230,18,255,253, - 193,115,135,194,138,33,1,253,112,226,247,254,245,235,122,121,90,220,161,131,16,22,82,184,71,189,255,253,187,71,238,63, - 36,31,251,15,143,210,235,121,120,94,136,39,61,28,26,156,5,103,17,214,67,103,96,156,198,247,36,78,56,180,161,232, - 215,72,69,20,251,216,118,198,252,212,40,15,28,153,227,230,245,13,158,191,154,144,149,246,50,119,244,65,14,223,115,148, - 201,93,19,40,4,43,43,151,184,126,229,22,15,190,243,4,123,15,236,225,236,51,103,65,130,176,30,54,203,6,166,96, - 150,192,131,206,118,131,44,203,16,66,20,67,130,90,227,28,248,97,80,36,150,122,133,29,71,165,82,193,247,124,156,133, - 208,143,104,182,123,36,105,70,169,84,193,9,133,47,60,172,21,24,157,162,100,64,85,6,22,231,114,1,89,2,246,143, - 40,28,29,255,122,145,4,246,231,178,45,26,138,75,135,4,244,67,137,207,190,206,215,59,160,4,245,16,142,174,195,137, - 221,63,255,145,145,243,23,174,176,182,182,142,241,71,16,66,33,149,162,82,138,241,148,44,242,175,140,64,27,75,175,155, - 146,154,46,73,218,167,221,237,98,17,56,1,163,99,227,32,2,116,154,16,171,132,229,118,74,26,31,225,3,127,243,151, - 153,152,170,145,247,91,172,173,109,114,230,250,50,141,164,204,198,250,50,129,159,115,242,205,39,120,230,241,39,9,85,5, - 157,75,172,72,104,54,27,4,65,72,71,119,208,218,226,73,133,239,251,84,42,85,148,146,148,203,17,189,94,15,207,243, - 8,195,152,153,153,57,42,229,10,121,166,65,129,182,119,27,207,170,16,183,74,139,115,2,41,68,161,118,247,21,42,146, - 78,64,238,64,43,112,31,2,82,99,153,121,246,73,110,165,9,211,98,72,31,67,2,26,226,219,226,208,235,40,239,5, - 144,129,216,134,154,133,197,246,145,195,123,153,159,147,207,127,246,243,100,198,225,185,14,190,95,71,201,136,114,80,101,106, - 87,141,133,221,147,84,106,33,89,63,163,185,222,226,233,211,231,232,119,83,180,211,168,80,129,113,84,188,93,152,216,177, - 222,91,166,35,160,62,86,97,178,60,143,114,25,79,61,253,12,91,43,13,178,84,210,74,250,84,203,147,92,93,185,68, - 111,189,203,123,31,184,151,127,229,123,224,4,78,40,180,215,67,153,14,42,23,244,122,61,130,32,68,72,69,181,90,29, - 28,187,27,164,204,240,60,143,192,47,51,55,187,155,122,173,74,150,247,7,114,10,31,129,193,23,6,231,2,140,5,165, - 114,44,2,105,65,24,131,72,19,166,186,253,60,42,52,108,205,25,48,255,19,69,143,40,185,126,153,7,128,138,148,124, - 42,8,96,72,68,67,2,26,226,91,209,150,30,145,213,175,137,132,4,133,133,170,145,66,9,235,194,185,201,73,121,249, - 226,101,218,237,30,113,20,160,164,135,179,41,190,215,231,192,161,69,142,31,219,207,200,120,25,235,108,145,242,112,104,158, - 202,68,137,63,250,227,47,83,142,74,96,53,213,74,181,176,39,45,89,214,150,187,108,54,20,123,38,234,92,249,234,139, - 180,31,155,165,39,186,132,186,77,144,135,104,171,241,71,3,150,238,40,206,45,189,192,209,153,58,227,19,85,150,119,114, - 202,153,198,225,145,43,3,54,37,8,2,106,181,26,97,24,99,140,193,247,139,192,192,66,51,22,16,199,49,99,99,99, - 120,158,79,174,19,242,92,35,16,228,66,17,87,71,40,197,37,148,76,144,194,34,40,60,125,208,22,157,58,242,141,173, - 84,194,70,10,59,189,66,209,143,30,92,159,10,69,21,53,255,212,19,44,191,239,175,146,6,193,240,164,106,72,64,67, - 220,197,71,103,142,243,179,27,151,25,207,122,175,105,128,45,7,234,8,36,14,175,211,211,87,94,190,140,242,60,156,53, - 88,28,81,232,113,207,241,67,156,122,232,40,82,229,8,50,24,52,114,51,221,231,240,161,93,28,59,184,200,234,202,50, - 165,56,160,94,171,162,148,32,247,12,73,174,185,178,180,197,131,239,62,73,125,116,25,151,165,140,150,43,180,123,29,124, - 153,178,103,102,140,23,47,95,66,101,227,184,102,29,229,239,112,96,62,230,246,198,38,130,26,46,47,99,92,15,200,145, - 210,209,233,116,169,84,106,232,220,144,231,57,165,82,209,24,15,195,136,133,133,57,170,213,50,89,150,98,29,88,235,8, - 67,137,231,251,76,78,77,17,4,62,66,244,193,89,156,182,197,73,158,12,57,119,254,69,154,171,171,122,15,244,203,144, - 254,54,216,63,248,118,100,125,229,18,251,148,226,64,171,201,189,195,101,55,36,160,33,6,8,74,188,48,58,207,149,181, - 75,223,119,163,51,5,126,6,152,118,206,51,16,172,151,170,126,203,130,176,22,169,20,2,69,28,150,89,92,88,196,147, - 138,60,239,35,144,40,21,35,164,35,211,41,130,156,131,251,23,248,202,87,193,87,18,223,243,208,38,35,55,61,146,212, - 240,153,39,110,241,115,63,254,22,222,245,224,28,143,95,110,211,82,146,204,102,216,238,37,222,250,222,15,178,123,254,24, - 51,174,71,232,174,225,162,113,142,239,61,193,19,79,223,194,85,115,112,10,165,21,8,131,82,138,56,138,209,185,70,8, - 73,28,199,4,65,64,28,151,168,86,107,212,106,181,65,83,218,97,140,197,243,124,162,40,70,231,25,83,211,35,8,101, - 192,88,76,63,3,17,129,11,56,123,238,34,127,252,241,63,230,100,179,149,0,125,3,250,167,129,3,128,255,31,53,203, - 28,189,151,207,51,201,127,156,121,54,196,144,128,222,176,240,157,229,98,105,148,207,188,198,215,63,2,226,158,194,178,198, - 107,132,161,159,106,13,121,70,218,207,81,194,35,80,62,206,88,176,14,233,192,100,6,252,194,172,171,72,123,176,108,53, - 54,177,54,71,56,65,154,100,180,123,13,182,183,54,8,163,18,207,157,89,225,242,218,14,71,78,236,99,185,213,97,114, - 143,100,241,222,119,176,122,166,194,242,165,47,242,230,135,238,33,223,184,205,234,166,225,143,255,244,28,159,127,236,121,202, - 126,133,220,119,8,145,160,80,4,65,9,223,247,9,163,176,120,207,190,55,248,30,16,69,37,198,199,39,8,163,0,173, - 53,214,25,148,44,30,215,58,103,98,178,198,225,67,243,96,179,226,125,8,159,44,151,156,62,125,142,47,125,245,113,242, - 181,6,211,189,254,182,133,13,160,87,5,222,253,29,8,70,80,184,63,150,135,203,110,72,64,67,20,208,206,176,55,30, - 99,79,101,130,165,206,230,247,253,122,67,49,16,103,64,110,6,177,111,173,5,147,145,166,9,158,12,105,119,119,184,185, - 124,131,197,197,147,56,99,16,202,2,41,166,216,231,208,234,102,188,248,210,121,12,154,94,191,152,201,105,181,154,228,185, - 197,154,156,181,141,156,63,250,183,79,242,235,127,171,205,59,102,203,4,113,139,252,230,13,246,250,9,155,145,229,147,159, - 252,18,95,127,106,155,11,75,61,158,56,127,150,70,99,135,48,10,144,89,140,144,2,233,65,24,132,32,10,151,194,32, - 14,176,214,81,42,69,212,235,35,76,78,78,83,173,86,48,38,35,203,82,130,32,66,160,240,124,31,107,53,7,22,23, - 152,26,175,14,124,131,34,214,55,119,120,241,197,23,120,252,107,95,39,40,133,252,149,83,15,57,62,247,39,77,7,155, - 10,146,79,83,196,75,203,87,185,102,18,24,3,194,225,242,27,18,208,27,29,119,239,212,247,141,237,125,77,4,212,150, - 66,72,207,19,46,203,197,213,141,77,185,92,190,78,144,118,209,14,202,229,49,114,157,240,252,139,167,57,126,104,31,147, - 99,37,12,125,4,6,97,4,206,40,190,254,245,115,92,190,118,131,219,43,183,105,52,91,108,109,55,232,180,91,8,2, - 156,53,136,32,231,183,63,251,20,126,205,240,142,251,247,145,52,250,60,250,244,10,103,111,238,32,130,58,126,181,66,101, - 98,23,227,251,29,51,59,107,52,90,25,125,155,225,153,140,216,31,108,245,242,140,177,209,113,2,63,196,31,196,221,140, - 140,140,50,54,54,70,20,21,113,58,214,25,60,95,146,101,41,190,23,99,173,102,100,180,206,187,222,241,118,60,20,91, - 141,38,75,183,87,57,247,242,117,158,121,246,52,229,146,207,135,62,252,55,184,244,135,31,179,94,150,165,2,210,14,152, - 127,69,49,3,244,221,16,1,31,102,56,205,60,36,160,55,56,4,144,59,195,92,121,244,53,85,65,117,235,156,201,114, - 235,131,243,251,61,179,182,182,78,217,246,201,140,99,107,171,205,158,189,123,184,112,225,26,159,253,220,151,248,233,159,248, - 81,170,181,10,189,78,151,141,141,109,158,127,238,28,159,249,179,175,113,107,229,14,107,27,183,89,91,109,97,140,69,72, - 137,213,2,132,69,90,65,187,175,248,39,255,215,83,252,206,39,47,209,111,182,89,152,223,195,254,163,199,40,141,132,220, - 92,90,162,183,233,216,53,61,195,177,197,7,89,187,149,176,153,172,128,167,208,46,67,106,139,26,184,31,214,106,117,162, - 40,38,12,66,198,199,199,41,151,43,120,202,199,216,188,200,228,114,142,48,12,177,6,42,149,42,239,127,255,251,201,211, - 148,39,191,118,158,229,149,117,94,190,188,196,205,213,6,251,14,237,227,167,254,243,247,49,187,48,198,153,141,85,83,118, - 100,14,242,17,112,255,61,133,116,226,187,85,64,171,131,94,208,80,185,62,36,160,33,28,56,241,218,171,160,65,126,151, - 213,155,183,76,143,24,191,18,211,75,183,72,251,45,148,39,152,156,28,231,209,199,30,231,197,179,103,88,152,159,195,88, - 199,141,155,183,89,89,91,163,213,110,115,231,206,29,26,141,6,157,78,7,59,176,50,13,35,133,144,30,253,110,15,207, - 179,24,171,216,218,106,33,149,32,26,169,241,210,153,23,185,179,124,7,173,29,199,143,159,96,114,98,158,218,68,153,217, - 221,19,108,159,93,69,249,22,141,69,225,35,132,71,28,151,136,162,136,145,122,141,106,165,78,41,174,32,133,135,0,66, - 63,160,223,55,132,97,136,195,17,197,30,71,14,29,100,109,121,153,23,159,221,102,117,117,149,102,227,38,211,149,113,254, - 202,187,223,197,125,111,59,202,254,185,17,154,253,148,222,157,213,108,10,183,165,97,167,14,230,191,230,123,107,48,219,193, - 86,109,133,225,148,243,144,128,134,64,91,195,76,121,148,71,38,247,115,102,227,234,171,222,193,239,162,75,113,218,35,192, - 74,208,213,118,91,175,244,175,194,238,41,106,35,37,180,150,108,110,110,209,237,182,153,155,153,97,103,167,193,213,107,87, - 11,77,86,146,113,103,101,149,126,210,39,75,83,180,214,133,68,98,16,103,227,7,1,8,247,74,198,151,64,32,85,113, - 124,255,252,115,207,17,4,1,74,42,74,213,152,245,245,117,54,183,182,152,155,157,225,200,145,35,220,190,125,155,86,171, - 53,168,164,44,190,231,177,111,223,62,74,113,76,20,132,248,42,0,109,169,148,35,74,213,18,142,194,204,222,58,135,242, - 37,83,19,147,52,26,219,92,188,116,145,94,179,195,228,216,24,111,122,211,73,14,29,63,192,209,147,71,168,151,75,144, - 229,228,105,134,235,119,50,96,83,194,78,0,38,227,123,27,236,20,131,30,208,20,176,54,92,176,67,2,26,2,180,115, - 220,63,50,207,135,118,150,17,121,255,187,222,201,45,80,5,215,131,36,130,230,92,24,245,140,203,217,106,111,178,211,131, - 188,229,33,21,212,70,98,110,175,88,202,113,17,63,188,177,177,78,179,221,38,73,179,194,28,62,207,49,198,224,156,195, - 243,60,162,40,34,240,125,210,44,41,102,114,156,0,44,14,144,74,18,122,17,224,176,214,96,172,161,84,142,73,146,62, - 253,126,194,216,232,4,15,191,245,17,190,252,229,175,208,75,250,68,129,79,173,82,163,215,233,161,211,156,190,239,83,171, - 86,193,194,86,150,97,221,24,86,138,66,32,170,36,129,10,216,220,220,66,231,154,90,173,198,248,200,24,7,247,204,114, - 228,196,62,118,31,95,68,8,135,236,39,133,177,124,150,35,114,99,92,97,149,145,255,83,176,191,13,196,223,207,53,167, - 80,185,247,134,203,111,72,64,111,248,126,144,179,180,252,144,237,209,5,126,118,253,210,119,37,32,1,164,224,214,161,99, - 97,61,180,174,147,27,77,214,234,99,243,12,151,6,8,37,72,117,200,214,214,22,58,47,140,224,173,45,146,33,140,27, - 164,82,72,31,165,160,84,42,17,197,49,74,41,90,173,29,250,73,31,107,45,82,202,226,53,20,61,154,48,12,105,53, - 119,144,82,146,235,156,102,163,133,153,53,248,190,143,231,121,204,207,47,176,127,255,126,110,221,188,197,161,195,135,11,31, - 232,48,26,228,128,5,148,75,49,149,114,25,37,20,81,169,140,23,12,166,118,132,32,215,57,253,94,239,149,252,46,229, - 251,220,243,192,125,28,56,92,39,205,83,252,220,71,56,139,139,28,237,126,15,63,147,133,64,30,92,62,184,46,253,239, - 243,186,95,26,46,189,33,1,13,81,64,89,67,119,100,134,79,55,151,185,152,118,94,245,148,198,0,19,192,143,66,106, - 160,61,233,92,111,97,124,146,43,171,55,9,125,129,13,44,214,64,183,219,5,1,149,82,25,231,138,237,158,213,182,72, - 14,117,16,199,17,97,24,146,231,57,253,126,31,173,53,89,158,14,162,142,93,33,6,149,30,142,194,72,172,215,235,97, - 29,8,91,184,19,250,158,143,148,146,36,73,104,54,155,128,96,223,226,62,78,61,120,10,223,247,209,86,147,231,154,36, - 77,17,206,20,166,241,82,18,148,98,130,48,192,243,10,2,202,117,142,195,225,251,62,130,66,49,47,156,164,159,228,128, - 195,211,57,82,75,50,15,124,17,177,121,233,26,193,173,149,190,131,158,6,243,87,129,105,190,255,44,174,187,150,28,191, - 51,232,9,13,49,36,160,55,46,1,57,199,154,10,185,49,115,148,201,27,207,188,106,63,227,110,254,87,12,166,11,201, - 136,54,253,227,243,115,110,105,107,83,88,157,0,69,76,177,67,22,238,126,73,70,24,68,248,94,128,117,22,207,83,8, - 100,97,113,234,28,217,192,62,35,205,138,78,138,214,69,190,123,81,156,200,65,85,82,228,122,149,226,26,221,110,151,90, - 173,198,236,204,44,35,35,163,120,158,95,228,171,87,171,56,99,144,82,208,107,119,48,206,21,141,114,229,21,57,91,65, - 132,19,18,173,13,46,24,100,121,13,72,64,73,137,118,20,118,28,56,242,164,199,250,237,219,184,227,51,8,153,162,189, - 132,160,84,231,198,229,43,172,254,246,239,247,38,175,93,61,99,224,106,94,84,129,188,214,52,10,31,248,101,224,183,248, - 222,142,241,135,24,18,208,15,45,164,213,148,227,17,62,84,153,228,129,206,198,119,125,254,121,208,109,216,246,250,189,141, - 55,151,131,188,245,35,111,15,190,252,165,47,225,97,145,24,156,28,156,147,185,98,186,56,8,130,34,59,29,135,20,96, - 156,165,215,110,99,181,65,15,178,213,7,188,131,148,2,73,17,117,46,165,71,28,197,120,94,192,248,248,36,211,187,118, - 177,184,103,145,106,173,74,28,71,228,70,147,38,9,206,90,130,48,64,122,62,141,78,151,181,149,85,70,171,53,198,198, - 199,169,212,234,120,190,87,152,207,75,85,228,120,41,129,16,2,147,229,131,0,67,135,144,5,225,41,223,103,121,109,21, - 157,38,248,165,0,43,224,153,207,127,145,139,191,250,209,230,220,153,243,79,1,159,13,224,89,160,125,138,215,55,229,252, - 163,192,28,240,145,225,18,28,18,208,27,186,23,52,168,110,62,62,190,135,127,223,217,224,213,82,198,51,224,199,32,159, - 133,213,28,174,30,184,117,103,123,249,173,239,216,181,118,239,253,92,60,127,6,169,187,8,43,144,74,34,165,122,133,124, - 172,213,3,55,68,65,158,166,224,28,218,232,34,81,75,74,140,45,26,195,175,40,207,157,96,126,126,158,125,251,15,48, - 57,53,205,232,232,24,113,24,163,60,143,164,159,144,101,26,135,165,86,175,129,20,116,27,219,52,207,158,177,245,151,47, - 232,122,187,205,246,169,183,121,106,106,90,226,64,56,1,6,226,56,36,14,35,180,213,131,30,147,64,121,170,56,113,19, - 18,103,45,206,15,176,113,136,240,28,55,207,94,224,201,223,255,152,238,254,223,255,110,101,177,217,121,86,194,159,120,240, - 165,18,220,250,29,200,99,160,198,107,183,55,137,40,172,87,135,24,18,208,112,43,102,13,155,165,81,110,76,29,224,193, - 245,43,40,190,253,124,75,6,204,20,237,160,181,12,206,238,186,113,237,202,200,129,197,169,83,15,63,40,199,106,37,46, - 157,62,77,171,213,66,10,65,185,84,166,90,175,131,128,78,167,69,174,51,148,49,248,214,129,47,65,72,242,60,43,42, - 16,107,200,179,12,68,153,61,187,15,240,240,155,223,204,222,61,11,88,9,61,155,163,60,15,172,165,151,116,169,142,84, - 9,2,159,78,179,73,114,237,101,166,175,93,237,239,191,116,121,115,87,171,181,58,225,156,150,48,243,137,222,214,252,86, - 104,101,28,9,130,48,64,57,137,22,142,204,104,140,209,24,35,193,249,4,94,72,106,83,148,7,81,57,70,167,9,165, - 235,55,220,215,255,155,207,247,150,63,241,137,173,250,230,246,245,89,120,30,120,76,195,243,22,86,62,10,217,39,135,75, - 102,136,33,1,253,249,193,1,129,53,28,157,56,192,223,238,53,57,248,42,91,177,12,120,17,90,192,185,32,201,158,59, - 113,230,194,190,47,76,239,157,61,114,252,30,118,239,154,225,133,211,47,176,116,115,169,200,80,239,52,177,198,224,156,69, - 231,57,218,128,239,135,4,202,199,26,73,166,29,58,207,41,197,101,14,239,187,135,99,71,143,113,248,240,65,194,48,164, - 211,238,224,210,28,101,12,81,217,71,196,33,213,168,130,202,53,205,103,158,118,19,47,189,212,222,187,124,123,121,38,77, - 46,120,112,94,195,245,4,144,112,106,223,203,23,223,219,169,141,237,73,246,29,19,65,77,225,252,16,89,13,113,78,160, - 6,65,131,214,9,116,214,39,72,122,148,117,134,60,123,75,215,158,125,170,25,94,187,182,154,102,217,149,121,56,235,224, - 124,14,23,114,184,49,2,173,223,2,51,36,159,33,134,4,244,250,118,92,238,59,61,208,119,134,127,55,177,200,111,188, - 10,1,5,69,21,148,95,133,27,26,158,88,88,186,113,240,216,153,211,245,211,39,223,84,246,75,1,15,63,242,86,22, - 118,47,176,178,186,70,191,215,67,8,65,191,223,163,223,235,97,133,71,169,82,67,73,1,90,83,158,171,48,63,191,192, - 145,35,71,153,158,222,5,194,144,244,59,244,186,93,132,148,152,80,225,171,128,40,12,72,218,93,242,243,215,221,244,11, - 207,108,159,188,117,243,70,93,235,139,14,94,178,240,146,129,107,1,108,38,224,57,88,58,218,106,53,103,190,252,232,91, - 239,60,245,244,108,30,70,126,88,42,17,150,203,104,157,129,49,88,231,112,206,162,180,182,113,158,217,82,146,228,81,187, - 181,86,178,246,162,131,11,182,248,186,146,193,198,94,232,124,5,242,39,249,54,182,27,67,12,49,36,160,239,187,216,121, - 213,7,79,116,183,190,235,15,89,0,82,216,185,3,207,9,152,185,247,185,167,107,237,170,255,192,141,125,135,35,95,120, - 220,115,248,24,39,142,221,75,158,229,104,173,49,185,38,244,3,180,40,82,48,42,81,137,122,181,74,185,84,38,42,197, - 244,147,132,84,247,49,182,56,202,15,189,128,220,106,188,56,198,96,216,57,119,134,125,47,157,110,237,191,181,116,173,154, - 36,207,105,120,206,193,121,3,75,26,54,28,244,207,130,253,47,129,23,32,233,67,163,174,243,211,99,237,198,140,107,23, - 39,229,118,160,130,184,27,6,248,205,217,90,6,50,1,43,6,174,8,184,133,16,59,35,74,245,207,104,109,223,9,156, - 7,110,48,148,81,12,49,36,160,191,80,24,227,136,59,13,150,10,130,121,213,50,202,130,25,131,91,91,240,133,216,104, - 255,109,95,121,204,69,205,238,125,183,79,190,165,98,29,120,198,17,120,1,97,84,122,101,32,209,15,36,206,228,131,19, - 41,73,187,219,161,213,239,224,135,33,42,240,240,157,79,53,174,128,146,100,121,74,239,218,117,70,95,120,186,127,224,252, - 217,165,201,110,247,37,11,79,25,120,38,134,43,171,208,168,64,58,3,238,14,112,109,240,119,37,208,156,135,179,55,225, - 90,9,226,210,64,132,110,41,28,29,131,111,67,36,61,48,9,244,35,33,186,7,14,29,200,211,195,251,221,212,196,8, - 75,95,250,26,246,250,173,225,194,24,98,72,64,127,225,228,99,29,251,234,17,215,30,121,136,23,146,14,82,124,103,133, - 152,39,37,75,221,46,201,115,207,166,191,226,220,149,77,248,211,64,91,115,234,217,231,146,169,102,251,77,23,223,252,224, - 164,155,157,23,65,232,147,27,141,118,14,43,101,17,113,227,10,162,19,18,148,23,225,5,138,32,80,68,113,132,148,18, - 50,141,185,190,68,233,233,39,251,251,47,156,185,189,171,213,56,39,29,207,26,120,110,16,129,188,118,24,250,159,6,142, - 81,72,27,238,18,138,1,38,129,189,144,158,133,116,22,26,255,219,128,120,74,158,98,97,116,140,155,141,6,169,214,175, - 156,254,5,20,121,92,231,129,119,252,200,91,168,253,212,143,99,146,62,38,246,169,47,175,13,9,104,136,33,1,253,101, - 32,183,150,15,28,159,231,161,125,179,69,64,240,171,118,146,4,120,30,239,217,217,225,127,190,114,57,249,187,112,169,15, - 105,136,219,58,116,249,226,234,200,157,219,167,206,47,238,95,216,62,113,50,142,23,22,240,3,133,242,61,60,21,160,42, - 101,132,44,68,167,65,224,19,122,30,158,16,36,157,54,237,75,231,92,240,228,83,189,189,55,174,223,158,236,118,206,75, - 120,206,192,139,249,128,120,22,161,87,3,187,243,77,149,216,119,130,164,104,152,127,124,64,64,191,246,158,119,114,100,113, - 47,255,227,255,249,251,223,242,188,24,248,111,7,63,75,249,62,86,128,233,37,72,5,54,207,135,219,174,33,134,4,244, - 151,5,37,4,89,154,146,234,239,238,92,83,141,34,170,74,241,135,192,12,36,31,129,171,13,104,229,176,58,213,235,222, - 24,63,247,210,253,203,183,150,14,95,157,157,223,149,238,222,29,245,162,72,154,56,22,34,12,113,206,81,169,85,104,182, - 90,168,141,117,29,111,108,234,218,198,122,251,158,181,181,149,145,52,189,12,60,111,224,197,92,138,75,210,186,85,191,176, - 63,181,21,10,85,249,119,83,239,127,59,210,24,13,124,198,148,122,245,215,56,203,43,83,145,67,12,49,36,160,191,92, - 184,239,247,201,119,165,19,64,21,244,255,11,107,143,192,19,10,150,4,188,176,187,213,188,103,161,213,60,144,93,186,48, - 154,64,156,249,126,77,123,94,221,89,43,124,104,187,60,111,199,90,247,98,104,43,88,6,174,89,196,229,28,119,57,129, - 245,178,117,189,17,176,222,224,215,189,158,106,196,216,194,132,108,136,33,134,4,244,195,86,57,1,91,192,117,176,191,14, - 173,231,161,155,192,178,134,211,22,166,34,107,43,1,132,54,77,71,101,154,78,57,80,18,54,44,108,73,72,53,244,50, - 216,150,176,237,227,218,14,250,115,96,253,111,170,78,134,110,130,67,12,9,104,136,87,45,136,238,110,112,170,96,34,104, - 93,131,206,12,220,186,13,106,18,68,25,162,118,209,118,17,9,244,125,72,19,48,62,216,147,160,159,6,171,129,121,94, - 187,196,97,136,33,254,178,33,220,176,180,30,98,136,33,254,19,65,14,47,193,16,67,12,241,159,10,255,31,228,61,54, - 41,71,79,28,213,0,0,0,0,73,69,78,68,174,66,96,130, -}; - -}; diff --git a/target-loki/resource/resource.hpp b/target-loki/resource/resource.hpp deleted file mode 100644 index a665316a..00000000 --- a/target-loki/resource/resource.hpp +++ /dev/null @@ -1,3 +0,0 @@ -namespace resource { - extern const uint8_t loki[121905]; -}; diff --git a/target-loki/settings/settings.cpp b/target-loki/settings/settings.cpp deleted file mode 100644 index 6a067be1..00000000 --- a/target-loki/settings/settings.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "../loki.hpp" -Settings* settings = nullptr; - -Settings::Settings() { - settings = this; - - video.append(video.driver = ruby::video.optimalDriver(), "Driver"); - video.append(video.synchronize = false, "Synchronize"); - append(video, "Video"); - - audio.append(audio.driver = ruby::audio.optimalDriver(), "Driver"); - audio.append(audio.synchronize = true, "Synchronize"); - audio.append(audio.mute = false, "Mute"); - append(audio, "Audio"); - - input.append(input.driver = ruby::input.optimalDriver(), "Driver"); - append(input, "Input"); - - terminal.append(terminal.backgroundColor = 0x481818, "BackgroundColor"); - terminal.append(terminal.foregroundColor = 0xffffff, "ForegroundColor"); - append(terminal, "Terminal"); - - geometry.append(geometry.presentation = "", "Presentation"); - geometry.append(geometry.terminal = "", "Terminal"); - append(geometry, "Geometry"); - - load(); -} - -void Settings::load() { - Configuration::Document::load(program->path("settings.bml")); - Configuration::Document::save(program->path("settings.bml")); -} - -void Settings::unload() { - //remember window geometry for next run - geometry.presentation = presentation->geometry().text(); - geometry.terminal = ::terminal->geometry().text(); - - Configuration::Document::save(program->path("settings.bml")); -} - -void Settings::command(string s, lstring args) { - unsigned argc = args.size(); - s.ltrim<1>("settings."); - - if(s == "video.driver" && argc == 1) { video.driver = args[0]; return; } - if(s == "video.synchronize" && argc == 1) { video.synchronize = args[0] != "false"; ruby::video.set(ruby::Video::Synchronize, video.synchronize); return; } - if(s == "audio.driver" && argc == 1) { audio.driver = args[0]; return; } - if(s == "audio.synchronize" && argc == 1) { audio.synchronize = args[0] != "false"; ruby::audio.set(ruby::Audio::Synchronize, audio.synchronize); return; } - if(s == "audio.mute" && argc == 1) { audio.mute = args[0] != "false"; return; } - if(s == "input.driver" && argc == 1) { input.driver = args[0]; return; } - if(s == "terminal.background-color" && argc == 1) { terminal.backgroundColor = hex(args[0]); ::terminal->setColors(); return; } - if(s == "terminal.foreground-color" && argc == 1) { terminal.foregroundColor = hex(args[0]); ::terminal->setColors(); return; } - - echo("Error: unrecognized setting: ", s, "\n"); -} diff --git a/target-loki/settings/settings.hpp b/target-loki/settings/settings.hpp deleted file mode 100644 index 68bd5de1..00000000 --- a/target-loki/settings/settings.hpp +++ /dev/null @@ -1,34 +0,0 @@ -struct Settings : Configuration::Document { - struct Video : Configuration::Node { - string driver; - bool synchronize; - } video; - - struct Audio : Configuration::Node { - string driver; - bool synchronize; - bool mute; - } audio; - - struct Input : Configuration::Node { - string driver; - } input; - - struct Terminal : Configuration::Node { - unsigned backgroundColor; - unsigned foregroundColor; - } terminal; - - struct Geometry : Configuration::Node { - string presentation; - string terminal; - } geometry; - - Settings(); - void load(); - void unload(); - - void command(string s, lstring args); -}; - -extern Settings* settings; diff --git a/target-loki/terminal/terminal.cpp b/target-loki/terminal/terminal.cpp deleted file mode 100644 index 18fd0213..00000000 --- a/target-loki/terminal/terminal.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include "../loki.hpp" -Terminal* terminal = nullptr; - -Terminal::Terminal() { - terminal = this; - if(settings->geometry.terminal.empty()) { - unsigned y = 64 + presentation->geometry().height + presentation->frameMargin().height; - settings->geometry.terminal = {"64,", y, ",800,480"}; - } - - setTitle({"loki v", Emulator::Version}); - setGeometry(settings->geometry.terminal); - - console.setFont(Font::monospace(8)); - console.setPrompt("$ "); - setColors(); - - layout.append(console, {~0, ~0}); - append(layout); - - onClose = &Application::quit; - console.onActivate = {&Terminal::command, this}; -} - -void Terminal::load() { - if(file::exists(program->path("aliases.cfg"))) { - string filedata = file::read(program->path("aliases.cfg")); - lstring lines = filedata.split("\n"); - for(auto& line : lines) { - lstring part = line.split<1>(" => "); - if(part.size() != 2) continue; - aliases.append({part[0], part[1]}); - } - } - - if(file::exists(program->path("hotkeys.cfg"))) { - string filedata = file::read(program->path("hotkeys.cfg")); - lstring lines = filedata.split("\n"); - for(auto& line : lines) { - lstring part = line.split<1>(" => "); - if(part.size() != 2) continue; - hotkeys.append({part[0], part[1]}); - } - } -} - -void Terminal::unload() { - file fp; - if(fp.open(program->path("aliases.cfg"), file::mode::write)) { - for(auto& alias : aliases) fp.print(alias.name, " => ", alias.mapping, "\n"); - fp.close(); - } - if(fp.open(program->path("hotkeys.cfg"), file::mode::write)) { - for(auto& hotkey : hotkeys) fp.print(hotkey.name, " => ", hotkey.mapping, "\n"); - fp.close(); - } -} - -void Terminal::command(string t) { - for(auto& alias : aliases) { - lstring tokens; - if(tokenize(tokens, t, alias.name) == false) continue; - string output = alias.mapping; - for(unsigned n = 0; n < tokens.size(); n++) { - output.replace(string{"{", 1 + n, "}"}, tokens[n]); - } - t = output; - break; - } - - auto source = Debugger::Source::CPU; - if(t.beginsWith("cpu/" )) { source = Debugger::Source::CPU; t.ltrim<1>("cpu/" ); } - if(t.beginsWith("smp/" )) { source = Debugger::Source::SMP; t.ltrim<1>("smp/" ); } - if(t.beginsWith("ppu/" )) { source = Debugger::Source::PPU; t.ltrim<1>("ppu/" ); } - if(t.beginsWith("dsp/" )) { source = Debugger::Source::DSP; t.ltrim<1>("dsp/" ); } - if(t.beginsWith("apu/" )) { source = Debugger::Source::APU; t.ltrim<1>("apu/" ); } - if(t.beginsWith("wram/" )) { source = Debugger::Source::WRAM; t.ltrim<1>("wram/" ); } - if(t.beginsWith("vram/" )) { source = Debugger::Source::VRAM; t.ltrim<1>("vram/" ); } - if(t.beginsWith("oam/" )) { source = Debugger::Source::OAM; t.ltrim<1>("oam/" ); } - if(t.beginsWith("cgram/")) { source = Debugger::Source::CGRAM; t.ltrim<1>("cgram/"); } - - if(source == Debugger::Source::CPU) t.replace("$", hex(SFC::cpu.regs.pc)); - if(source == Debugger::Source::SMP) t.replace("$", hex(SFC::smp.regs.pc)); - - lstring part = t.strip().split<1>(" "), args; - string s = part(0); - string p = part(1); - if(p) args = p.qsplit(" ").strip(); - unsigned argc = args.size(); - - if(s.empty()) return; - - if(s.beginsWith("settings.")) return settings->command(s, args); - - if(s == "aliases") { - echoAliases(); - return; - } - - if(s == "aliases.append") { - lstring part = p.qsplit<1>("=>").strip(); - if(part.size() == 2) aliases.append({part[0], part[1]}); - echoAliases(); - return; - } - - if(s == "aliases.remove" && argc == 1) { - unsigned n = decimal(args[0]); - if(n < aliases.size()) aliases.remove(n); - echoAliases(); - return; - } - - if(s == "aliases.reset") { - aliases.reset(); - echo("All aliases removed\n"); - return; - } - - if(s == "break") { - debugger->stop(); - return; - } - - if(s == "breakpoints") { - debugger->echoBreakpoints(); - return; - } - - if(s == "breakpoints.append" && argc >= 2 && argc <= 3) { - Debugger::Breakpoint bp; - bp.source = source; - if(args[0] == "read" ) bp.mode = Debugger::Breakpoint::Mode::Read; - if(args[0] == "write" ) bp.mode = Debugger::Breakpoint::Mode::Write; - if(args[0] == "execute") bp.mode = Debugger::Breakpoint::Mode::Execute; - bp.addr = hex(args[1]); - if(argc >= 3) bp.data = (uint8_t)hex(args[2]); - debugger->breakpoints.append(bp); - debugger->echoBreakpoints(); - return; - } - - if(s == "breakpoints.remove" && argc == 1) { - unsigned n = decimal(args[0]); - if(n < debugger->breakpoints.size()) { - debugger->breakpoints.remove(n); - } - debugger->echoBreakpoints(); - return; - } - - if(s == "breakpoints.reset") { - debugger->breakpoints.reset(); - echo("All breakpoints removed\n"); - return; - } - - if(s == "clear") { - reset(); - return; - } - - if(s == "counter") { - if(source == Debugger::Source::CPU) echo("CPU instructions executed: ", debugger->cpuInstructionCounter, "\n"); - if(source == Debugger::Source::SMP) echo("SMP instructions executed: ", debugger->smpInstructionCounter, "\n"); - return; - } - - if(s == "counter.reset") { - if(source == Debugger::Source::CPU) { echo("CPU instruction counter reset\n"); debugger->cpuInstructionCounter = 0; } - if(source == Debugger::Source::SMP) { echo("SMP instruction counter reset\n"); debugger->smpInstructionCounter = 0; } - return; - } - - if(s == "disassemble" && argc >= 1 && argc <= 2) { - debugger->echoDisassemble(source, hex(args[0]), argc == 2 ? decimal(args[1]) : 16); - return; - } - - if(s == "export" && argc <= 1) { - string filename = {debugger->sourceName(source), "-", string::datetime().transform(" :", "--"), ".ram"}; - if(argc >= 1) filename = args[0]; - string pathname = {interface->pathname, "loki/", filename}; - debugger->memoryExport(source, pathname); - return; - } - - if(s == "hex" && argc >= 1 && argc <= 2) { - debugger->echoHex(source, hex(args[0]), argc == 2 ? decimal(args[1]) : 256); - return; - } - - if(s == "hotkeys") { - echoHotkeys(); - return; - } - - if(s == "hotkeys.append") { - lstring part = p.qsplit<1>("=>").strip(); - if(part.size() == 2) hotkeys.append({part[0], part[1]}); - echoHotkeys(); - return; - } - - if(s == "hotkeys.remove" && argc == 1) { - unsigned n = decimal(args[0]); - if(n < hotkeys.size()) hotkeys.remove(n); - echoHotkeys(); - return; - } - - if(s == "hotkeys.reset") { - hotkeys.reset(); - echo("All hotkeys removed\n"); - return; - } - - if(s == "power") { - emulator->power(); - echo("System has been power cycled\n"); - return; - } - - if(s == "quit") { - Application::quit(); - return; - } - - if(s == "read" && argc == 1) { - unsigned addr = hex(args[0]); - uint8_t data = debugger->memoryRead(source, addr); - echo(debugger->sourceName(source), "/", hex<6>(addr), " = ", hex<2>(data), "\n"); - return; - } - - if(s == "reset") { - emulator->reset(); - echo("System has been reset\n"); - return; - } - - if(s == "run" && argc == 0) { - debugger->run(); - return; - } - - if(s == "run.for" && argc == 1) { - debugger->run(); - if(source == Debugger::Source::CPU) debugger->cpuRunFor = (unsigned)decimal(args[0]); - if(source == Debugger::Source::SMP) debugger->smpRunFor = (unsigned)decimal(args[0]); - return; - } - - if(s == "run.to" && argc == 1) { - debugger->run(); - if(source == Debugger::Source::CPU) debugger->cpuRunTo = (unsigned)hex(args[0]); - if(source == Debugger::Source::SMP) debugger->smpRunTo = (unsigned)hex(args[0]); - return; - } - - if(s == "state.load" && argc == 1) { - string pathname = {interface->pathname, "loki/state-", args[0], ".bst"}; - debugger->stateLoad(pathname); - return; - } - - if(s == "state.save" && argc == 1) { - string pathname = {interface->pathname, "loki/state-", args[0], ".bst"}; - debugger->stateSave(pathname); - return; - } - - if(s == "step" && argc == 0) { - debugger->run(); - if(source == Debugger::Source::CPU) debugger->cpuStepFor = 1u; - if(source == Debugger::Source::SMP) debugger->smpStepFor = 1u; - return; - } - - if(s == "step.for" && argc == 1) { - debugger->run(); - if(source == Debugger::Source::CPU) debugger->cpuStepFor = (unsigned)decimal(args[0]); - if(source == Debugger::Source::SMP) debugger->smpStepFor = (unsigned)decimal(args[0]); - return; - } - - if(s == "step.to" && argc == 1) { - debugger->run(); - if(source == Debugger::Source::CPU) debugger->cpuStepTo = (unsigned)hex(args[0]); - if(source == Debugger::Source::SMP) debugger->smpStepTo = (unsigned)hex(args[0]); - return; - } - - if(s == "tracer.enable" && argc <= 1) { - string filename = {debugger->sourceName(source), "-trace-", string::datetime().transform(" :", "--"), ".log"}; - if(argc >= 1) filename = args[0]; - string pathname = {interface->pathname, "loki/", filename}; - debugger->tracerEnable(source, pathname); - return; - } - - if(s == "tracer.disable") { - debugger->tracerDisable(source); - return; - } - - if(s == "tracer.mask.enable") { - debugger->tracerMaskEnable(source); - return; - } - - if(s == "tracer.mask.disable") { - debugger->tracerMaskDisable(source); - return; - } - - if(s == "usage.reset") { - if(source == Debugger::Source::CPU) memset(debugger->cpuUsage, 0x00, 0x1000000); - if(source == Debugger::Source::APU) memset(debugger->apuUsage, 0x00, 0x10000); - return; - } - - if(s == "write" && argc == 2) { - unsigned addr = hex(args[0]); - uint8 data = hex(args[1]); - debugger->memoryWrite(source, addr, data); - echo(debugger->sourceName(source), "/", hex<6>(addr), " = ", hex<2>(data), "\n"); - return; - } - - echo("Error: unrecognized command: ", s, "\n"); -} - -void Terminal::echoAliases() { - if(aliases.size() == 0) return echo("No aliases defined\n"); - echo("# alias\n"); - echo("--- -----\n"); - for(unsigned n = 0; n < aliases.size(); n++) { - echo(format<-3>(n), " ", aliases[n].name, " => ", aliases[n].mapping, "\n"); - } -} - -void Terminal::echoHotkeys() { - if(hotkeys.size() == 0) return echo("No hotkeys defined\n"); - echo("# hotkey\n"); - echo("--- ------\n"); - for(unsigned n = 0; n < hotkeys.size(); n++) { - echo(format<-3>(n), " ", hotkeys[n].name, " => ", hotkeys[n].mapping, "\n"); - } -} - -void Terminal::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { - if(focused() == false) return; - if(device.isKeyboard() == false) return; //only capture keyboard events - if(oldValue != 0 || newValue != 1) return; //only capture key down events - string name = device.group[group].input[input].name; - - for(auto& hotkey : hotkeys) { - if(name != hotkey.name) continue; - command(hotkey.mapping); - } -} - -void Terminal::reset() { - console.reset(); -} - -void Terminal::print(const string& text) { - console.print(text); -} - -void Terminal::setColors() { - console.setBackgroundColor({ - (uint8)(settings->terminal.backgroundColor >> 16), - (uint8)(settings->terminal.backgroundColor >> 8), - (uint8)(settings->terminal.backgroundColor >> 0) - }); - - console.setForegroundColor({ - (uint8)(settings->terminal.foregroundColor >> 16), - (uint8)(settings->terminal.foregroundColor >> 8), - (uint8)(settings->terminal.foregroundColor >> 0) - }); -} diff --git a/target-loki/terminal/terminal.hpp b/target-loki/terminal/terminal.hpp deleted file mode 100644 index 93f05460..00000000 --- a/target-loki/terminal/terminal.hpp +++ /dev/null @@ -1,31 +0,0 @@ -struct Terminal : Window { - struct Alias { - string name; - string mapping; - }; - - struct Hotkey { - string name; - string mapping; - }; - - Terminal(); - void load(); - void unload(); - - void command(string s); - void echoAliases(); - void echoHotkeys(); - void inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue); - void reset(); - void print(const string& text); - void setColors(); - - VerticalLayout layout; - Console console; - - vector<Alias> aliases; - vector<Hotkey> hotkeys; -}; - -extern Terminal* terminal;