mirror of
https://github.com/autc04/Retro68.git
synced 2025-02-16 19:32:07 +00:00
Console improvements
This commit is contained in:
parent
e7d2e37e22
commit
1048b06ce4
@ -21,6 +21,8 @@ set(CMAKE_CXX_FLAGS "-std=c++11")
|
||||
add_library(RetroConsole
|
||||
Console.cc
|
||||
Console.h
|
||||
ConsoleWindow.cc
|
||||
ConsoleWindow.h
|
||||
MacUtils.h
|
||||
InitConsole.cc
|
||||
)
|
||||
@ -31,4 +33,3 @@ add_application(ConsoleTest
|
||||
ConsoleTest.cc
|
||||
)
|
||||
target_link_libraries(ConsoleTest RetroConsole)
|
||||
|
||||
|
@ -29,10 +29,17 @@ using namespace Retro;
|
||||
|
||||
Console *Console::currentInstance = NULL;
|
||||
|
||||
Console::Console(GrafPtr port, Rect r)
|
||||
: consolePort(port), bounds(r), dirtyRect(),
|
||||
Console::Console()
|
||||
: consolePort(NULL), dirtyRect(),
|
||||
blinkTicks(0), cursorDrawn(false), cursorVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
void Console::Init(GrafPtr port, Rect r)
|
||||
{
|
||||
consolePort = port;
|
||||
bounds = r;
|
||||
|
||||
if(currentInstance == NULL)
|
||||
currentInstance = (Console*) -1;
|
||||
PortSetter setport(consolePort);
|
||||
@ -52,9 +59,16 @@ Console::Console(GrafPtr port, Rect r)
|
||||
onscreen = chars;
|
||||
|
||||
cursorX = cursorY = 0;
|
||||
|
||||
currentInstance = this;
|
||||
}
|
||||
|
||||
Console::Console(GrafPtr port, Rect r)
|
||||
: consolePort(NULL), dirtyRect(),
|
||||
blinkTicks(0), cursorDrawn(false), cursorVisible(true)
|
||||
{
|
||||
Init(port, r);
|
||||
}
|
||||
|
||||
Console::~Console()
|
||||
{
|
||||
}
|
||||
@ -103,16 +117,25 @@ void Console::DrawCells(short x1, short x2, short y, bool erase)
|
||||
DrawText(&chars[y * cols + x1], 0, x2 - x1);
|
||||
}
|
||||
|
||||
void Console::Draw()
|
||||
void Console::Draw(Rect r)
|
||||
{
|
||||
PortSetter setport(consolePort);
|
||||
|
||||
for(short row = 0; row < rows; ++row)
|
||||
short minRow = std::max(0, (r.top - bounds.top) / cellSizeY);
|
||||
short maxRow = std::min((int)rows, (r.bottom - bounds.top + cellSizeY - 1) / cellSizeY);
|
||||
|
||||
short minCol = std::max(0, (r.left - bounds.left) / cellSizeX);
|
||||
short maxCol = std::min((int)cols, (r.right - bounds.left + cellSizeX - 1) / cellSizeX);
|
||||
|
||||
EraseRect(&r);
|
||||
for(short row = minRow; row < maxRow; ++row)
|
||||
{
|
||||
for(short col = 0; col < cols; ++col)
|
||||
{
|
||||
DrawCell(col, row);
|
||||
}
|
||||
DrawCells(minCol, maxCol, row, false);
|
||||
}
|
||||
if(cursorDrawn)
|
||||
{
|
||||
Rect cursor = CellRect(cursorX, cursorY);
|
||||
InvertRect(&cursor);
|
||||
}
|
||||
onscreen = chars;
|
||||
}
|
||||
@ -231,15 +254,8 @@ std::string Console::ReadLine()
|
||||
char c;
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
Idle();
|
||||
while(!GetNextEvent(everyEvent, &event))
|
||||
Idle();
|
||||
} while(event.what != keyDown && event.what != autoKey);
|
||||
|
||||
c = event.message & charCodeMask;
|
||||
{
|
||||
c = WaitNextChar();
|
||||
|
||||
if(c == '\r')
|
||||
c = '\n';
|
||||
@ -288,3 +304,49 @@ void Console::Idle()
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
void Console::Reshape(Rect newBounds)
|
||||
{
|
||||
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<char> newChars(newRows*newCols, ' ');
|
||||
for(short row = 0; row < newRows && row + upshift < rows; row++)
|
||||
{
|
||||
char *src = &chars[(row+upshift) * cols];
|
||||
char *dst = &newChars[row * newCols];
|
||||
std::copy(src, src + std::min(cols, newCols), dst);
|
||||
}
|
||||
chars.swap(newChars);
|
||||
/*newChars = std::vector<char>(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();
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RETRO68_CONSOLE_H_
|
||||
#define RETRO68_CONSOLE_H_
|
||||
|
||||
#include <Quickdraw.h>
|
||||
#include <vector>
|
||||
@ -29,7 +31,8 @@ namespace Retro
|
||||
public:
|
||||
Console(GrafPtr port, Rect r);
|
||||
~Console();
|
||||
void Draw();
|
||||
void Draw(Rect r);
|
||||
void Draw() { Draw(bounds); }
|
||||
void putch(char c);
|
||||
|
||||
void write(const char *s, int n);
|
||||
@ -39,6 +42,8 @@ namespace Retro
|
||||
|
||||
short GetRows() const { return rows; }
|
||||
short GetCols() const { return cols; }
|
||||
|
||||
void Idle();
|
||||
private:
|
||||
GrafPtr consolePort;
|
||||
Rect bounds;
|
||||
@ -67,8 +72,17 @@ namespace Retro
|
||||
void ScrollUp(short n = 1);
|
||||
|
||||
void InvalidateCursor();
|
||||
void Idle();
|
||||
|
||||
virtual char WaitNextChar() = 0;
|
||||
|
||||
protected:
|
||||
Console();
|
||||
void Init(GrafPtr port, Rect r);
|
||||
|
||||
void Reshape(Rect newBounds);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* RETRO68_CONSOLE_H_ */
|
||||
|
@ -9,8 +9,15 @@ namespace Retro
|
||||
int main()
|
||||
{
|
||||
Retro::InitConsole();
|
||||
const char *s = "Hello, world.\n";
|
||||
Retro::Console::currentInstance->write(s, strlen(s));
|
||||
Retro::Console::currentInstance->ReadLine();
|
||||
std::string out = "Hello, world.\nEnter \"exit\" to quit.\n";
|
||||
Retro::Console::currentInstance->write(out.data(), out.size());
|
||||
|
||||
std::string in;
|
||||
do
|
||||
{
|
||||
in = Retro::Console::currentInstance->ReadLine();
|
||||
out = "You Entered: " + in;
|
||||
Retro::Console::currentInstance->write(out.data(), out.size());
|
||||
} while(in != "exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
116
Console/ConsoleWindow.cc
Normal file
116
Console/ConsoleWindow.cc
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ConsoleWindow.h"
|
||||
#include "Events.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace Retro;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<WindowPtr, ConsoleWindow*> windows;
|
||||
}
|
||||
|
||||
ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
|
||||
{
|
||||
GrafPtr port;
|
||||
|
||||
win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, false, 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);
|
||||
|
||||
windows[win] = this;
|
||||
|
||||
Init(port, portRect);
|
||||
}
|
||||
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
{
|
||||
windows.erase(win);
|
||||
DisposeWindow(win);
|
||||
}
|
||||
|
||||
char ConsoleWindow::WaitNextChar()
|
||||
{
|
||||
EventRecord event;
|
||||
WindowPtr eventWin;
|
||||
ConsoleWindow *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)
|
||||
{
|
||||
BeginUpdate(eventWin);
|
||||
realConsole->Draw((*qd.thePort->visRgn)->rgnBBox);
|
||||
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, true);
|
||||
Reshape(Rect {0, 0, (short) (growResult >> 16), (short) (growResult & 0xFFFF) });
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while(event.what != keyDown && event.what != autoKey);
|
||||
|
||||
return event.message & charCodeMask;
|
||||
}
|
38
Console/ConsoleWindow.h
Normal file
38
Console/ConsoleWindow.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Console.h"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
class ConsoleWindow : public Console
|
||||
{
|
||||
public:
|
||||
ConsoleWindow(Rect r, ConstStr255Param title);
|
||||
~ConsoleWindow();
|
||||
private:
|
||||
WindowPtr win;
|
||||
|
||||
virtual char WaitNextChar();
|
||||
};
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "MacUtils.h"
|
||||
#include "Console.h"
|
||||
#include "ConsoleWindow.h"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
@ -42,9 +43,6 @@ void Retro::InitConsole()
|
||||
{
|
||||
if(Console::currentInstance)
|
||||
return;
|
||||
|
||||
WindowPtr win;
|
||||
GrafPtr port;
|
||||
|
||||
#if !TARGET_API_MAC_CARBON
|
||||
InitGraf(&qd.thePort);
|
||||
@ -59,21 +57,9 @@ void Retro::InitConsole()
|
||||
|
||||
r.top += 40;
|
||||
InsetRect(&r, 5,5);
|
||||
win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, false, 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);
|
||||
|
||||
Console *console = new Console(port, portRect);
|
||||
|
||||
new ConsoleWindow(r, "\pRetro68 Console");
|
||||
InitCursor();
|
||||
}
|
||||
|
||||
extern "C" ssize_t _consolewrite(int fd, const void *buf, size_t count)
|
||||
|
Loading…
x
Reference in New Issue
Block a user