aboutsummaryrefslogtreecommitdiff
path: root/util/fbrun/FbRun.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/fbrun/FbRun.cc')
-rw-r--r--util/fbrun/FbRun.cc285
1 files changed, 285 insertions, 0 deletions
diff --git a/util/fbrun/FbRun.cc b/util/fbrun/FbRun.cc
new file mode 100644
index 0000000..039be6b
--- /dev/null
+++ b/util/fbrun/FbRun.cc
@@ -0,0 +1,285 @@
1// FbRun.hh
2// Copyright (c) 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id: FbRun.cc,v 1.6 2002/11/13 16:44:42 fluxgen Exp $
23
24#include "FbRun.hh"
25
26#include "BaseDisplay.hh"
27
28#include <X11/Xlib.h>
29#include <X11/keysym.h>
30#include <X11/Xutil.h>
31
32#include <unistd.h>
33
34#include <iostream>
35#include <fstream>
36
37using namespace std;
38FbRun::FbRun(int x, int y, size_t width):
39m_font("fixed"),
40m_win(None),
41m_display(BaseDisplay::getXDisplay()),
42m_bevel(4),
43m_gc(DefaultGC(m_display, DefaultScreen(m_display))),
44m_end(false),
45m_current_history_item(0) {
46 createWindow(x, y, width + m_bevel, m_font.height());
47}
48
49FbRun::~FbRun() {
50 hide();
51 XDestroyWindow(m_display, m_win);
52}
53
54void FbRun::run(const std::string &command) {
55 //fork and execute program
56 if (!fork()) {
57 setsid();
58 execl("/bin/sh", "/bin/sh", "-c", command.c_str(), 0);
59 exit(0); //exit fork
60 }
61
62 hide(); // hide gui
63
64 // save command history to file
65 if (m_runtext.size() != 0) { // no need to save empty command
66 // open file in append mode
67 ofstream outfile(m_history_file.c_str(), ios::app);
68 if (outfile)
69 outfile<<m_runtext<<endl;
70 else
71 cerr<<"FbRun Warning: Can't write command history to file: "<<m_history_file<<endl;
72 }
73
74 m_end = true; // mark end of processing
75}
76
77bool FbRun::loadHistory(const char *filename) {
78 if (filename == 0)
79 return false;
80 ifstream infile(filename);
81 if (!infile) {
82 //even though we fail to load file, we should try save to it
83 m_history_file = filename;
84 return false;
85 }
86 // clear old history and load new one from file
87 m_history.clear();
88 // each line is a command
89 string line;
90 while (!infile.eof()) {
91 getline(infile, line);
92 if (line.size()) // don't add empty lines
93 m_history.push_back(line);
94 }
95 // set no current histor to display
96 m_current_history_item = m_history.size();
97 // set history file
98 m_history_file = filename;
99 return true;
100}
101
102bool FbRun::loadFont(const string &fontname) {
103 if (!m_font.load(fontname.c_str()))
104 return false;
105
106 // resize to fit new font height
107 resize(m_width, m_font.height() + m_bevel);
108 return true;
109}
110
111void FbRun::setForeground(const XColor &color) {
112 XSetForeground(m_display, m_gc, color.pixel);
113 redrawLabel();
114}
115
116void FbRun::setBackground(const XColor &color) {
117 XSetWindowBackground(m_display, m_win, color.pixel);
118 redrawLabel();
119}
120
121
122void FbRun::setText(const string &text) {
123 m_runtext = text;
124 redrawLabel();
125}
126
127void FbRun::setTitle(const string &title) {
128 assert(m_win);
129 XStoreName(m_display, m_win, const_cast<char *>(title.c_str()));
130}
131
132void FbRun::move(int x, int y) {
133 XMoveWindow(m_display, m_win, x, y);
134}
135
136void FbRun::resize(size_t width, size_t height) {
137 assert(m_win);
138 XResizeWindow(m_display, m_win, width, height);
139 m_width = width;
140 m_height = height;
141 setNoMaximize();
142}
143
144void FbRun::show() {
145 assert(m_win);
146 XMapWindow(m_display, m_win);
147}
148
149void FbRun::hide() {
150 assert(m_win);
151 XUnmapWindow(m_display, m_win);
152}
153
154void FbRun::redrawLabel() {
155 assert(m_win);
156
157 XClearWindow(m_display, m_win);
158 drawString(m_bevel/2, m_font.ascent() + m_bevel/2,
159 m_runtext.c_str(), m_runtext.size());
160
161}
162
163void FbRun::drawString(int x, int y,
164 const char *text, size_t len) {
165 assert(m_win);
166 assert(m_gc);
167 // check right boundary
168 // and adjust text drawing
169 size_t text_width = m_font.textWidth(text, len);
170 size_t startpos = 0;
171 if (text_width > m_width) {
172 for (; startpos < len; ++startpos) {
173 if (m_font.textWidth(text+startpos, len-startpos) < m_width)
174 break;
175 }
176 }
177
178 m_font.drawText(m_win, DefaultScreen(m_display), m_gc, text + startpos, len-startpos, x, y);
179}
180
181
182void FbRun::createWindow(int x, int y, size_t width, size_t height) {
183 m_win = XCreateSimpleWindow(m_display, // display
184 DefaultRootWindow(m_display), // parent windows
185 x, y,
186 width, height,
187 1, // border_width
188 0, // border
189 WhitePixel(m_display, DefaultScreen(m_display))); // background
190
191 if (m_win == None)
192 throw string("Failed to create FbRun window!");
193
194 XSelectInput(m_display, m_win, KeyPressMask|ExposureMask);
195
196 setNoMaximize();
197
198 m_width = width;
199 m_height = height;
200
201}
202
203void FbRun::handleEvent(XEvent * const xev) {
204 switch (xev->type) {
205 case KeyPress: {
206 KeySym ks;
207 char keychar[1];
208 XLookupString(&xev->xkey, keychar, 1, &ks, 0);
209 if (ks == XK_Escape) {
210 m_end = true;
211 hide();
212 return; // no more processing
213 } else if (ks == XK_Return) {
214 run(m_runtext);
215 m_runtext = ""; // clear text
216 } else if (ks == XK_BackSpace) {
217 if (m_runtext.size() != 0) { // we can't erase what we don't have ;)
218 m_runtext.erase(m_runtext.size()-1);
219 redrawLabel();
220 }
221 } else if (! IsModifierKey(ks) && !IsCursorKey(ks)) {
222 m_runtext+=keychar[0]; // append character
223 redrawLabel();
224 } else if (IsCursorKey(ks)) {
225
226 switch (ks) {
227 case XK_Up:
228 prevHistoryItem();
229 break;
230 case XK_Down:
231 nextHistoryItem();
232 break;
233 }
234 redrawLabel();
235 }
236 } break;
237 case Expose:
238 redrawLabel();
239 break;
240 default:
241 break;
242 }
243}
244
245void FbRun::getSize(size_t &width, size_t &height) {
246 XWindowAttributes attr;
247 XGetWindowAttributes(m_display, m_win, &attr);
248 width = attr.width;
249 height = attr.height;
250}
251
252void FbRun::setNoMaximize() {
253
254 size_t width, height;
255
256 getSize(width, height);
257
258 // we don't need to maximize this window
259 XSizeHints sh;
260 sh.flags = PMaxSize | PMinSize;
261 sh.max_width = width;
262 sh.max_height = height;
263 sh.min_width = width;
264 sh.min_height = height;
265 XSetWMNormalHints(m_display, m_win, &sh);
266}
267
268void FbRun::prevHistoryItem() {
269
270 if (m_current_history_item > 0 && m_history.size() > 0)
271 m_current_history_item--;
272 if (m_current_history_item < m_history.size())
273 m_runtext = m_history[m_current_history_item];
274}
275
276void FbRun::nextHistoryItem() {
277 m_current_history_item++;
278 if (m_current_history_item >= m_history.size()) {
279 m_current_history_item = m_history.size();
280 m_runtext = "";
281 return;
282 } else
283 m_runtext = m_history[m_current_history_item];
284
285}