Skip to content

Commit

Permalink
Shell: Added text canvas classes for text-based drawing
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Jan 20, 2013
1 parent 2b47ab0 commit 3912369
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 7 deletions.
8 changes: 6 additions & 2 deletions doomsday/tools/shell/shell-text/shell-text.pro
Expand Up @@ -26,11 +26,15 @@ INCLUDEPATH += ../libshell/include

HEADERS += \
src/cursesapp.h \
src/main.h
src/main.h \
src/textcanvas.h \
src/cursestextcanvas.h

SOURCES += \
src/cursesapp.cpp \
src/main.cpp
src/main.cpp \
src/textcanvas.cpp \
src/cursestextcanvas.cpp

# Installation --------------------------------------------------------------

Expand Down
16 changes: 12 additions & 4 deletions doomsday/tools/shell/shell-text/src/cursesapp.cpp
Expand Up @@ -21,9 +21,10 @@
#include <QTextStream>
#include <QDebug>
#include "cursesapp.h"
#include "cursestextcanvas.h"
#include <curses.h>
#include <de/Vector>
#include <stdio.h>
#include <de/Vector>

static void windowResized(int)
{
Expand Down Expand Up @@ -61,10 +62,11 @@ struct CursesApp::Instance
// Curses state:
WINDOW *rootWin;
de::Vector2i rootSize;

QTimer *inputPollTimer;

Instance(CursesApp &a) : self(a)
CursesTextCanvas *canvas;

Instance(CursesApp &a) : self(a), canvas(0)
{
initCurses();
}
Expand All @@ -90,6 +92,10 @@ struct CursesApp::Instance
inputPollTimer = new QTimer(&self);
QObject::connect(inputPollTimer, SIGNAL(timeout()), &self, SLOT(pollForInput()));
inputPollTimer->start(1000 / 20);

// Create the canvas.
canvas = new CursesTextCanvas(rootSize, rootWin);
canvas->show();
}

void initCursesState()
Expand All @@ -99,7 +105,6 @@ struct CursesApp::Instance

scrollok(rootWin, FALSE);
wclear(rootWin);
wrefresh(rootWin);

// Initialize input.
cbreak();
Expand All @@ -111,6 +116,9 @@ struct CursesApp::Instance

void shutdownCurses()
{
delete canvas;
canvas = 0;

delete inputPollTimer;
inputPollTimer = 0;

Expand Down
2 changes: 1 addition & 1 deletion doomsday/tools/shell/shell-text/src/cursesapp.h
Expand Up @@ -31,7 +31,7 @@ class CursesApp : public QApplication

void windowWasResized();

public slots:
protected slots:
void pollForInput();

signals:
Expand Down
66 changes: 66 additions & 0 deletions doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp
@@ -0,0 +1,66 @@
/** @file cursestextcanvas.cpp Text-based drawing surface for curses.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "cursestextcanvas.h"

CursesTextCanvas::CursesTextCanvas(Size const &size, WINDOW *window, Coord const &originInWindow)
: TextCanvas(size), _window(window), _origin(originInWindow)
{}

void CursesTextCanvas::show()
{
Size const dims = size();

// All dirty characters are drawn.
for(int row = 0; row < dims.y; ++row)
{
bool needMove = true;

for(int col = 0; col < dims.x; ++col)
{
Coord const pos(col, row);
Char const &ch = at(pos);

if(!ch.attrib.dirty)
{
needMove = true;
continue;
}

if(needMove)
{
// Advance cursor.
wmove(_window, _origin.y + row, _origin.x + col);
needMove = false;
}

// Set attributes.
wattrset(_window,
(ch.attrib.bold? A_BOLD : 0) |
(ch.attrib.reverse? A_REVERSE : 0) |
(ch.attrib.underline? A_UNDERLINE : 0));

waddch(_window, ch.ch.unicode()); // cursor advanced
}
}

// Mark everything clean.
TextCanvas::show();

wrefresh(_window);
}
37 changes: 37 additions & 0 deletions doomsday/tools/shell/shell-text/src/cursestextcanvas.h
@@ -0,0 +1,37 @@
/** @file cursestextcanvas.h Text-based drawing surface for curses.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef CURSESTEXTCANVAS_H
#define CURSESTEXTCANVAS_H

#include <curses.h>
#include "textcanvas.h"

class CursesTextCanvas : public TextCanvas
{
public:
CursesTextCanvas(Size const &size, WINDOW *window, Coord const &originInWindow = Coord(0, 0));

void show();

private:
WINDOW *_window;
Coord _origin;
};

#endif // CURSESTEXTCANVAS_H
135 changes: 135 additions & 0 deletions doomsday/tools/shell/shell-text/src/textcanvas.cpp
@@ -0,0 +1,135 @@
/** @file textcanvas.cpp Text-based drawing surface.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "textcanvas.h"
#include <QList>

struct TextCanvas::Instance
{
Size size;

typedef QList<Char> Line;
QList<Line> lines;

Instance(Size const &initialSize) : size(initialSize)
{
// Allocate lines based on supplied initial size.
for(int row = 0; row < size.y; ++row)
{
lines.append(makeLine());
}
}

Line makeLine()
{
Line line;
for(int col = 0; col < size.x; ++col)
{
line.append(Char());
}
return line;
}

void resize(Size const &newSize)
{
if(newSize == size) return;

// Allocate or free lines.
while(newSize.y < size.y)
{
lines.removeLast();
size.y--;
}
while(newSize.y > size.y)
{
lines.append(makeLine());
size.y++;
}

// Make sure all lines are the correct width.
for(int row = 0; row < lines.size(); ++row)
{
Line &line = lines[row];
if(line.size() == newSize.x) continue;

while(newSize.x < line.size())
{
line.removeLast();
}
while(newSize.x > line.size())
{
line.append(Char());
}
}

Q_ASSERT(lines.size() == size.y);
}

void markAllAsDirty(bool markDirty)
{
for(int row = 0; row < lines.size(); ++row)
{
Line &line = lines[row];
for(int col = 0; col < line.size(); ++col)
{
line[col].attrib.dirty = markDirty;
}
}
}
};

TextCanvas::TextCanvas(Size const &size) : d(new Instance(size))
{
d->size = size;
}

TextCanvas::~TextCanvas()
{
delete d;
}

TextCanvas::Size TextCanvas::size() const
{
return d->size;
}

void TextCanvas::resize(Size const &newSize)
{
d->resize(newSize);
}

TextCanvas::Char &TextCanvas::at(Coord const &pos)
{
Q_ASSERT(pos.x >= 0 && pos.x < d->size.x);
Q_ASSERT(pos.y >= 0 && pos.y < d->size.y);
Char &c = d->lines[pos.y][pos.x];
c.attrib.dirty = true;
return c;
}

TextCanvas::Char const &TextCanvas::at(Coord const &pos) const
{
Q_ASSERT(pos.x >= 0 && pos.x < d->size.x);
Q_ASSERT(pos.y >= 0 && pos.y < d->size.y);
return d->lines[pos.y].at(pos.x);
}

void TextCanvas::show()
{
d->markAllAsDirty(false);
}

0 comments on commit 3912369

Please sign in to comment.