source: mainline/uspace/lib/fb/screenbuffer.c@ 7711296

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7711296 was 7c014d1, checked in by Martin Decky <martin@…>, 14 years ago

console and framebuffer server rewrite

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup console
30 * @{
31 */
32/** @file
33 */
34
35#include <io/style.h>
36#include <malloc.h>
37#include <unistd.h>
38#include <assert.h>
39#include <bool.h>
40#include <as.h>
41#include "screenbuffer.h"
42
43/** Structure for buffering state of one virtual console.
44 *
45 */
46struct screenbuffer {
47 size_t size; /**< Structure size */
48 screenbuffer_flag_t flags; /**< Screenbuffer flags */
49
50 sysarg_t cols; /**< Number of columns */
51 sysarg_t rows; /**< Number of rows */
52
53 sysarg_t col; /**< Current column */
54 sysarg_t row; /**< Current row */
55 bool cursor_visible; /**< Cursor visibility */
56
57 char_attrs_t attrs; /**< Current attributes */
58
59 sysarg_t top_row; /**< The first row in the cyclic buffer */
60 charfield_t data[]; /**< Screen contents (cyclic buffer) */
61};
62
63/** Create a screenbuffer.
64 *
65 * @param[in] cols Number of columns.
66 * @param[in] rows Number of rows.
67 * @param[in] flags Screenbuffer flags.
68 *
69 * @return New screenbuffer.
70 * @return NULL on failure.
71 *
72 */
73screenbuffer_t *screenbuffer_create(sysarg_t cols, sysarg_t rows,
74 screenbuffer_flag_t flags)
75{
76 size_t size =
77 sizeof(screenbuffer_t) + cols * rows * sizeof(charfield_t);
78 screenbuffer_t *scrbuf;
79
80 if ((flags & SCREENBUFFER_FLAG_SHARED) == SCREENBUFFER_FLAG_SHARED) {
81 scrbuf = (screenbuffer_t *) as_get_mappable_page(size);
82
83 if (as_area_create((void *) scrbuf, size, AS_AREA_READ |
84 AS_AREA_WRITE | AS_AREA_CACHEABLE) != (void *) scrbuf)
85 return NULL;
86 } else {
87 scrbuf = (screenbuffer_t *) malloc(size);
88 if (scrbuf == NULL)
89 return NULL;
90 }
91
92 scrbuf->size = size;
93 scrbuf->flags = flags;
94 scrbuf->cols = cols;
95 scrbuf->rows = rows;
96 scrbuf->cursor_visible = false;
97
98 scrbuf->attrs.type = CHAR_ATTR_STYLE;
99 scrbuf->attrs.val.style = STYLE_NORMAL;
100
101 scrbuf->top_row = 0;
102 screenbuffer_clear(scrbuf);
103
104 return scrbuf;
105}
106
107/** Return keyfield by coordinates
108 *
109 * The back buffer is organized as a cyclic buffer.
110 * Therefore we must take into account the topmost column.
111 *
112 * @param scrbuf Screenbuffer
113 * @param col Column position on screen
114 * @param row Row position on screen
115 *
116 * @return Keyfield structure on (row, col)
117 *
118 */
119charfield_t *screenbuffer_field_at(screenbuffer_t *scrbuf, sysarg_t col,
120 sysarg_t row)
121{
122 return scrbuf->data +
123 ((row + scrbuf->top_row) % scrbuf->rows) * scrbuf->cols +
124 col;
125}
126
127bool screenbuffer_cursor_at(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
128{
129 return ((scrbuf->cursor_visible) && (scrbuf->col == col) &&
130 (scrbuf->row == row));
131}
132
133sysarg_t screenbuffer_get_top_row(screenbuffer_t *scrbuf)
134{
135 return scrbuf->top_row;
136}
137
138static sysarg_t screenbuffer_update_rows(screenbuffer_t *scrbuf)
139{
140 if (scrbuf->row == scrbuf->rows) {
141 scrbuf->row = scrbuf->rows - 1;
142 scrbuf->top_row = (scrbuf->top_row + 1) % scrbuf->rows;
143 screenbuffer_clear_row(scrbuf, scrbuf->row);
144
145 return scrbuf->rows;
146 }
147
148 return 2;
149}
150
151static sysarg_t screenbuffer_update_cols(screenbuffer_t *scrbuf)
152{
153 /* Column overflow */
154 if (scrbuf->col == scrbuf->cols) {
155 scrbuf->col = 0;
156 scrbuf->row++;
157 return screenbuffer_update_rows(scrbuf);
158 }
159
160 return 1;
161}
162
163/** Store one character to screenbuffer.
164 *
165 * Its position is determined by scrbuf->col
166 * and scrbuf->row.
167 *
168 * @param scrbuf Screenbuffer.
169 * @param ch Character to store.
170 * @param update Update coordinates.
171 *
172 * @return Number of rows which have been affected. In usual
173 * situations this is 1. If the current position was
174 * updated to a new row, this value is 2.
175 *
176 */
177sysarg_t screenbuffer_putchar(screenbuffer_t *scrbuf, wchar_t ch, bool update)
178{
179 assert(scrbuf->col < scrbuf->cols);
180 assert(scrbuf->row < scrbuf->rows);
181
182 charfield_t *field =
183 screenbuffer_field_at(scrbuf, scrbuf->col, scrbuf->row);
184
185 field->ch = ch;
186 field->attrs = scrbuf->attrs;
187 field->flags |= CHAR_FLAG_DIRTY;
188
189 if (update) {
190 scrbuf->col++;
191 return screenbuffer_update_cols(scrbuf);
192 }
193
194 return 1;
195}
196
197/** Jump to a new row in screenbuffer.
198 *
199 * @param scrbuf Screenbuffer.
200 *
201 * @return Number of rows which have been affected. In usual
202 * situations this is 2 (the original row and the new
203 * row).
204 *
205 */
206sysarg_t screenbuffer_newline(screenbuffer_t *scrbuf)
207{
208 assert(scrbuf->col < scrbuf->cols);
209 assert(scrbuf->row < scrbuf->rows);
210
211 scrbuf->col = 0;
212 scrbuf->row++;
213
214 return screenbuffer_update_rows(scrbuf);
215}
216
217/** Jump to a new row in screenbuffer.
218 *
219 * @param scrbuf Screenbuffer.
220 * @param tab_size Tab size.
221 *
222 * @return Number of rows which have been affected. In usual
223 * situations this is 1. If the current position was
224 * updated to a new row, this value is 2.
225 *
226 */
227sysarg_t screenbuffer_tabstop(screenbuffer_t *scrbuf, sysarg_t tab_size)
228{
229 assert(scrbuf->col < scrbuf->cols);
230 assert(scrbuf->row < scrbuf->rows);
231
232 sysarg_t spaces = tab_size - scrbuf->cols % tab_size;
233 sysarg_t flush = 1;
234
235 for (sysarg_t i = 0; i < spaces; i++)
236 flush += screenbuffer_putchar(scrbuf, ' ', true) - 1;
237
238 return flush;
239}
240
241/** Jump to the previous character in screenbuffer.
242 *
243 * Currently no scrollback is supported.
244 *
245 * @param scrbuf Screenbuffer.
246 *
247 * @return Number of rows which have been affected. In usual
248 * situations this is 1. If the current position was
249 * updated to the previous row, this value is 2.
250 * @return 0 if no backspace is possible.
251 *
252 */
253sysarg_t screenbuffer_backspace(screenbuffer_t *scrbuf)
254{
255 assert(scrbuf->col < scrbuf->cols);
256 assert(scrbuf->row < scrbuf->rows);
257
258 if ((scrbuf->col == 0) && (scrbuf->row == 0))
259 return 0;
260
261 if (scrbuf->col == 0) {
262 scrbuf->col = scrbuf->cols - 1;
263 scrbuf->row--;
264
265 screenbuffer_putchar(scrbuf, ' ', false);
266 return 2;
267 }
268
269 scrbuf->col--;
270 screenbuffer_putchar(scrbuf, ' ', false);
271 return 1;
272}
273
274/** Clear the screenbuffer.
275 *
276 * @param scrbuf Screenbuffer.
277 *
278 */
279void screenbuffer_clear(screenbuffer_t *scrbuf)
280{
281 for (size_t pos = 0; pos < (scrbuf->cols * scrbuf->rows); pos++) {
282 scrbuf->data[pos].ch = 0;
283 scrbuf->data[pos].attrs = scrbuf->attrs;
284 scrbuf->data[pos].flags = CHAR_FLAG_DIRTY;
285 }
286
287 scrbuf->col = 0;
288 scrbuf->row = 0;
289}
290
291/** Update current screenbuffer coordinates
292 *
293 * @param scrbuf Screenbuffer.
294 * @param col New column.
295 * @param row New row.
296 *
297 */
298void screenbuffer_set_cursor(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
299{
300 scrbuf->col = col;
301 scrbuf->row = row;
302}
303
304void screenbuffer_set_cursor_visibility(screenbuffer_t *scrbuf, bool visible)
305{
306 scrbuf->cursor_visible = visible;
307}
308
309/** Get current screenbuffer coordinates
310 *
311 * @param scrbuf Screenbuffer.
312 * @param col Column.
313 * @param row Row.
314 *
315 */
316void screenbuffer_get_cursor(screenbuffer_t *scrbuf, sysarg_t *col,
317 sysarg_t *row)
318{
319 assert(col);
320 assert(row);
321
322 *col = scrbuf->col;
323 *row = scrbuf->row;
324}
325
326bool screenbuffer_get_cursor_visibility(screenbuffer_t *scrbuf)
327{
328 return scrbuf->cursor_visible;
329}
330
331/** Clear one buffer row.
332 *
333 * @param scrbuf Screenbuffer.
334 * @param row Row to clear.
335 *
336 */
337void screenbuffer_clear_row(screenbuffer_t *scrbuf, sysarg_t row)
338{
339 for (sysarg_t col = 0; col < scrbuf->cols; col++) {
340 charfield_t *field =
341 screenbuffer_field_at(scrbuf, col, row);
342
343 field->ch = 0;
344 field->attrs = scrbuf->attrs;
345 field->flags |= CHAR_FLAG_DIRTY;
346 }
347}
348
349/** Set screenbuffer style.
350 *
351 * @param scrbuf Screenbuffer.
352 * @param style Style.
353 *
354 */
355void screenbuffer_set_style(screenbuffer_t *scrbuf, console_style_t style)
356{
357 scrbuf->attrs.type = CHAR_ATTR_STYLE;
358 scrbuf->attrs.val.style = style;
359}
360
361/** Set screenbuffer color.
362 *
363 * @param scrbuf Screenbuffer.
364 * @param bgcolor Background color.
365 * @param fgcolor Foreground color.
366 * @param attr Color attribute.
367 *
368 */
369void screenbuffer_set_color(screenbuffer_t *scrbuf, console_color_t bgcolor,
370 console_color_t fgcolor, console_color_attr_t attr)
371{
372 scrbuf->attrs.type = CHAR_ATTR_INDEX;
373 scrbuf->attrs.val.index.bgcolor = bgcolor;
374 scrbuf->attrs.val.index.fgcolor = fgcolor;
375 scrbuf->attrs.val.index.attr = attr;
376}
377
378/** Set screenbuffer RGB color.
379 *
380 * @param scrbuf Screenbuffer.
381 * @param bgcolor Background color.
382 * @param fgcolor Foreground color.
383 *
384 */
385void screenbuffer_set_rgb_color(screenbuffer_t *scrbuf, pixel_t bgcolor,
386 pixel_t fgcolor)
387{
388 scrbuf->attrs.type = CHAR_ATTR_RGB;
389 scrbuf->attrs.val.rgb.bgcolor = bgcolor;
390 scrbuf->attrs.val.rgb.fgcolor = fgcolor;
391}
392
393/** @}
394 */
Note: See TracBrowser for help on using the repository browser.