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