teken_demo.c revision 186681
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 186681 2009-01-01 13:26:53Z 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 73186681Sed#define NROWS 24 74186681Sedstruct pixel buffer[NCOLS][NROWS]; 75186681Sed 76186681Sedstatic int ptfd; 77186681Sed 78186681Sedstatic void 79186681Sedprintchar(const teken_pos_t *p) 80186681Sed{ 81186681Sed int y, x, attr = 0; 82186681Sed struct pixel *px, pt; 83186681Sed 84186681Sed assert(p->tp_row < NROWS); 85186681Sed assert(p->tp_col < NCOLS); 86186681Sed 87186681Sed getyx(stdscr, y, x); 88186681Sed 89186681Sed px = &buffer[p->tp_col][p->tp_row]; 90186681Sed 91186681Sed if (px->c >= 0x80) { 92186681Sed /* Mark UTF-8 chars (we don't support it). */ 93186681Sed px = &pt; 94186681Sed px->c = '?'; 95186681Sed px->a.ta_format = TF_BOLD; 96186681Sed px->a.ta_fgcolor = TC_BROWN; 97186681Sed px->a.ta_bgcolor = TC_RED; 98186681Sed } 99186681Sed 100186681Sed if (px->a.ta_format & TF_BOLD) 101186681Sed attr |= A_BOLD; 102186681Sed if (px->a.ta_format & TF_UNDERLINE) 103186681Sed attr |= A_UNDERLINE; 104186681Sed if (px->a.ta_format & TF_BLINK) 105186681Sed attr |= A_BLINK; 106186681Sed 107186681Sed bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor + 1)); 108186681Sed mvaddch(p->tp_row, p->tp_col, px->c); 109186681Sed 110186681Sed move(y, x); 111186681Sed} 112186681Sed 113186681Sedstatic void 114186681Sedtest_bell(void *s __unused) 115186681Sed{ 116186681Sed 117186681Sed beep(); 118186681Sed} 119186681Sed 120186681Sedstatic void 121186681Sedtest_cursor(void *s __unused, const teken_pos_t *p) 122186681Sed{ 123186681Sed 124186681Sed move(p->tp_row, p->tp_col); 125186681Sed} 126186681Sed 127186681Sedstatic void 128186681Sedtest_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, 129186681Sed const teken_attr_t *a) 130186681Sed{ 131186681Sed 132186681Sed buffer[p->tp_col][p->tp_row].c = c; 133186681Sed buffer[p->tp_col][p->tp_row].a = *a; 134186681Sed printchar(p); 135186681Sed} 136186681Sed 137186681Sedstatic void 138186681Sedtest_fill(void *s, const teken_rect_t *r, teken_char_t c, 139186681Sed const teken_attr_t *a) 140186681Sed{ 141186681Sed teken_pos_t p; 142186681Sed 143186681Sed /* Braindead implementation of fill() - just call putchar(). */ 144186681Sed for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) 145186681Sed for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) 146186681Sed test_putchar(s, &p, c, a); 147186681Sed} 148186681Sed 149186681Sedstatic void 150186681Sedtest_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) 151186681Sed{ 152186681Sed int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ 153186681Sed teken_pos_t d; 154186681Sed 155186681Sed /* 156186681Sed * Copying is a little tricky. We must make sure we do it in 157186681Sed * correct order, to make sure we don't overwrite our own data. 158186681Sed */ 159186681Sed 160186681Sed nrow = r->tr_end.tp_row - r->tr_begin.tp_row; 161186681Sed ncol = r->tr_end.tp_col - r->tr_begin.tp_col; 162186681Sed 163186681Sed if (p->tp_row < r->tr_begin.tp_row) { 164186681Sed /* Copy from top to bottom. */ 165186681Sed if (p->tp_col < r->tr_begin.tp_col) { 166186681Sed /* Copy from left to right. */ 167186681Sed for (y = 0; y < nrow; y++) { 168186681Sed d.tp_row = p->tp_row + y; 169186681Sed for (x = 0; x < ncol; x++) { 170186681Sed d.tp_col = p->tp_col + x; 171186681Sed buffer[d.tp_col][d.tp_row] = 172186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 173186681Sed printchar(&d); 174186681Sed } 175186681Sed } 176186681Sed } else { 177186681Sed /* Copy from right to left. */ 178186681Sed for (y = 0; y < nrow; y++) { 179186681Sed d.tp_row = p->tp_row + y; 180186681Sed for (x = ncol - 1; x >= 0; x--) { 181186681Sed d.tp_col = p->tp_col + x; 182186681Sed buffer[d.tp_col][d.tp_row] = 183186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 184186681Sed printchar(&d); 185186681Sed } 186186681Sed } 187186681Sed } 188186681Sed } else { 189186681Sed /* Copy from bottom to top. */ 190186681Sed if (p->tp_col < r->tr_begin.tp_col) { 191186681Sed /* Copy from left to right. */ 192186681Sed for (y = nrow - 1; y >= 0; y--) { 193186681Sed d.tp_row = p->tp_row + y; 194186681Sed for (x = 0; x < ncol; x++) { 195186681Sed d.tp_col = p->tp_col + x; 196186681Sed buffer[d.tp_col][d.tp_row] = 197186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 198186681Sed printchar(&d); 199186681Sed } 200186681Sed } 201186681Sed } else { 202186681Sed /* Copy from right to left. */ 203186681Sed for (y = nrow - 1; y >= 0; y--) { 204186681Sed d.tp_row = p->tp_row + y; 205186681Sed for (x = ncol - 1; x >= 0; x--) { 206186681Sed d.tp_col = p->tp_col + x; 207186681Sed buffer[d.tp_col][d.tp_row] = 208186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 209186681Sed printchar(&d); 210186681Sed } 211186681Sed } 212186681Sed } 213186681Sed } 214186681Sed} 215186681Sed 216186681Sedstatic void 217186681Sedtest_param(void *s __unused, int cmd, int value) 218186681Sed{ 219186681Sed 220186681Sed switch (cmd) { 221186681Sed case TP_SHOWCURSOR: 222186681Sed curs_set(value); 223186681Sed break; 224186681Sed case TP_KEYPADAPP: 225186681Sed keypad(stdscr, value ? TRUE : FALSE); 226186681Sed break; 227186681Sed } 228186681Sed} 229186681Sed 230186681Sedstatic void 231186681Sedtest_respond(void *s __unused, const void *buf, size_t len) 232186681Sed{ 233186681Sed 234186681Sed write(ptfd, buf, len); 235186681Sed} 236186681Sed 237186681Sedstatic void 238186681Sedredraw_border(void) 239186681Sed{ 240186681Sed unsigned int i; 241186681Sed 242186681Sed for (i = 0; i < NROWS; i++) 243186681Sed mvaddch(i, NCOLS, '|'); 244186681Sed for (i = 0; i < NCOLS; i++) 245186681Sed mvaddch(NROWS, i, '-'); 246186681Sed 247186681Sed mvaddch(NROWS, NCOLS, '+'); 248186681Sed} 249186681Sed 250186681Sedstatic void 251186681Sedredraw_all(void) 252186681Sed{ 253186681Sed teken_pos_t tp; 254186681Sed 255186681Sed for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) 256186681Sed for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) 257186681Sed printchar(&tp); 258186681Sed 259186681Sed redraw_border(); 260186681Sed} 261186681Sed 262186681Sedint 263186681Sedmain(int argc __unused, char *argv[] __unused) 264186681Sed{ 265186681Sed struct winsize ws; 266186681Sed teken_t t; 267186681Sed teken_pos_t tp; 268186681Sed fd_set rfds; 269186681Sed char b[256]; 270186681Sed ssize_t bl; 271186681Sed const int ccolors[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; 272186681Sed int i, j; 273186681Sed 274186681Sed tp.tp_row = ws.ws_row = NROWS; 275186681Sed tp.tp_col = ws.ws_col = NCOLS; 276186681Sed 277186681Sed switch (forkpty(&ptfd, NULL, NULL, &ws)) { 278186681Sed case -1: 279186681Sed perror("forkpty"); 280186681Sed exit(1); 281186681Sed case 0: 282186681Sed setenv("TERM", "xterm-color", 1); 283186681Sed setenv("LC_CTYPE", "UTF-8", 0); 284186681Sed execlp("zsh", "-zsh", NULL); 285186681Sed execlp("bash", "-bash", NULL); 286186681Sed execlp("sh", "-sh", NULL); 287186681Sed _exit(1); 288186681Sed } 289186681Sed 290186681Sed teken_init(&t, &tf, NULL); 291186681Sed teken_set_winsize(&t, &tp); 292186681Sed 293186681Sed initscr(); 294186681Sed raw(); 295186681Sed start_color(); 296186681Sed for (i = 0; i < 8; i++) 297186681Sed for (j = 0; j < 8; j++) 298186681Sed init_pair(i + 8 * j + 1, ccolors[i], ccolors[j]); 299186681Sed 300186681Sed redraw_border(); 301186681Sed 302186681Sed FD_ZERO(&rfds); 303186681Sed 304186681Sed for (;;) { 305186681Sed FD_SET(STDIN_FILENO, &rfds); 306186681Sed FD_SET(ptfd, &rfds); 307186681Sed 308186681Sed if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { 309186681Sed if (errno == EINTR) { 310186681Sed redraw_all(); 311186681Sed refresh(); 312186681Sed continue; 313186681Sed } 314186681Sed break; 315186681Sed } 316186681Sed 317186681Sed if (FD_ISSET(STDIN_FILENO, &rfds)) { 318186681Sed bl = read(STDIN_FILENO, b, sizeof b); 319186681Sed if (bl <= 0) 320186681Sed break; 321186681Sed write(ptfd, b, bl); 322186681Sed } 323186681Sed 324186681Sed if (FD_ISSET(ptfd, &rfds)) { 325186681Sed bl = read(ptfd, b, sizeof b); 326186681Sed if (bl <= 0) 327186681Sed break; 328186681Sed teken_input(&t, b, bl); 329186681Sed refresh(); 330186681Sed } 331186681Sed } 332186681Sed 333186681Sed endwin(); 334186681Sed 335186681Sed return (0); 336186681Sed} 337