"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 14 02:50AM +0200 I've only implemented this for Windows, not for Unixland, and it's been some time since I used e.g. ncurses. The intent is to support the simple kind of stuff that Indian students now use Turbo C++ in DOSBox for. E.g. snake game, that kind of thing, what we once did on IBM PC. So, how practical/impractical is it wrt. implementation for Unix-land, e.g. in terms of ncurses? I'm thinking, maybe ncurses can't turn off automatic line wrapping or automatic scrolling, or maybe all necessary info isn't available. Or maybe (I seem to remember) different colors? Other comments? Cheers!, - Alf PS: Sorry for the pasted code rather than more easily extracted attachments, but the Eternal September server didn't like the attachments. It mumbled something about "binary". Maybe Thunderbird encoded as base64, I couldn't find anything about it in options. <file text_screen_decl.hpp> #pragma once // Copyright © 2016 Alf P. Steinbach // Screen output – a minimal interface to console windows, like ncurses. #include "../cppx/basics.hpp" #include <assert.h> // assert #include <algorithm> // std::(min, max) namespace console { using cppx::Char; using cppx::Non_copyable; using cppx::Non_movable; using cppx::operator*; using cppx::Ref_; using cppx::String; using cppx::string_from; using std::max; using std::min; inline namespace colors { struct Colorbit { enum Enum: unsigned { blue, green, red, intensity }; }; struct Color { unsigned value; friend auto operator|( const Color a, const Color b ) -> Color { return Color( a.value | b.value ); } void operator|=( const Color other ) { value |= other.value; } Color() : value( 0 ) {} explicit Color( const unsigned bits ) : value( bits ) {} Color( const Colorbit::Enum bitnum ); // System specific mapping. }; const Color bit_b = Colorbit::blue; // System specific. const Color bit_g = Colorbit::green; // System specific. const Color bit_r = Colorbit::red; // System specific. const Color bit_i = Colorbit::intensity; // System specific. const Color black = {}; const Color dark_blue = bit_b; const Color green = bit_g; const Color teal = bit_b | bit_g; const Color dark_red = bit_r; const Color purple = bit_b | bit_r; const Color olive = bit_g | bit_r; const Color light_gray = bit_b | bit_g | bit_r; const Color dark_gray = bit_i; const Color blue = bit_b | bit_i; const Color light_green = bit_g | bit_i; const Color light_cyan = bit_b | bit_g | bit_i; const Color red = bit_r | bit_i; const Color light_purple = bit_b | bit_r | bit_i; const Color yellow = bit_g | bit_r | bit_i; const Color white = bit_b | bit_g | bit_r | bit_i; } // namespace colors inline namespace geometry { struct Point { int x; int y; }; inline auto operator+( Ref_<const Point> a, Ref_<const Point> b ) -> Point { return Point{ a.x + b.x, a.y + b.y }; } inline auto operator-( Ref_<const Point> a, Ref_<const Point> b ) -> Point { return Point{ a.x - b.x, a.y - b.y }; } struct Rect { Point top_left; Point past_bottom_right; auto x1() const -> int { return top_left.x; } auto y1() const -> int { return top_left.y; } auto x2() const -> int { return past_bottom_right.x; } auto y2() const -> int { return past_bottom_right.y; } auto width() const -> int { return x2() - x1(); } auto height() const -> int { return y2() - y1(); } auto is_empty() const -> bool { return width() <= 0 or height() <= 0; } }; inline auto union_of( Ref_<const Rect> a, Ref_<const Rect> b ) -> Rect { return Rect { { min( a.x1(), b.x1() ), min( a.y1(), b.y1() ) }, { max( a.x2(), b.x2() ), max( a.y2(), b.y2() ) } }; } inline auto intersection_of( Ref_<const Rect> a, Ref_<const Rect> b ) -> Rect { // A result with ≤ 0 width or height indicates the intersection's empty. return Rect { { max( a.x1(), b.x1() ), max( a.y1(), b.y1() ) }, { min( a.x2(), b.x2() ), min( a.y2(), b.y2() ) } }; } } // namespace geometry template< class Derived > class One_at_a_time : public Non_copyable , public Non_movable { private: static auto instance_exists() -> Ref_<bool> { static bool whether_it_does; return whether_it_does; } One_at_a_time( Ref_<const One_at_a_time> ) = delete; auto operator=( Ref_<const One_at_a_time> ) -> Ref_<One_at_a_time> = delete; public: ~One_at_a_time() { instance_exists() = false; } One_at_a_time() { assert( not instance_exists() ); if( instance_exists() ) { throw 0; } instance_exists() = true; } }; // System specific: class Display : public One_at_a_time< Display > { private: class Impl; Impl* p_impl_; Display( Ref_<const Display> ) = delete; auto operator=( Ref_<const Display> ) = delete; void clear_by_writing_spaces() { const Point sz = size(); const auto spaces = sz.x*string_from( L' ' ); for( int y = 0; y < sz.y; ++y ) { write_at( {0, y}, spaces ); } gotoxy( 0, 0 ); } public: auto size() const -> Point; // Equivalent to clear_by_writing_spaces(), but can be faster: void clear(); auto position() const -> Point; void gotoxy( const Point pos ); auto textcolor() const -> Color; void set_textcolor( const Color c ); auto bgcolor() const -> Color; void set_bgcolor( const Color c ); void write( Ref_<const String> s ); void gotoxy( const int x, const int y ) { gotoxy( {x, y} ); } void write_at( const Point pos, Ref_<const String> s ) { gotoxy( pos ); write( s ); } ~Display(); Display( Ref_<const String> title, const Point size = Point{ 120, 30 } ); }; } // namespace console </file> <file cppx/basics.hpp> #pragma once // Copyright © 2016 Alf P. Steinbach // // Configuration macro symbols: // • CPPX_NO_IOSTREAMS Don't drag in the iostreams header, please. // • CPPX_STDLIB_HAS_QUICK_EXIT Force assumption that std::quick_exit exists. // • NDEBUG Standard meaning (here: suppress tracing). #include <assert.h> // assert #ifndef CPPX_NO_IOSTREAMS # include <iostream> // std::(wistream, wostream, wcin, wcout, wcerr, endl)
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment