teken_demo.c revision 187469
1186681Sed/*- 2186681Sed * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> 3186681Sed * All rights reserved. 4186681Sed * 5186681Sed * Redistribution and use in source and binary forms, with or without 6186681Sed * modification, are permitted provided that the following conditions 7186681Sed * are met: 8186681Sed * 1. Redistributions of source code must retain the above copyright 9186681Sed * notice, this list of conditions and the following disclaimer. 10186681Sed * 2. Redistributions in binary form must reproduce the above copyright 11186681Sed * notice, this list of conditions and the following disclaimer in the 12186681Sed * documentation and/or other materials provided with the distribution. 13186681Sed * 14186681Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15186681Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16186681Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17186681Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18186681Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19186681Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20186681Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21186681Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22186681Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23186681Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24186681Sed * SUCH DAMAGE. 25186681Sed * 26186681Sed * $FreeBSD: head/sys/dev/syscons/teken/teken_demo.c 187469 2009-01-20 11:34:28Z ed $ 27186681Sed */ 28186681Sed 29186681Sed#include <sys/ioctl.h> 30186681Sed 31186681Sed#include <assert.h> 32186681Sed#include <errno.h> 33186681Sed#include <inttypes.h> 34186681Sed#include <stdio.h> 35186681Sed#include <stdlib.h> 36186681Sed#include <unistd.h> 37186681Sed 38186681Sed#include <ncurses.h> 39186681Sed#if defined(__FreeBSD__) 40186681Sed#include <libutil.h> 41186681Sed#elif defined(__linux__) 42186681Sed#include <pty.h> 43186681Sed#else 44186681Sed#include <util.h> 45186681Sed#endif 46186681Sed 47186681Sed#include "teken.h" 48186681Sed 49186681Sedstatic tf_bell_t test_bell; 50186681Sedstatic tf_cursor_t test_cursor; 51186681Sedstatic tf_putchar_t test_putchar; 52186681Sedstatic tf_fill_t test_fill; 53186681Sedstatic tf_copy_t test_copy; 54186681Sedstatic tf_param_t test_param; 55186681Sedstatic tf_respond_t test_respond; 56186681Sed 57186681Sedstatic teken_funcs_t tf = { 58186681Sed .tf_bell = test_bell, 59186681Sed .tf_cursor = test_cursor, 60186681Sed .tf_putchar = test_putchar, 61186681Sed .tf_fill = test_fill, 62186681Sed .tf_copy = test_copy, 63186681Sed .tf_param = test_param, 64186681Sed .tf_respond = test_respond, 65186681Sed}; 66186681Sed 67186681Sedstruct pixel { 68186681Sed teken_char_t c; 69186681Sed teken_attr_t a; 70186681Sed}; 71186681Sed 72186681Sed#define NCOLS 80 73187469Sed#ifdef TEKEN_XTERM 74187469Sed#define NROWS 24 75187469Sed#else /* !TEKEN_XTERM */ 76186729Sed#define NROWS 25 77187469Sed#endif /* TEKEN_XTERM */ 78186681Sedstruct pixel buffer[NCOLS][NROWS]; 79186681Sed 80186681Sedstatic int ptfd; 81186681Sed 82186681Sedstatic void 83186681Sedprintchar(const teken_pos_t *p) 84186681Sed{ 85186681Sed int y, x, attr = 0; 86186681Sed struct pixel *px, pt; 87186681Sed 88186681Sed assert(p->tp_row < NROWS); 89186681Sed assert(p->tp_col < NCOLS); 90186681Sed 91186681Sed getyx(stdscr, y, x); 92186681Sed 93186681Sed px = &buffer[p->tp_col][p->tp_row]; 94186681Sed 95186681Sed if (px->c >= 0x80) { 96186681Sed /* Mark UTF-8 chars (we don't support it). */ 97186681Sed px = &pt; 98186681Sed px->c = '?'; 99186681Sed px->a.ta_format = TF_BOLD; 100186681Sed px->a.ta_fgcolor = TC_BROWN; 101186681Sed px->a.ta_bgcolor = TC_RED; 102186681Sed } 103186681Sed 104186681Sed if (px->a.ta_format & TF_BOLD) 105186681Sed attr |= A_BOLD; 106186681Sed if (px->a.ta_format & TF_UNDERLINE) 107186681Sed attr |= A_UNDERLINE; 108186681Sed if (px->a.ta_format & TF_BLINK) 109186681Sed attr |= A_BLINK; 110186681Sed 111187469Sed bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor)); 112186681Sed mvaddch(p->tp_row, p->tp_col, px->c); 113186681Sed 114186681Sed move(y, x); 115186681Sed} 116186681Sed 117186681Sedstatic void 118186681Sedtest_bell(void *s __unused) 119186681Sed{ 120186681Sed 121186681Sed beep(); 122186681Sed} 123186681Sed 124186681Sedstatic void 125186681Sedtest_cursor(void *s __unused, const teken_pos_t *p) 126186681Sed{ 127186681Sed 128186681Sed move(p->tp_row, p->tp_col); 129186681Sed} 130186681Sed 131186681Sedstatic void 132186681Sedtest_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, 133186681Sed const teken_attr_t *a) 134186681Sed{ 135186681Sed 136186681Sed buffer[p->tp_col][p->tp_row].c = c; 137186681Sed buffer[p->tp_col][p->tp_row].a = *a; 138186681Sed printchar(p); 139186681Sed} 140186681Sed 141186681Sedstatic void 142186681Sedtest_fill(void *s, const teken_rect_t *r, teken_char_t c, 143186681Sed const teken_attr_t *a) 144186681Sed{ 145186681Sed teken_pos_t p; 146186681Sed 147186681Sed /* Braindead implementation of fill() - just call putchar(). */ 148186681Sed for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) 149186681Sed for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) 150186681Sed test_putchar(s, &p, c, a); 151186681Sed} 152186681Sed 153186681Sedstatic void 154186681Sedtest_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) 155186681Sed{ 156186681Sed int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ 157186681Sed teken_pos_t d; 158186681Sed 159186681Sed /* 160186681Sed * Copying is a little tricky. We must make sure we do it in 161186681Sed * correct order, to make sure we don't overwrite our own data. 162186681Sed */ 163186681Sed 164186681Sed nrow = r->tr_end.tp_row - r->tr_begin.tp_row; 165186681Sed ncol = r->tr_end.tp_col - r->tr_begin.tp_col; 166186681Sed 167186681Sed if (p->tp_row < r->tr_begin.tp_row) { 168186681Sed /* Copy from top to bottom. */ 169186681Sed if (p->tp_col < r->tr_begin.tp_col) { 170186681Sed /* Copy from left to right. */ 171186681Sed for (y = 0; y < nrow; y++) { 172186681Sed d.tp_row = p->tp_row + y; 173186681Sed for (x = 0; x < ncol; x++) { 174186681Sed d.tp_col = p->tp_col + x; 175186681Sed buffer[d.tp_col][d.tp_row] = 176186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 177186681Sed printchar(&d); 178186681Sed } 179186681Sed } 180186681Sed } else { 181186681Sed /* Copy from right to left. */ 182186681Sed for (y = 0; y < nrow; y++) { 183186681Sed d.tp_row = p->tp_row + y; 184186681Sed for (x = ncol - 1; x >= 0; x--) { 185186681Sed d.tp_col = p->tp_col + x; 186186681Sed buffer[d.tp_col][d.tp_row] = 187186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 188186681Sed printchar(&d); 189186681Sed } 190186681Sed } 191186681Sed } 192186681Sed } else { 193186681Sed /* Copy from bottom to top. */ 194186681Sed if (p->tp_col < r->tr_begin.tp_col) { 195186681Sed /* Copy from left to right. */ 196186681Sed for (y = nrow - 1; y >= 0; y--) { 197186681Sed d.tp_row = p->tp_row + y; 198186681Sed for (x = 0; x < ncol; x++) { 199186681Sed d.tp_col = p->tp_col + x; 200186681Sed buffer[d.tp_col][d.tp_row] = 201186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 202186681Sed printchar(&d); 203186681Sed } 204186681Sed } 205186681Sed } else { 206186681Sed /* Copy from right to left. */ 207186681Sed for (y = nrow - 1; y >= 0; y--) { 208186681Sed d.tp_row = p->tp_row + y; 209186681Sed for (x = ncol - 1; x >= 0; x--) { 210186681Sed d.tp_col = p->tp_col + x; 211186681Sed buffer[d.tp_col][d.tp_row] = 212186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 213186681Sed printchar(&d); 214186681Sed } 215186681Sed } 216186681Sed } 217186681Sed } 218186681Sed} 219186681Sed 220186681Sedstatic void 221186681Sedtest_param(void *s __unused, int cmd, int value) 222186681Sed{ 223186681Sed 224186681Sed switch (cmd) { 225186681Sed case TP_SHOWCURSOR: 226186681Sed curs_set(value); 227186681Sed break; 228186681Sed case TP_KEYPADAPP: 229186681Sed keypad(stdscr, value ? TRUE : FALSE); 230186681Sed break; 231186681Sed } 232186681Sed} 233186681Sed 234186681Sedstatic void 235186681Sedtest_respond(void *s __unused, const void *buf, size_t len) 236186681Sed{ 237186681Sed 238186681Sed write(ptfd, buf, len); 239186681Sed} 240186681Sed 241186681Sedstatic void 242186681Sedredraw_border(void) 243186681Sed{ 244186681Sed unsigned int i; 245186681Sed 246186681Sed for (i = 0; i < NROWS; i++) 247186681Sed mvaddch(i, NCOLS, '|'); 248186681Sed for (i = 0; i < NCOLS; i++) 249186681Sed mvaddch(NROWS, i, '-'); 250186681Sed 251186681Sed mvaddch(NROWS, NCOLS, '+'); 252186681Sed} 253186681Sed 254186681Sedstatic void 255186681Sedredraw_all(void) 256186681Sed{ 257186681Sed teken_pos_t tp; 258186681Sed 259186681Sed for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) 260186681Sed for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) 261186681Sed printchar(&tp); 262186681Sed 263186681Sed redraw_border(); 264186681Sed} 265186681Sed 266186681Sedint 267186681Sedmain(int argc __unused, char *argv[] __unused) 268186681Sed{ 269186681Sed struct winsize ws; 270186681Sed teken_t t; 271186681Sed teken_pos_t tp; 272186681Sed fd_set rfds; 273186681Sed char b[256]; 274186681Sed ssize_t bl; 275186681Sed const int ccolors[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; 276186681Sed int i, j; 277186681Sed 278186681Sed tp.tp_row = ws.ws_row = NROWS; 279186681Sed tp.tp_col = ws.ws_col = NCOLS; 280186681Sed 281186681Sed switch (forkpty(&ptfd, NULL, NULL, &ws)) { 282186681Sed case -1: 283186681Sed perror("forkpty"); 284186681Sed exit(1); 285186681Sed case 0: 286187367Sed#ifdef TEKEN_XTERM 287187367Sed setenv("TERM", "xterm", 1); 288187367Sed#else /* !TEKEN_XTERM */ 289186729Sed setenv("TERM", "cons25", 1); 290187367Sed#endif /* TEKEN_XTERM */ 291186731Sed#ifdef TEKEN_UTF8 292186681Sed setenv("LC_CTYPE", "UTF-8", 0); 293186731Sed#endif /* TEKEN_UTF8 */ 294186681Sed execlp("zsh", "-zsh", NULL); 295186681Sed execlp("bash", "-bash", NULL); 296186681Sed execlp("sh", "-sh", NULL); 297186681Sed _exit(1); 298186681Sed } 299186681Sed 300186681Sed teken_init(&t, &tf, NULL); 301186681Sed teken_set_winsize(&t, &tp); 302186681Sed 303186681Sed initscr(); 304186681Sed raw(); 305186681Sed start_color(); 306186681Sed for (i = 0; i < 8; i++) 307186681Sed for (j = 0; j < 8; j++) 308187469Sed init_pair(i + 8 * j, ccolors[i], ccolors[j]); 309186681Sed 310186681Sed redraw_border(); 311186681Sed 312186681Sed FD_ZERO(&rfds); 313186681Sed 314186681Sed for (;;) { 315186681Sed FD_SET(STDIN_FILENO, &rfds); 316186681Sed FD_SET(ptfd, &rfds); 317186681Sed 318186681Sed if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { 319186681Sed if (errno == EINTR) { 320186681Sed redraw_all(); 321186681Sed refresh(); 322186681Sed continue; 323186681Sed } 324186681Sed break; 325186681Sed } 326186681Sed 327186681Sed if (FD_ISSET(STDIN_FILENO, &rfds)) { 328186681Sed bl = read(STDIN_FILENO, b, sizeof b); 329186681Sed if (bl <= 0) 330186681Sed break; 331186681Sed write(ptfd, b, bl); 332186681Sed } 333186681Sed 334186681Sed if (FD_ISSET(ptfd, &rfds)) { 335186681Sed bl = read(ptfd, b, sizeof b); 336186681Sed if (bl <= 0) 337186681Sed break; 338186681Sed teken_input(&t, b, bl); 339186681Sed refresh(); 340186681Sed } 341186681Sed } 342186681Sed 343186681Sed endwin(); 344186681Sed 345186681Sed return (0); 346186681Sed} 347