1 //
2 // This file is part of libyacurs.
3 // Copyright (C) 2013  Rafael Ostertag
4 //
5 // This program is free software: you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program.  If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19 //
20 // $Id$
21 
22 #include <cerrno>
23 #include <cstdlib>
24 
25 #include "colors.h"
26 #include "curs.h"
27 #include "eventqueue.h"
28 #include "lineobject.h"
29 #include "yacursconst.h"
30 #include "yacursex.h"
31 
32 using namespace YACURS;
33 
34 //
35 // Private
36 //
37 
compute_margin()38 void LineObject::compute_margin() {
39 #ifndef NDEBUG
40     Margin _m_debug;
41 #endif  // NDEBUG
42     switch (_position) {
43         case POS_TOP:
44 #ifdef NDEBUG
45             margin(Margin(0, 0, area().rows() - 1, 0));
46 #else   // NDEBUG
47             _m_debug = Margin(0, 0, area().rows() - 1, 0);
48             assert(_m_debug.bottom() >= 0);
49             margin(_m_debug);
50 #endif  // NDEBUG
51             break;
52 
53         case POS_BOTTOM:
54 #ifdef NDEBUG
55             margin(Margin(area().rows() - 1, 0, 0, 0));
56 #else  // NDEBUG
57             _m_debug = Margin(area().rows() - 1, 0, 0, 0);
58             assert(_m_debug.top() >= 0);
59             margin(_m_debug);
60 #endif
61             break;
62     }
63 }
64 
text_length() const65 size_t LineObject::text_length() const {
66 #ifdef YACURS_USE_WCHAR
67     size_t mbslen = std::mbstowcs(0, _linetext.c_str(), 0);
68     if (mbslen == (size_t)-1) throw EXCEPTIONS::SystemError(errno);
69 
70     return mbslen;
71 #else
72     return _linetext.length();
73 #endif
74 }
75 
76 //
77 // Protected
78 //
79 
put_line()80 void LineObject::put_line() {
81     if (!(realization() == REALIZED || realization() == REALIZING)) return;
82 
83     curses_window()->erase();
84 
85     if (text_length() < 1) return;
86 
87     assert(area().cols() >= MIN_COLS);
88     if (static_cast<std::string::size_type>(area().cols()) <= text_length()) {
89         // Since we are here, the text is too big for the screen
90         // width, so we can't align anyway.
91         CurStr tmp(_linetext, Coordinates(0, 0));
92         curses_window()->addstrx(tmp);
93     } else {
94         int hpos = 0;
95         switch (_alignment) {
96             case LEFT:
97                 // Nothing to do, since hpos is == 0
98                 assert(hpos == 0);
99                 break;
100 
101             case CENTER:
102                 assert(static_cast<std::string::size_type>(area().cols()) >=
103                        text_length());
104                 hpos = (area().cols() - text_length()) / 2;
105                 break;
106 
107             case RIGHT:
108                 assert(static_cast<std::string::size_type>(area().cols()) >=
109                        text_length());
110                 hpos = area().cols() - text_length();
111                 break;
112         }
113 
114         CurStr tmp(_linetext, Coordinates(hpos, 0), color());
115         curses_window()->addstr(tmp);
116     }
117 }
118 
119 //
120 // Public
121 //
LineObject(POSITION pos,const std::string & t,COLOROBJ c)122 LineObject::LineObject(POSITION pos, const std::string& t, COLOROBJ c)
123     : _linetext(t), _position(pos), _alignment(LEFT) {
124     color(c);
125 }
126 
~LineObject()127 LineObject::~LineObject() {}
128 
line(const std::string & str)129 void LineObject::line(const std::string& str) {
130     _linetext = str;
131     // Refresh is responsible for taking care of whether or not the
132     // refresh can happen, for instance, it cannot happen if the
133     // object is not realized.
134     refresh(true);
135 }
136 
alignment(ALIGNMENT a)137 void LineObject::alignment(ALIGNMENT a) {
138     _alignment = a;
139 
140     if (realization() == REALIZED) refresh(true);
141 }
142 
alignment() const143 LineObject::ALIGNMENT LineObject::alignment() const { return _alignment; }
144 
line() const145 std::string LineObject::line() const { return _linetext; }
146 
realize()147 void LineObject::realize() {
148     REALIZE_ENTER;
149     compute_margin();
150     WindowBase::realize();
151     REALIZE_LEAVE;
152 }
153 
refresh(bool immediate)154 void LineObject::refresh(bool immediate) {
155     if (realization() != REALIZED) return;
156     put_line();
157 
158     curses_window()->set_color(YACURS::DEFAULT);
159 
160     WindowBase::refresh(immediate);
161 }
162