diff --git a/Console/CMakeLists.txt b/Console/CMakeLists.txt deleted file mode 100644 index 8121b652f7..0000000000 --- a/Console/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2014 Wolfgang Thaller. -# -# This file is part of Retro68. -# -# Retro68 is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Retro68 is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Retro68. If not, see . - -add_library(RetroConsole - retro/Console.cc - retro/Console.h - retro/ConsoleWindow.cc - retro/ConsoleWindow.h - retro/MacUtils.h - retro/InitConsole.cc - ) -set_target_properties(retrocrt - PROPERTIES - COMPILE_OPTIONS -ffunction-sections) - -# different library name for Carbon -# (Carbon shares the powerpc-apple-macos/ directory with Classic PPC) -if(CMAKE_SYSTEM_NAME MATCHES RetroCarbon) - set_target_properties(RetroConsole PROPERTIES OUTPUT_NAME RetroConsoleCarbon) -endif() -target_include_directories(RetroConsole PUBLIC .) - -install(TARGETS RetroConsole DESTINATION lib) - -add_application(ConsoleTest - ConsoleTest.cc - ) -target_link_libraries(ConsoleTest RetroConsole) diff --git a/Console/ConsoleTest.cc b/Console/ConsoleTest.cc index 587490fddb..b32da0ea83 100644 --- a/Console/ConsoleTest.cc +++ b/Console/ConsoleTest.cc @@ -9,7 +9,7 @@ namespace retro int main() { retro::InitConsole(); - std::string out = "Hello, world.\nEnter \"exit\" to quit.\n"; + std::string out = "Hello, \033[1mexternal world of \033[0m\033[3mtrue beauty and \033[4mgreatness\033[0m.\nEnter \"exit\" to quit.\n"; retro::Console::currentInstance->write(out.data(), out.size()); std::string in; diff --git a/IConsole/Makefile b/Console/Makefile similarity index 54% rename from IConsole/Makefile rename to Console/Makefile index 4ea7c1636a..c9a0114ab4 100644 --- a/IConsole/Makefile +++ b/Console/Makefile @@ -6,21 +6,21 @@ CC=$(RETRO68)/bin/m68k-apple-macos-gcc CXX=$(RETRO68)/bin/m68k-apple-macos-g++ REZ=$(RETRO68)/bin/Rez -LDFLAGS=retro/libIConsole.a +LDFLAGS=retro/libConsole.a RINCLUDES=$(PREFIX)/RIncludes REZFLAGS=-I$(RINCLUDES) -IConsoleTest.bin IConsoleTest.APPL IConsoleTest.dsk: IConsoleTest.code.bin +ConsoleTest.bin ConsoleTest.APPL ConsoleTest.dsk: ConsoleTest.code.bin $(REZ) $(REZFLAGS) \ - --copy "IConsoleTest.code.bin" \ + --copy "ConsoleTest.code.bin" \ "$(RINCLUDES)/Retro68APPL.r" \ -t "APPL" -c "????" \ - -o IConsoleTest.bin --cc IConsoleTest.APPL --cc IConsoleTest.dsk + -o ConsoleTest.bin --cc ConsoleTest.APPL --cc ConsoleTest.dsk -IConsoleTest.code.bin: IConsoleTest.o +ConsoleTest.code.bin: ConsoleTest.o $(CXX) $< -o $@ $(LDFLAGS) # C++ used for linking because RetroConsole needs it .PHONY: clean clean: - rm -f IConsoleTest.bin IConsoleTest.APPL IConsoleTest.dsk IConsoleTest.code.bin IConsoleTest.code.bin.gdb IConsoleTest.o + rm -f ConsoleTest.bin ConsoleTest.APPL ConsoleTest.dsk ConsoleTest.code.bin ConsoleTest.code.bin.gdb ConsoleTest.o diff --git a/IConsole/readme.txt b/Console/readme.txt similarity index 100% rename from IConsole/readme.txt rename to Console/readme.txt diff --git a/Console/retro/Console.cc b/Console/retro/Console.cc index bc10bf582b..47681da9eb 100644 --- a/Console/retro/Console.cc +++ b/Console/retro/Console.cc @@ -1,5 +1,5 @@ /* - Copyright 2012 Wolfgang Thaller. + Copyright 2012-2020 Wolfgang Thaller, Davide Bucci This file is part of Retro68. @@ -28,11 +28,73 @@ using namespace retro; Console *Console::currentInstance = NULL; +Attributes::Attributes(void) +{ + reset(); +} +void Attributes::reset(void) +{ + cBold=false; + cUnderline=false; + cItalic=false; +} + +bool Attributes::isBold(void) const +{ + return cBold; +} + + +bool Attributes::isUnderline(void) const +{ + return cUnderline; +} + +bool Attributes::isItalic(void) const +{ + return cItalic; +} + +void Attributes::setBold(const bool v) +{ + cBold=v; +} + +void Attributes::setItalic(const bool v) +{ + cItalic=v; +} + +void Attributes::setUnderline(const bool v) +{ + cUnderline=v; +} + +inline bool operator==(const Attributes& lhs, const Attributes& rhs) +{ + return lhs.isBold()==rhs.isBold() && lhs.isUnderline()==rhs.isUnderline() && lhs.isItalic()==rhs.isItalic(); +} + +inline bool operator!=(const Attributes& lhs, const Attributes& rhs) +{ + return !(lhs == rhs); +} + +inline bool operator==(const AttributedChar& lhs, const AttributedChar& rhs) +{ + return lhs.c==rhs.c && lhs.attrs==rhs.attrs; +} + +inline bool operator!=(const AttributedChar& lhs, const AttributedChar& rhs) +{ + return !(lhs == rhs); +} + namespace { class FontSetup { - short saveFont, saveSize; + short saveFont, saveSize, saveFace; public: FontSetup() { @@ -44,15 +106,18 @@ namespace #else saveFont = qd.thePort->txFont; saveSize = qd.thePort->txSize; + saveFace = qd.thePort->txFace; #endif TextFont(kFontIDMonaco); TextSize(9); + TextFace(normal); } ~FontSetup() { TextFont(saveFont); TextSize(saveSize); + TextFace(saveFace); } }; } @@ -88,11 +153,17 @@ void Console::Init(GrafPtr port, Rect r) rows = (bounds.bottom - bounds.top) / cellSizeY; cols = (bounds.right - bounds.left) / cellSizeX; - chars = std::vector(rows*cols, ' '); + chars = std::vector(rows*cols, AttributedChar(' ',currentAttr)); onscreen = chars; cursorX = cursorY = 0; + isProcessingEscSequence=false; +} + +void Console::SetAttributes(Attributes aa) +{ + TextFace(aa.isBold()?bold+condense:0 + aa.isUnderline()?underline:0 + aa.isItalic()?italic:0); } Rect Console::CellRect(short x, short y) @@ -116,14 +187,13 @@ void Console::DrawCell(short x, short y, bool erase) if(erase) EraseRect(&r); MoveTo(r.left, r.bottom - 2); - DrawChar(chars[y * cols + x]); + DrawChar(chars[y * cols + x].c); } void Console::DrawCells(short x1, short x2, short y, bool erase) { Rect r = { (short) (bounds.top + y * cellSizeY), (short) (bounds.left + x1 * cellSizeX), - (short) (bounds.top + (y+1) * cellSizeY), (short) (bounds.left + x2 * cellSizeX) }; - + (short) (bounds.top + (y+1) * cellSizeY), (short) (bounds.left + x2 * cellSizeX) }; if(cursorDrawn) { if(y == cursorY && x1 <= cursorX && x2 > cursorX) @@ -136,7 +206,17 @@ void Console::DrawCells(short x1, short x2, short y, bool erase) if(erase) EraseRect(&r); MoveTo(r.left, r.bottom - 2); - DrawText(&chars[y * cols + x1], 0, x2 - x1); + + Attributes a=chars[y * cols + x1].attrs; + SetAttributes(a); + for(int i=x1; i 0 ? dirtyRect.bottom - 1 : 0; } +void Console::ProcessEscSequence(char c) +{ + switch(sequenceStep) + { + case 0: + if(c=='[') + ++sequenceStep; + else + isProcessingEscSequence=false; + break; + case 1: + ++sequenceStep; + switch(c) + { + case '0': // Normal character + currentAttr.reset(); + break; + case '1': // Bold + currentAttr.setBold(true); + break; + case '3': // Italic + currentAttr.setItalic(true); + break; + case '4': // Underline + currentAttr.setUnderline(true); + break; + default: + isProcessingEscSequence=false; + } + break; + case 2: + if(c=='m') + isProcessingEscSequence=false; + else if(c==';') + sequenceStep=1; + else + isProcessingEscSequence=false; + break; + default: + sequenceStep=0; + } +} void Console::PutCharNoUpdate(char c) { + if(isProcessingEscSequence) + { + ProcessEscSequence(c); + return; + } InvalidateCursor(); switch(c) { + case '\033': // Begin of an ANSI escape sequence + isProcessingEscSequence=true; + sequenceStep=0; + break; case '\r': cursorX = 0; break; @@ -197,7 +329,9 @@ void Console::PutCharNoUpdate(char c) ScrollUp(); break; default: - chars[cursorY * cols + cursorX] = c; + chars[cursorY * cols + cursorX].c = c; + chars[cursorY * cols + cursorX].attrs = currentAttr; + if(dirtyRect.right == 0) { dirtyRect.right = (dirtyRect.left = cursorX) + 1; @@ -214,6 +348,8 @@ void Console::PutCharNoUpdate(char c) cursorX++; if(cursorX >= cols) PutCharNoUpdate('\n'); + // This is to make sure the cursor width is calculated correctly + chars[cursorY * cols + cursorX].attrs = currentAttr; } } @@ -228,12 +364,12 @@ void Console::Update() bool needclear = false; for(short col = dirtyRect.left; col < dirtyRect.right; ++col) { - char old = onscreen[row * cols + col]; + AttributedChar old = onscreen[row * cols + col]; if(chars[row * cols + col] != old) { if(start == -1) start = col; - if(old != ' ') + if(old.c != ' ') needclear = true; onscreen[row * cols + col] = chars[row * cols + col]; } @@ -259,7 +395,7 @@ void Console::Update() InvertRect(&r); cursorDrawn = !cursorDrawn; } - + #if TARGET_API_MAC_CARBON QDFlushPortBuffer(consolePort,NULL); #endif @@ -331,7 +467,6 @@ void Console::InvalidateCursor() if(cursorDrawn) { PortSetter setport(consolePort); - DrawCell(cursorX, cursorY, true); cursorDrawn = false; } @@ -368,11 +503,11 @@ void Console::Reshape(Rect newBounds) cursorY = newRows - 1; } - std::vector newChars(newRows*newCols, ' '); + std::vector newChars(newRows*newCols, AttributedChar(' ', currentAttr)); for(short row = 0; row < newRows && row + upshift < rows; row++) { - char *src = &chars[(row+upshift) * cols]; - char *dst = &newChars[row * newCols]; + AttributedChar *src = &chars[(row+upshift) * cols]; + AttributedChar *dst = &newChars[row * newCols]; std::copy(src, src + std::min(cols, newCols), dst); } chars.swap(newChars); diff --git a/Console/retro/Console.h b/Console/retro/Console.h index d94417c21b..e1d998eafd 100644 --- a/Console/retro/Console.h +++ b/Console/retro/Console.h @@ -1,5 +1,5 @@ /* - Copyright 2012 Wolfgang Thaller. + Copyright 2012-2020 Wolfgang Thaller, Davide Bucci This file is part of Retro68. @@ -25,6 +25,39 @@ namespace retro { + class Attributes + { + public: + + bool isBold(void) const; + bool isUnderline(void) const; + bool isItalic(void) const; + + void setBold(const bool v); + void setUnderline(const bool v); + void setItalic(const bool v); + + Attributes(void); + void reset(void); + + private: + + bool cBold; + bool cUnderline; + bool cItalic; + }; + + class AttributedChar + { + public: + char c; + Attributes attrs; + AttributedChar(char cc, Attributes aa) {c=cc; attrs=aa;} + }; + +// inline bool operator==(const Attributes& lhs, const Attributes& rhs); +// inline bool operator!=(const Attributes& lhs, const Attributes& rhs); + class Console { public: @@ -52,8 +85,11 @@ namespace retro private: GrafPtr consolePort = nullptr; Rect bounds; + Attributes currentAttr; - std::vector chars, onscreen; + std::vector chars, onscreen; + bool isProcessingEscSequence; + int sequenceStep; short cellSizeX; short cellSizeY; @@ -72,10 +108,13 @@ namespace retro void PutCharNoUpdate(char c); void Update(); + short CalcStartX(short x, short y); Rect CellRect(short x, short y); void DrawCell(short x, short y, bool erase = true); void DrawCells(short x1, short x2, short y, bool erase = true); void ScrollUp(short n = 1); + void ProcessEscSequence(char c); + void SetAttributes(Attributes aa); void InvalidateCursor(); diff --git a/Console/retro/ConsoleWindow.cc b/Console/retro/ConsoleWindow.cc index 1f4092d313..9b5c9ae5cf 100644 --- a/Console/retro/ConsoleWindow.cc +++ b/Console/retro/ConsoleWindow.cc @@ -1,5 +1,5 @@ /* - Copyright 2012 Wolfgang Thaller. + Copyright 2012-2020 Wolfgang Thaller, Davide Bucci This file is part of Retro68. @@ -31,8 +31,8 @@ namespace ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title) { GrafPtr port; - - win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, false, 0); + //Retro68 Improved Console + win = NewWindow(NULL, &r, "\pThe Queen's Footsteps", true, 0, (WindowPtr)-1, true, 0); #if !TARGET_API_MAC_CARBON port = win; @@ -105,7 +105,6 @@ char ConsoleWindow::WaitNextChar() } break; case mouseDown: - switch(FindWindow(event.where, &eventWin)) { case inDrag: @@ -118,6 +117,11 @@ char ConsoleWindow::WaitNextChar() Reshape(Rect {0, 0, (short) (growResult >> 16), (short) (growResult & 0xFFFF) }); } break; + case inGoAway: + { + if (TrackGoAway(eventWin,event.where)) + exit(0); + } } break; } diff --git a/Console/retro/ConsoleWindow.h b/Console/retro/ConsoleWindow.h index 6d491f7b04..9e149b4cc9 100644 --- a/Console/retro/ConsoleWindow.h +++ b/Console/retro/ConsoleWindow.h @@ -1,5 +1,5 @@ /* - Copyright 2012 Wolfgang Thaller. + Copyright 2012-2020 Wolfgang Thaller, Davide Bucci This file is part of Retro68. diff --git a/Console/retro/Makefile b/Console/retro/Makefile new file mode 100644 index 0000000000..6e413e98e3 --- /dev/null +++ b/Console/retro/Makefile @@ -0,0 +1,20 @@ +# path to RETRO68 +RETRO68=../../../Retro68-build/toolchain + +PREFIX=$(RETRO68)/m68k-apple-macos +CC=$(RETRO68)/bin/m68k-apple-macos-gcc +CXX=$(RETRO68)/bin/m68k-apple-macos-g++ +REZ=$(RETRO68)/bin/Rez +AR=$(RETRO68)/bin/m68k-apple-macos-gcc-ar + +LDFLAGS= +RINCLUDES=$(PREFIX)/RIncludes +REZFLAGS=-I$(RINCLUDES) + + +libConsole.a: Console.o ConsoleWindow.o InitConsole.o + $(AR) rcs $@ $? + +.PHONY: clean +clean: + rm -f Console.o ConsoleWindow.o InitConsole.o diff --git a/IConsole/IConsoleTest.cc b/IConsole/IConsoleTest.cc deleted file mode 100644 index beb9f5ee24..0000000000 --- a/IConsole/IConsoleTest.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "retro/IConsole.h" -#include - -namespace retro -{ - void InitIConsole(); -} - -int main() -{ - retro::InitIConsole(); - std::string out = "Hello, \033[1mexternal world of \033[0m\033[3mtrue beauty and \033[4mgreatness\033[0m.\nEnter \"exit\" to quit.\n"; - retro::IConsole::currentInstance->write(out.data(), out.size()); - - std::string in; - do - { - in = retro::IConsole::currentInstance->ReadLine(); - out = "You Entered: " + in; - retro::IConsole::currentInstance->write(out.data(), out.size()); - } while(in != "exit\n"); - return 0; -} diff --git a/IConsole/retro/IConsole.cc b/IConsole/retro/IConsole.cc deleted file mode 100644 index c9f99df9e0..0000000000 --- a/IConsole/retro/IConsole.cc +++ /dev/null @@ -1,538 +0,0 @@ -/* - Copyright 2012-2019 Wolfgang Thaller, Davide Bucci - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ - -#include "IConsole.h" -#include "MacUtils.h" -#include "Fonts.h" -#include "Processes.h" - -#include - -using namespace retro; - -IConsole *IConsole::currentInstance = NULL; - -Attributes::Attributes(void) -{ - reset(); -} -void Attributes::reset(void) -{ - cBold=false; - cUnderline=false; - cItalic=false; -} - -bool Attributes::isBold(void) const -{ - return cBold; -} - - -bool Attributes::isUnderline(void) const -{ - return cUnderline; -} - -bool Attributes::isItalic(void) const -{ - return cItalic; -} - -void Attributes::setBold(const bool v) -{ - cBold=v; -} - -void Attributes::setItalic(const bool v) -{ - cItalic=v; -} - -void Attributes::setUnderline(const bool v) -{ - cUnderline=v; -} - -inline bool operator==(const Attributes& lhs, const Attributes& rhs) -{ - return lhs.isBold()==rhs.isBold() && lhs.isUnderline()==rhs.isUnderline() && lhs.isItalic()==rhs.isItalic(); -} - -inline bool operator!=(const Attributes& lhs, const Attributes& rhs) -{ - return !(lhs == rhs); -} - -inline bool operator==(const AttributedChar& lhs, const AttributedChar& rhs) -{ - return lhs.c==rhs.c && lhs.attrs==rhs.attrs; -} - -inline bool operator!=(const AttributedChar& lhs, const AttributedChar& rhs) -{ - return !(lhs == rhs); -} - -namespace -{ - class FontSetup - { - short saveFont, saveSize, saveFace; - public: - FontSetup() - { -#if TARGET_API_MAC_CARBON - GrafPtr port; - GetPort(&port); - saveFont = GetPortTextFont(port); - saveSize = GetPortTextSize(port); -#else - saveFont = qd.thePort->txFont; - saveSize = qd.thePort->txSize; - saveFace = qd.thePort->txFace; -#endif - TextFont(kFontIDMonaco); - TextSize(9); - TextFace(normal); - } - - ~FontSetup() - { - TextFont(saveFont); - TextSize(saveSize); - TextFace(saveFace); - } - }; -} - -IConsole::IConsole() -{ -} - -IConsole::IConsole(GrafPtr port, Rect r) -{ - Init(port, r); -} - -IConsole::~IConsole() -{ - if(currentInstance == this) - currentInstance = NULL; -} - -void IConsole::Init(GrafPtr port, Rect r) -{ - consolePort = port; - bounds = r; - - PortSetter setport(consolePort); - FontSetup fontSetup; - - InsetRect(&bounds, 2,2); - - cellSizeY = 12; - cellSizeX = CharWidth('M'); - - rows = (bounds.bottom - bounds.top) / cellSizeY; - cols = (bounds.right - bounds.left) / cellSizeX; - - chars = std::vector(rows*cols, AttributedChar(' ',currentAttr)); - - onscreen = chars; - - cursorX = cursorY = 0; - isProcessingEscSequence=false; -} - -void IConsole::SetAttributes(Attributes aa) -{ - TextFace(aa.isBold()?bold+condense:0 + aa.isUnderline()?underline:0 + aa.isItalic()?italic:0); -} - -Rect IConsole::CellRect(short x, short y) -{ - return { (short) (bounds.top + y * cellSizeY), (short) (bounds.left + x * cellSizeX), - (short) (bounds.top + (y+1) * cellSizeY), (short) (bounds.left + (x+1) * cellSizeX) }; -} -void IConsole::DrawCell(short x, short y, bool erase) -{ - Rect r = CellRect(x,y); - - if(cursorDrawn) - { - if(y == cursorY && x == cursorX) - { - erase = true; - cursorDrawn = false; - } - } - - if(erase) - EraseRect(&r); - MoveTo(r.left, r.bottom - 2); - DrawChar(chars[y * cols + x].c); -} - -void IConsole::DrawCells(short x1, short x2, short y, bool erase) -{ - Rect r = { (short) (bounds.top + y * cellSizeY), (short) (bounds.left + x1 * cellSizeX), - (short) (bounds.top + (y+1) * cellSizeY), (short) (bounds.left + x2 * cellSizeX) }; - if(cursorDrawn) - { - if(y == cursorY && x1 <= cursorX && x2 > cursorX) - { - erase = true; - cursorDrawn = false; - } - } - - if(erase) - EraseRect(&r); - MoveTo(r.left, r.bottom - 2); - - Attributes a=chars[y * cols + x1].attrs; - SetAttributes(a); - for(int i=x1; i 0 ? dirtyRect.top - 1 : 0; - dirtyRect.bottom = dirtyRect.bottom > 0 ? dirtyRect.bottom - 1 : 0; -} - -void IConsole::ProcessEscSequence(char c) -{ - switch(sequenceStep) - { - case 0: - if(c=='[') - ++sequenceStep; - else - isProcessingEscSequence=false; - break; - case 1: - ++sequenceStep; - switch(c) - { - case '0': // Normal character - currentAttr.reset(); - break; - case '1': // Bold - currentAttr.setBold(true); - break; - case '3': // Italic - currentAttr.setItalic(true); - break; - case '4': // Underline - currentAttr.setUnderline(true); - break; - default: - isProcessingEscSequence=false; - } - break; - case 2: - if(c=='m') - isProcessingEscSequence=false; - else if(c==';') - sequenceStep=1; - else - isProcessingEscSequence=false; - break; - default: - sequenceStep=0; - } -} - -void IConsole::PutCharNoUpdate(char c) -{ - if(isProcessingEscSequence) - { - ProcessEscSequence(c); - return; - } - InvalidateCursor(); - switch(c) - { - case '\033': // Begin of an ANSI escape sequence - isProcessingEscSequence=true; - sequenceStep=0; - break; - case '\r': - cursorX = 0; - break; - case '\n': - cursorY++; - cursorX = 0; - if(cursorY >= rows) - ScrollUp(); - break; - default: - chars[cursorY * cols + cursorX].c = c; - chars[cursorY * cols + cursorX].attrs = currentAttr; - - if(dirtyRect.right == 0) - { - dirtyRect.right = (dirtyRect.left = cursorX) + 1; - dirtyRect.bottom = (dirtyRect.top = cursorY) + 1; - } - else - { - dirtyRect.left = std::min(dirtyRect.left, cursorX); - dirtyRect.top = std::min(dirtyRect.top, cursorY); - dirtyRect.right = std::max(dirtyRect.right, short(cursorX + 1)); - dirtyRect.bottom = std::max(dirtyRect.bottom, short(cursorY + 1)); - } - - cursorX++; - if(cursorX >= cols) - PutCharNoUpdate('\n'); - // This is to make sure the cursor width is calculated correctly - chars[cursorY * cols + cursorX].attrs = currentAttr; - } -} - -void IConsole::Update() -{ - PortSetter setport(consolePort); - FontSetup fontSetup; - - for(short row = dirtyRect.top; row < dirtyRect.bottom; ++row) - { - short start = -1; - bool needclear = false; - for(short col = dirtyRect.left; col < dirtyRect.right; ++col) - { - AttributedChar old = onscreen[row * cols + col]; - if(chars[row * cols + col] != old) - { - if(start == -1) - start = col; - if(old.c != ' ') - needclear = true; - onscreen[row * cols + col] = chars[row * cols + col]; - } - else - { - if(start != -1) - DrawCells(start, col, row, needclear); - start = -1; - needclear = false; - } - } - if(start != -1) - DrawCells(start, dirtyRect.right, row, needclear); - } - dirtyRect = Rect(); - - if(cursorVisible != cursorDrawn) - { - Rect r = CellRect(cursorX, cursorY); - if(cursorDrawn) - DrawCell(cursorX, cursorY, true); - else - InvertRect(&r); - cursorDrawn = !cursorDrawn; - } - -#if TARGET_API_MAC_CARBON - QDFlushPortBuffer(consolePort,NULL); -#endif -} - -void IConsole::putch(char c) -{ - if(!rows) - return; - PutCharNoUpdate(c); - Update(); -} - -void IConsole::write(const char *p, int n) -{ - if(!rows) - return; - - for(int i = 0; i < n; i++) - IConsole::currentInstance->PutCharNoUpdate(*p++); - Update(); -} - - -std::string IConsole::ReadLine() -{ - if(!consolePort) - return ""; - - std::string buffer; - char c; - - do - { - c = WaitNextChar(); - if(!c) - { - eof = true; - return ""; - } - - if(c == '\r') - c = '\n'; - - if(c == '\b') - { - if(buffer.size()) - { - InvalidateCursor(); - cursorX--; - PutCharNoUpdate(' '); - cursorX--; - Update(); - - buffer.resize(buffer.size()-1); - } - - continue; - } - - putch(c); - buffer.append(1,c); - } while(c != '\n'); - return buffer; -} - -void IConsole::InvalidateCursor() -{ - if(cursorDrawn) - { - PortSetter setport(consolePort); - DrawCell(cursorX, cursorY, true); - cursorDrawn = false; - } -} - -void IConsole::Idle() -{ - long ticks = TickCount(); - if(ticks - blinkTicks > 60) - { - cursorVisible = !cursorVisible; - blinkTicks = ticks; - Update(); - } -} - -void IConsole::Reshape(Rect newBounds) -{ - if(!consolePort) - return; - - InsetRect(&newBounds, 2,2); - - bounds = newBounds; - short newRows = (bounds.bottom - bounds.top) / cellSizeY; - short newCols = (bounds.right - bounds.left) / cellSizeX; - - short upshift = 0; - if(cursorY >= newRows) - { - upshift = cursorY - (newRows - 1); - - InvalidateCursor(); - cursorY = newRows - 1; - } - - std::vector newChars(newRows*newCols, AttributedChar(' ', currentAttr)); - for(short row = 0; row < newRows && row + upshift < rows; row++) - { - AttributedChar *src = &chars[(row+upshift) * cols]; - AttributedChar *dst = &newChars[row * newCols]; - std::copy(src, src + std::min(cols, newCols), dst); - } - chars.swap(newChars); - /*newChars = std::vector(newRows*newCols, ' '); - for(short row = 0; row < newRows && row < rows; row++) - { - char *src = &chars[row * cols]; - char *dst = &newChars[row * newCols]; - std::copy(src, src + std::min(cols, newCols), dst); - } - onscreen.swap(newChars);*/ - onscreen = newChars; - - rows = newRows; - cols = newCols; - - if(upshift) - { - //dirtyRect = Rect { 0, 0, rows, cols }; - //Update(); - Draw(); - } -} - -char IConsole::WaitNextChar() -{ - return 0; -} diff --git a/IConsole/retro/IConsole.h b/IConsole/retro/IConsole.h deleted file mode 100644 index 053a7a7357..0000000000 --- a/IConsole/retro/IConsole.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2012 Wolfgang Thaller. - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ -#ifndef RETRO68_CONSOLE_H_ -#define RETRO68_CONSOLE_H_ - -#include -#include -#include - -namespace retro -{ - class Attributes - { - public: - - bool isBold(void) const; - bool isUnderline(void) const; - bool isItalic(void) const; - - void setBold(const bool v); - void setUnderline(const bool v); - void setItalic(const bool v); - - Attributes(void); - void reset(void); - - private: - - bool cBold; - bool cUnderline; - bool cItalic; - }; - - class AttributedChar - { - public: - char c; - Attributes attrs; - AttributedChar(char cc, Attributes aa) {c=cc; attrs=aa;} - }; - -// inline bool operator==(const Attributes& lhs, const Attributes& rhs); -// inline bool operator!=(const Attributes& lhs, const Attributes& rhs); - - class IConsole - { - public: - IConsole(); - IConsole(GrafPtr port, Rect r); - ~IConsole(); - - void Reshape(Rect newBounds); - - void Draw(Rect r); - void Draw() { Draw(bounds); } - void putch(char c); - - void write(const char *s, int n); - std::string ReadLine(); - - static IConsole *currentInstance; - - short GetRows() const { return rows; } - short GetCols() const { return cols; } - - void Idle(); - - bool IsEOF() const { return eof; } - private: - GrafPtr consolePort = nullptr; - Rect bounds; - Attributes currentAttr; - - std::vector chars, onscreen; - bool isProcessingEscSequence; - int sequenceStep; - - short cellSizeX; - short cellSizeY; - - short rows = 0, cols = 0; - - short cursorX, cursorY; - - Rect dirtyRect = {}; - - long blinkTicks = 0; - bool cursorDrawn = false; - bool cursorVisible = true; - bool eof = false; - - void PutCharNoUpdate(char c); - void Update(); - - short CalcStartX(short x, short y); - Rect CellRect(short x, short y); - void DrawCell(short x, short y, bool erase = true); - void DrawCells(short x1, short x2, short y, bool erase = true); - void ScrollUp(short n = 1); - void ProcessEscSequence(char c); - void SetAttributes(Attributes aa); - - void InvalidateCursor(); - - virtual char WaitNextChar(); - - protected: - void Init(GrafPtr port, Rect r); - - }; - - -} - -#endif /* RETRO68_CONSOLE_H_ */ diff --git a/IConsole/retro/IConsoleWindow.cc b/IConsole/retro/IConsoleWindow.cc deleted file mode 100644 index 0872fbcc94..0000000000 --- a/IConsole/retro/IConsoleWindow.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2012 Wolfgang Thaller. - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ - -#include "IConsoleWindow.h" -#include "Events.h" -#include - -using namespace retro; - -namespace -{ - std::unordered_map *windows = NULL; -} - -IConsoleWindow::IConsoleWindow(Rect r, ConstStr255Param title) -{ - GrafPtr port; - //Retro68 Improved Console - win = NewWindow(NULL, &r, "\pThe Queen's Footsteps", true, 0, (WindowPtr)-1, true, 0); - -#if !TARGET_API_MAC_CARBON - port = win; - Rect portRect = port->portRect; -#else - port = GetWindowPort(win); - Rect portRect; - GetPortBounds(port, &portRect); -#endif - - SetPort(port); - EraseRect(&portRect); - - if(!windows) - windows = new std::unordered_map(); - (*windows)[win] = this; - - Init(port, portRect); -} - -IConsoleWindow::~IConsoleWindow() -{ - windows->erase(win); - DisposeWindow(win); -} - -char IConsoleWindow::WaitNextChar() -{ - EventRecord event; - WindowPtr eventWin; - IConsoleWindow *realConsole; -#if TARGET_API_MAC_CARBON - Rect *boundsPtr = NULL; -#else - Rect *boundsPtr = &qd.screenBits.bounds; -#endif - - do - { - #if TARGET_API_MAC_CARBON - #define SystemTask() - #endif - SystemTask(); - Idle(); - while(!GetNextEvent(everyEvent, &event)) - { - SystemTask(); - Idle(); - } - - switch(event.what) - { - case updateEvt: - eventWin = (WindowPtr)event.message; - realConsole = (*windows)[(WindowPtr)event.message]; - if(realConsole) - { - Rect updateRect; - BeginUpdate(eventWin); -#if TARGET_API_MAC_CARBON - RgnHandle rgn = NewRgn(); - GetPortVisibleRegion(GetWindowPort(eventWin), rgn); - GetRegionBounds(rgn, &updateRect); - DisposeRgn(rgn); -#else - updateRect = (*qd.thePort->visRgn)->rgnBBox; // Life was simple back then. -#endif - realConsole->Draw(updateRect); - EndUpdate(eventWin); - } - break; - case mouseDown: - switch(FindWindow(event.where, &eventWin)) - { - case inDrag: - DragWindow(eventWin, event.where, boundsPtr); - break; - case inGrow: - { - long growResult = GrowWindow(eventWin, event.where, boundsPtr); - SizeWindow(eventWin, growResult & 0xFFFF, growResult >> 16, false); - Reshape(Rect {0, 0, (short) (growResult >> 16), (short) (growResult & 0xFFFF) }); - } - break; - case inGoAway: - { - if (TrackGoAway(eventWin,event.where)) - exit(0); - } - } - break; - } - } while(event.what != keyDown && event.what != autoKey); - - return event.message & charCodeMask; -} diff --git a/IConsole/retro/IConsoleWindow.h b/IConsole/retro/IConsoleWindow.h deleted file mode 100644 index 62d820f246..0000000000 --- a/IConsole/retro/IConsoleWindow.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2012 Wolfgang Thaller. - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ - -#include -#include -#include - -#include "IConsole.h" - -namespace retro -{ - class IConsoleWindow : public IConsole - { - public: - IConsoleWindow(Rect r, ConstStr255Param title); - ~IConsoleWindow(); - private: - WindowPtr win; - - virtual char WaitNextChar(); - }; -} diff --git a/IConsole/retro/InitIConsole.cc b/IConsole/retro/InitIConsole.cc deleted file mode 100644 index 01df867552..0000000000 --- a/IConsole/retro/InitIConsole.cc +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright 2014 Wolfgang Thaller. - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "MacUtils.h" -#include "IConsole.h" -#include "IConsoleWindow.h" - -namespace retro -{ - void InitIConsole(); -} - -using namespace retro; - -void retro::InitIConsole() -{ - if(IConsole::currentInstance) - return; - IConsole::currentInstance = (IConsole*) -1; - -#if !TARGET_API_MAC_CARBON - InitGraf(&qd.thePort); - InitFonts(); - InitWindows(); - InitMenus(); - - Rect r = qd.screenBits.bounds; -#else - Rect r = (*GetMainDevice())->gdRect; -#endif - { - // give MultiFinder a chance to bring the App to front - // see Technote TB 35 - MultiFinder Miscellanea - // "If your application [...] has the canBackground bit set in the - // size resource, then it should call _EventAvail several times - // (or _WaitNextEvent or _GetNextEvent) before putting up the splash - // screen, or the splash screen will come up behind the frontmost - // layer. If the canBackground bit is set, MultiFinder will not move - // your layer to the front until you call _GetNextEvent, - // _WaitNextEvent, or _EventAvail." - - EventRecord event; - for(int i = 0; i < 5; i++) - EventAvail(everyEvent, &event); - } - - r.top += 40; - InsetRect(&r, 5,5); - - IConsole::currentInstance = new IConsoleWindow(r, "\pRetro68 IConsole"); - InitCursor(); -} - -extern "C" ssize_t _consolewrite(int fd, const void *buf, size_t count) -{ - if(!IConsole::currentInstance) - InitIConsole(); - if(IConsole::currentInstance == (IConsole*)-1) - return 0; - - IConsole::currentInstance->write((const char*)buf, count); - return count; -} - -extern "C" ssize_t _consoleread(int fd, void *buf, size_t count) -{ - if(!IConsole::currentInstance) - InitIConsole(); - if(IConsole::currentInstance == (IConsole*)-1) - return 0; - - static std::string consoleBuf; - if(consoleBuf.size() == 0) - consoleBuf = IConsole::currentInstance->ReadLine(); - - if(count > consoleBuf.size()) - count = consoleBuf.size(); - memcpy(buf, consoleBuf.data(), count); - consoleBuf = consoleBuf.substr(count); - return count; -} diff --git a/IConsole/retro/MacUtils.h b/IConsole/retro/MacUtils.h deleted file mode 100644 index 4bff8f907c..0000000000 --- a/IConsole/retro/MacUtils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2012 Wolfgang Thaller. - - This file is part of Retro68. - - Retro68 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Retro68 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Retro68. If not, see . -*/ - -#include -#include - -namespace retro -{ - class PortSetter - { - GrafPtr save; - public: - PortSetter(GrafPtr port) - { - ::GetPort(&save); - ::SetPort(port); - } - - ~PortSetter() - { - ::SetPort(save); - } - }; -}