FreeNOS
Terminal.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <Types.h>
19 #include <Macros.h>
20 #include <VGA.h>
21 #include <Runtime.h>
22 #include "Terminal.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 
30 {
31  BLACK,
32  RED,
33  LIGHTGREEN,
34  LIGHTBROWN,
35  LIGHTBLUE,
37  LIGHTCYAN,
38  LIGHTGREY,
39  LIGHTGREY,
40 };
41 
42 Terminal::Terminal(const u32 inode,
43  const char *in,
44  const char *out,
45  const Size w,
46  const Size h)
48  , inputFile(in)
49  , outputFile(out)
50  , width(w)
51  , height(h)
52 {
53  m_identifier << "tty0";
54  buffer = new u16[width * height];
55 }
56 
58 {
59  teken_pos_t winsz;
60 
61  // Close standard I/O
62  ::close(0);
63  ::close(1);
64 
65  // Attempt to open input file.
66  if ((input = ::open(inputFile, O_RDONLY)) < 0)
67  {
68  printf("failed to open `%s': %s\r\n",
70  return FileSystem::IOError;
71  }
72 
73  // Then open the output file.
74  if ((output = ::open(outputFile, O_RDWR)) < 0)
75  {
76  printf("failed to open `%s': %s\r\n",
78  return FileSystem::IOError;
79  }
80 
81  // Fill in function pointers
89 
90  // Reset cursor
91  memset(&cursorPos, 0, sizeof(cursorPos));
92 
93  // Initialize libteken
94  teken_init(&state, &funcs, this);
95 
96  // Set appropriate terminal sizes
97  winsz.tp_col = 80;
98  winsz.tp_row = 25;
99  teken_set_winsize(&state, &winsz);
100 
101  // Print banners
102  writeTerminal((const u8 *)(BANNER COPYRIGHT "\r\n"), strlen(BANNER)+strlen(COPYRIGHT)+2);
103 
104  // Done
105  return FileSystem::Success;
106 }
107 
109 {
110  delete buffer;
111  ::close(input);
112  ::close(output);
113 }
114 
116 {
117  return width;
118 }
119 
121 {
122  return height;
123 }
124 
126 {
127  return input;
128 }
129 
131 {
132  return output;
133 }
134 
136 {
137  return buffer;
138 }
139 
141 {
142  return &cursorValue;
143 }
144 
146  Size & size,
147  const Size offset)
148 {
149  char tmp[255];
150  int n;
151 
152  n = ::read(input, tmp, size < sizeof(tmp) ? size : sizeof(tmp));
153  if (n < 0)
154  {
155  return FileSystem::IOError;
156  }
157  else if (n > 0)
158  {
159  buffer.write(tmp, n);
160  }
161 
162  size = n;
163  return FileSystem::Success;
164 }
165 
167  Size & size,
168  const Size offset)
169 {
170  return writeTerminal(buffer.getBuffer(), size);
171 }
172 
174  const Size size)
175 {
176  char cr = '\r', ch;
177 
178  // Initialize buffer with the current screen first
179  ::lseek(output, 0, SEEK_SET);
180  ::read(output, this->buffer, width * height * 2);
181 
182  // Loop all input characters. Add an additional carriage return
183  // whenever a linefeed is detected.
184  for (Size i = 0; i < size; i++)
185  {
186  if (bytes[i] == '\n')
187  {
188  teken_input(&state, &cr, 1);
189  }
190  ch = bytes[i];
191  teken_input(&state, &ch, 1);
192  }
193 
194  // Flush changes back to our output device
195  ::lseek(output, 0, SEEK_SET);
196  ::write(output, this->buffer, width * height * 2);
197 
198  // Done
199  return FileSystem::Success;
200 }
201 
203 {
204  u16 index = cursorPos.tp_col + (cursorPos.tp_row * width);
205 
206  // Restore old attributes
207  buffer[index] &= 0xff;
208  buffer[index] |= (cursorValue & 0xff00);
209 }
210 
212 {
213  // Save value
214  cursorValue = buffer[pos->tp_col + (pos->tp_row * width)];
215  cursorPos = *pos;
216 }
217 
219 {
220  u16 index = cursorPos.tp_col + (cursorPos.tp_row * width);
221 
222  // Refresh cursorValue first
224 
225  // Write cursor
226  buffer[index] &= 0xff;
227  buffer[index] |= VGA_ATTR(LIGHTGREY, LIGHTGREY) << 8;
228 }
229 
230 void bell(Terminal *term)
231 {
232  // Does nothing yet
233 }
234 
235 void putchar(Terminal *term, const teken_pos_t *pos,
236  teken_char_t ch, const teken_attr_t *attr)
237 {
238  // Retrieve variables first
239  u16 *buffer = term->getBuffer();
240  Size width = term->getWidth();
241 
242  // Make sure to don't overwrite cursor
243  term->hideCursor();
244 
245  // Write the buffer
246  buffer[pos->tp_col + (pos->tp_row * width)] =
247  VGA_CHAR(ch, tekenToVGA[attr->ta_fgcolor], BLACK);
248 
249  // Show cursor again
250  term->showCursor();
251 }
252 
253 void cursor(Terminal *term, const teken_pos_t *pos)
254 {
255  term->hideCursor();
256  term->setCursor(pos);
257  term->showCursor();
258 }
259 
260 void fill(Terminal *term, const teken_rect_t *rect,
261  teken_char_t ch, const teken_attr_t *attr)
262 {
263  // Make sure we don't overwrite the cursor
264  term->hideCursor();
265 
266  // Fill video memory; loop rows
267  for (Size row = rect->tr_begin.tp_row;
268  row < rect->tr_end.tp_row; row++)
269  {
270  // Loop columns
271  for (Size col = rect->tr_begin.tp_col;
272  col < rect->tr_end.tp_col; col++)
273  {
274  term->getBuffer()[col + (row * term->getWidth())] =
275  VGA_CHAR(ch, tekenToVGA[attr->ta_fgcolor], BLACK);
276  }
277  }
278  // Show cursor again
279  term->showCursor();
280 }
281 
282 void copy(Terminal *term, const teken_rect_t *rect,
283  const teken_pos_t *pos)
284 {
285  // Retrieve variables
286  u16 *buffer = term->getBuffer();
287  Size width = term->getWidth();
288 
289  // Calculate sizes
290  Size numCols = rect->tr_end.tp_col - rect->tr_begin.tp_col;
291  Size numRows = rect->tr_end.tp_row - rect->tr_begin.tp_row;
292 
293  // Hide cursor first
294  term->hideCursor();
295 
296  // Copy video memory
297  memcpy(buffer + pos->tp_col + (pos->tp_row * width),
298  buffer + rect->tr_begin.tp_col + (rect->tr_begin.tp_row * width),
299  numCols + (numRows * width) * sizeof(u16));
300 
301  // Show cursor again
302  term->showCursor();
303 }
304 
305 void param(Terminal *term, int key, int value)
306 {
307  // Do nothing
308 }
309 
310 void respond(Terminal *ctx, const void *buf, size_t size)
311 {
312  // Do nothing
313 }
Terminal::output
int output
Definition: Terminal.h:204
VGA.h
LIGHTGREY
@ LIGHTGREY
Definition: VGA.h:73
Runtime.h
copy
void copy(Terminal *term, const teken_rect_t *rect, const teken_pos_t *pos)
Copy bytes to the terminal.
Definition: Terminal.cpp:282
tf_copy_t
void tf_copy_t(void *, const teken_rect_t *, const teken_pos_t *)
Definition: teken.h:100
Terminal::writeTerminal
FileSystem::Result writeTerminal(const u8 *bytes, const Size size)
Write bytes to the output device.
Definition: Terminal.cpp:173
Terminal::cursorPos
teken_pos_t cursorPos
Saved cursor position.
Definition: Terminal.h:188
Terminal::inputFile
const char * inputFile
Path to the input and output files.
Definition: Terminal.h:196
Macros.h
fcntl.h
Terminal::getInput
int getInput()
Retrieve file descriptor of the input source.
Definition: Terminal.cpp:125
strlen
size_t strlen(const char *str)
Calculate the length of a string.
Definition: strlen.cpp:21
Types.h
errno
C int errno
The lvalue errno is used by many functions to return error values.
teken_attr_t::ta_fgcolor
teken_color_t ta_fgcolor
Definition: teken.h:78
tf_cursor_t
void tf_cursor_t(void *, const teken_pos_t *)
Definition: teken.h:95
string.h
Terminal::setCursor
void setCursor(const teken_pos_t *pos)
Sets the new position of the cursor.
Definition: Terminal.cpp:211
Terminal::buffer
u16 * buffer
Buffer for local Terminal updates.
Definition: Terminal.h:185
Terminal::getCursorValue
u16 * getCursorValue()
Saved byte and attribute value at cursor position.
Definition: Terminal.cpp:140
LIGHTBROWN
@ LIGHTBROWN
Definition: VGA.h:80
Terminal::~Terminal
virtual ~Terminal()
Class destructor.
Definition: Terminal.cpp:108
VGA_ATTR
#define VGA_ATTR(front, back)
Encodes VGA attributes.
Definition: VGA.h:48
Device
Abstract device class interface.
Definition: Device.h:35
teken_funcs_t::tf_copy
tf_copy_t * tf_copy
Definition: teken.h:118
teken_attr_t
Definition: teken.h:76
Terminal::state
teken_t state
Terminal state.
Definition: Terminal.h:179
tekenToVGA
u8 tekenToVGA[]
Definition: Terminal.cpp:29
Terminal::height
const Size height
Definition: Terminal.h:201
param
void param(Terminal *term, int key, int value)
Set terminal parameters.
Definition: Terminal.cpp:305
FileSystem::IOError
@ IOError
Definition: FileSystem.h:58
teken_rect_t::tr_end
teken_pos_t tr_end
Definition: teken.h:74
open
int open(const char *path, int oflag,...)
Open file relative to directory file descriptor.
Definition: open.cpp:26
FileSystem::Success
@ Success
Definition: FileSystem.h:54
teken_funcs_t::tf_respond
tf_respond_t * tf_respond
Definition: teken.h:120
tf_fill_t
void tf_fill_t(void *, const teken_rect_t *, teken_char_t, const teken_attr_t *)
Definition: teken.h:98
teken_pos_t::tp_col
teken_unit_t tp_col
Definition: teken.h:70
teken_funcs_t::tf_putchar
tf_putchar_t * tf_putchar
Definition: teken.h:116
teken_set_winsize
void teken_set_winsize(teken_t *t, const teken_pos_t *p)
Definition: teken.c:337
Terminal::showCursor
void showCursor()
Show the VGA cursor.
Definition: Terminal.cpp:218
Terminal::cursorValue
u16 cursorValue
Saved value at cursor position.
Definition: Terminal.h:191
Terminal::initialize
virtual FileSystem::Result initialize()
Initialize the Terminal.
Definition: Terminal.cpp:57
printf
int printf(const char *format,...)
Output a formatted string to standard output.
Definition: printf.cpp:22
close
int close(int fildes)
Close a file descriptor.
Definition: close.cpp:22
Terminal::funcs
teken_funcs_t funcs
Terminal function handlers.
Definition: Terminal.h:182
teken_input
void teken_input(teken_t *t, const void *buf, size_t len)
Definition: teken.c:289
tf_bell_t
void tf_bell_t(void *)
Definition: teken.h:94
Terminal::getWidth
Size getWidth()
Retrieve the width of the Terminal.
Definition: Terminal.cpp:115
Terminal::read
virtual FileSystem::Result read(IOBuffer &buffer, Size &size, const Size offset)
Read bytes from the Terminal.
Definition: Terminal.cpp:145
u16
unsigned short u16
Unsigned 16-bit number.
Definition: Types.h:56
IOBuffer
Abstract Input/Output buffer.
Definition: IOBuffer.h:37
stdio.h
cursor
void cursor(Terminal *term, const teken_pos_t *pos)
Sets the Terminal cursor.
Definition: Terminal.cpp:253
strerror
char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition: strerror.cpp:20
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
teken_init
void teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
Definition: teken.c:173
LIGHTMAGENTA
@ LIGHTMAGENTA
Definition: VGA.h:79
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
bell
void bell(Terminal *term)
Makes a sound (bell).
Definition: Terminal.cpp:230
BANNER
#define BANNER
Print this banner per default on new Terminals.
Definition: Terminal.h:38
tf_respond_t
void tf_respond_t(void *, const void *, size_t)
Definition: teken.h:111
O_RDWR
#define O_RDWR
Open for reading and writing.
Definition: fcntl.h:84
teken_funcs_t::tf_param
tf_param_t * tf_param
Definition: teken.h:119
teken_char_t
unsigned char teken_char_t
Definition: teken.h:49
teken_pos_t::tp_row
teken_unit_t tp_row
Definition: teken.h:69
lseek
off_t lseek(int fildes, off_t offset, int whence)
Move the read/write file offset.
Definition: lseek.cpp:22
tf_putchar_t
void tf_putchar_t(void *, const teken_pos_t *, teken_char_t, const teken_attr_t *)
Definition: teken.h:96
teken_rect_t::tr_begin
teken_pos_t tr_begin
Definition: teken.h:73
LIGHTCYAN
@ LIGHTCYAN
Definition: VGA.h:77
unistd.h
Terminal::Terminal
Terminal(const u32 inode, const char *inputFile, const char *outputFile, const Size width=80, const Size height=25)
Class constructor.
Definition: Terminal.cpp:42
Device::m_identifier
String m_identifier
Unique identifier for this Device.
Definition: Device.h:79
FileSystem::CharacterDeviceFile
@ CharacterDeviceFile
Definition: FileSystem.h:75
SEEK_SET
#define SEEK_SET
Seek relative to start-of-file.
Definition: stdio.h:46
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
Terminal::hideCursor
void hideCursor()
Hides the cursor from the VGA screen.
Definition: Terminal.cpp:202
teken_funcs_t::tf_cursor
tf_cursor_t * tf_cursor
Definition: teken.h:115
Terminal.h
Terminal::getBuffer
u16 * getBuffer()
Retrieve a pointer to the local buffer.
Definition: Terminal.cpp:135
memset
void * memset(void *dest, int ch, size_t count)
Fill memory with a constant byte.
Definition: memset.cpp:20
LIGHTGREEN
@ LIGHTGREEN
Definition: VGA.h:76
tf_param_t
void tf_param_t(void *, int, unsigned int)
Definition: teken.h:101
teken_pos_t
Definition: teken.h:68
FileSystem
Definition: FileSystem.h:31
RED
@ RED
Definition: VGA.h:70
LIGHTBLUE
@ LIGHTBLUE
Definition: VGA.h:75
teken_funcs_t::tf_fill
tf_fill_t * tf_fill
Definition: teken.h:117
Terminal::getHeight
Size getHeight()
Retrieve the height of the Terminal.
Definition: Terminal.cpp:120
Terminal::width
const Size width
Width and height of the Terminal.
Definition: Terminal.h:201
Terminal::getOutput
int getOutput()
Retrieve file descriptor of the output source.
Definition: Terminal.cpp:130
VGA_CHAR
#define VGA_CHAR(ch, front, back)
Encodes a character for VGA output.
Definition: VGA.h:58
stdlib.h
memcpy
void * memcpy(void *dest, const void *src, size_t count)
Copy memory from one place to another.
Definition: memcpy.cpp:20
teken_funcs_t::tf_bell
tf_bell_t * tf_bell
Definition: teken.h:114
respond
void respond(Terminal *ctx, const void *buf, size_t size)
Unused.
Definition: Terminal.cpp:310
Terminal::input
int input
Input and output file descriptors.
Definition: Terminal.h:204
O_RDONLY
#define O_RDONLY
Open for reading only.
Definition: fcntl.h:81
fill
void fill(Terminal *term, const teken_rect_t *rect, teken_char_t ch, const teken_attr_t *attr)
Fills the Terminal buffer with a character.
Definition: Terminal.cpp:260
BLACK
@ BLACK
Definition: VGA.h:66
putchar
void putchar(Terminal *term, const teken_pos_t *pos, teken_char_t ch, const teken_attr_t *attr)
Output a new character.
Definition: Terminal.cpp:235
Terminal
A Terminal enables user to interact with the system.
Definition: Terminal.h:44
teken_rect_t
Definition: teken.h:72
Terminal::outputFile
const char * outputFile
Definition: Terminal.h:196
Terminal::write
virtual FileSystem::Result write(IOBuffer &buffer, Size &size, const Size offset)
Write bytes to the Terminal.
Definition: Terminal.cpp:166