teken_demo.c revision 186729
1/*- 2 * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> 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 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/syscons/teken/teken_demo.c 186729 2009-01-03 22:51:54Z ed $ 27 */ 28 29#include <sys/ioctl.h> 30 31#include <assert.h> 32#include <errno.h> 33#include <inttypes.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <unistd.h> 37 38#include <ncurses.h> 39#if defined(__FreeBSD__) 40#include <libutil.h> 41#elif defined(__linux__) 42#include <pty.h> 43#else 44#include <util.h> 45#endif 46 47#include "teken.h" 48 49static tf_bell_t test_bell; 50static tf_cursor_t test_cursor; 51static tf_putchar_t test_putchar; 52static tf_fill_t test_fill; 53static tf_copy_t test_copy; 54static tf_param_t test_param; 55static tf_respond_t test_respond; 56 57static teken_funcs_t tf = { 58 .tf_bell = test_bell, 59 .tf_cursor = test_cursor, 60 .tf_putchar = test_putchar, 61 .tf_fill = test_fill, 62 .tf_copy = test_copy, 63 .tf_param = test_param, 64 .tf_respond = test_respond, 65}; 66 67struct pixel { 68 teken_char_t c; 69 teken_attr_t a; 70}; 71 72#define NCOLS 80 73#define NROWS 25 74struct pixel buffer[NCOLS][NROWS]; 75 76static int ptfd; 77 78static void 79printchar(const teken_pos_t *p) 80{ 81 int y, x, attr = 0; 82 struct pixel *px, pt; 83 84 assert(p->tp_row < NROWS); 85 assert(p->tp_col < NCOLS); 86 87 getyx(stdscr, y, x); 88 89 px = &buffer[p->tp_col][p->tp_row]; 90 91 if (px->c >= 0x80) { 92 /* Mark UTF-8 chars (we don't support it). */ 93 px = &pt; 94 px->c = '?'; 95 px->a.ta_format = TF_BOLD; 96 px->a.ta_fgcolor = TC_BROWN; 97 px->a.ta_bgcolor = TC_RED; 98 } 99 100 if (px->a.ta_format & TF_BOLD) 101 attr |= A_BOLD; 102 if (px->a.ta_format & TF_UNDERLINE) 103 attr |= A_UNDERLINE; 104 if (px->a.ta_format & TF_BLINK) 105 attr |= A_BLINK; 106 107 bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor + 1)); 108 mvaddch(p->tp_row, p->tp_col, px->c); 109 110 move(y, x); 111} 112 113static void 114test_bell(void *s __unused) 115{ 116 117 beep(); 118} 119 120static void 121test_cursor(void *s __unused, const teken_pos_t *p) 122{ 123 124 move(p->tp_row, p->tp_col); 125} 126 127static void 128test_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, 129 const teken_attr_t *a) 130{ 131 132 buffer[p->tp_col][p->tp_row].c = c; 133 buffer[p->tp_col][p->tp_row].a = *a; 134 printchar(p); 135} 136 137static void 138test_fill(void *s, const teken_rect_t *r, teken_char_t c, 139 const teken_attr_t *a) 140{ 141 teken_pos_t p; 142 143 /* Braindead implementation of fill() - just call putchar(). */ 144 for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) 145 for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) 146 test_putchar(s, &p, c, a); 147} 148 149static void 150test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) 151{ 152 int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ 153 teken_pos_t d; 154 155 /* 156 * Copying is a little tricky. We must make sure we do it in 157 * correct order, to make sure we don't overwrite our own data. 158 */ 159 160 nrow = r->tr_end.tp_row - r->tr_begin.tp_row; 161 ncol = r->tr_end.tp_col - r->tr_begin.tp_col; 162 163 if (p->tp_row < r->tr_begin.tp_row) { 164 /* Copy from top to bottom. */ 165 if (p->tp_col < r->tr_begin.tp_col) { 166 /* Copy from left to right. */ 167 for (y = 0; y < nrow; y++) { 168 d.tp_row = p->tp_row + y; 169 for (x = 0; x < ncol; x++) { 170 d.tp_col = p->tp_col + x; 171 buffer[d.tp_col][d.tp_row] = 172 buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 173 printchar(&d); 174 } 175 } 176 } else { 177 /* Copy from right to left. */ 178 for (y = 0; y < nrow; y++) { 179 d.tp_row = p->tp_row + y; 180 for (x = ncol - 1; x >= 0; x--) { 181 d.tp_col = p->tp_col + x; 182 buffer[d.tp_col][d.tp_row] = 183 buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 184 printchar(&d); 185 } 186 } 187 } 188 } else { 189 /* Copy from bottom to top. */ 190 if (p->tp_col < r->tr_begin.tp_col) { 191 /* Copy from left to right. */ 192 for (y = nrow - 1; y >= 0; y--) { 193 d.tp_row = p->tp_row + y; 194 for (x = 0; x < ncol; x++) { 195 d.tp_col = p->tp_col + x; 196 buffer[d.tp_col][d.tp_row] = 197 buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 198 printchar(&d); 199 } 200 } 201 } else { 202 /* Copy from right to left. */ 203 for (y = nrow - 1; y >= 0; y--) { 204 d.tp_row = p->tp_row + y; 205 for (x = ncol - 1; x >= 0; x--) { 206 d.tp_col = p->tp_col + x; 207 buffer[d.tp_col][d.tp_row] = 208 buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 209 printchar(&d); 210 } 211 } 212 } 213 } 214} 215 216static void 217test_param(void *s __unused, int cmd, int value) 218{ 219 220 switch (cmd) { 221 case TP_SHOWCURSOR: 222 curs_set(value); 223 break; 224 case TP_KEYPADAPP: 225 keypad(stdscr, value ? TRUE : FALSE); 226 break; 227 } 228} 229 230static void 231test_respond(void *s __unused, const void *buf, size_t len) 232{ 233 234 write(ptfd, buf, len); 235} 236 237static void 238redraw_border(void) 239{ 240 unsigned int i; 241 242 for (i = 0; i < NROWS; i++) 243 mvaddch(i, NCOLS, '|'); 244 for (i = 0; i < NCOLS; i++) 245 mvaddch(NROWS, i, '-'); 246 247 mvaddch(NROWS, NCOLS, '+'); 248} 249 250static void 251redraw_all(void) 252{ 253 teken_pos_t tp; 254 255 for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) 256 for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) 257 printchar(&tp); 258 259 redraw_border(); 260} 261 262int 263main(int argc __unused, char *argv[] __unused) 264{ 265 struct winsize ws; 266 teken_t t; 267 teken_pos_t tp; 268 fd_set rfds; 269 char b[256]; 270 ssize_t bl; 271 const int ccolors[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; 272 int i, j; 273 274 tp.tp_row = ws.ws_row = NROWS; 275 tp.tp_col = ws.ws_col = NCOLS; 276 277 switch (forkpty(&ptfd, NULL, NULL, &ws)) { 278 case -1: 279 perror("forkpty"); 280 exit(1); 281 case 0: 282 setenv("TERM", "cons25", 1); 283 setenv("LC_CTYPE", "UTF-8", 0); 284 execlp("zsh", "-zsh", NULL); 285 execlp("bash", "-bash", NULL); 286 execlp("sh", "-sh", NULL); 287 _exit(1); 288 } 289 290 teken_init(&t, &tf, NULL); 291 teken_set_winsize(&t, &tp); 292 293 initscr(); 294 raw(); 295 start_color(); 296 for (i = 0; i < 8; i++) 297 for (j = 0; j < 8; j++) 298 init_pair(i + 8 * j + 1, ccolors[i], ccolors[j]); 299 300 redraw_border(); 301 302 FD_ZERO(&rfds); 303 304 for (;;) { 305 FD_SET(STDIN_FILENO, &rfds); 306 FD_SET(ptfd, &rfds); 307 308 if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { 309 if (errno == EINTR) { 310 redraw_all(); 311 refresh(); 312 continue; 313 } 314 break; 315 } 316 317 if (FD_ISSET(STDIN_FILENO, &rfds)) { 318 bl = read(STDIN_FILENO, b, sizeof b); 319 if (bl <= 0) 320 break; 321 write(ptfd, b, bl); 322 } 323 324 if (FD_ISSET(ptfd, &rfds)) { 325 bl = read(ptfd, b, sizeof b); 326 if (bl <= 0) 327 break; 328 teken_input(&t, b, bl); 329 refresh(); 330 } 331 } 332 333 endwin(); 334 335 return (0); 336} 337