teken_demo.c revision 223574
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/teken/demo/teken_demo.c 223574 2011-06-26 18:25:10Z ed $ 27186681Sed */ 28186681Sed 29186681Sed#include <sys/ioctl.h> 30186681Sed 31186681Sed#include <assert.h> 32186681Sed#include <errno.h> 33186681Sed#include <inttypes.h> 34187562Sed#include <locale.h> 35186681Sed#include <stdio.h> 36186681Sed#include <stdlib.h> 37186681Sed#include <unistd.h> 38186681Sed 39186681Sed#include <ncurses.h> 40186681Sed#if defined(__FreeBSD__) 41186681Sed#include <libutil.h> 42186681Sed#elif defined(__linux__) 43186681Sed#include <pty.h> 44186681Sed#else 45186681Sed#include <util.h> 46186681Sed#endif 47186681Sed 48221698Sed#include <teken.h> 49186681Sed 50186681Sedstatic tf_bell_t test_bell; 51186681Sedstatic tf_cursor_t test_cursor; 52186681Sedstatic tf_putchar_t test_putchar; 53186681Sedstatic tf_fill_t test_fill; 54186681Sedstatic tf_copy_t test_copy; 55186681Sedstatic tf_param_t test_param; 56186681Sedstatic tf_respond_t test_respond; 57186681Sed 58186681Sedstatic teken_funcs_t tf = { 59186681Sed .tf_bell = test_bell, 60186681Sed .tf_cursor = test_cursor, 61186681Sed .tf_putchar = test_putchar, 62186681Sed .tf_fill = test_fill, 63186681Sed .tf_copy = test_copy, 64186681Sed .tf_param = test_param, 65186681Sed .tf_respond = test_respond, 66186681Sed}; 67186681Sed 68186681Sedstruct pixel { 69186681Sed teken_char_t c; 70186681Sed teken_attr_t a; 71186681Sed}; 72186681Sed 73186681Sed#define NCOLS 80 74187469Sed#define NROWS 24 75186681Sedstruct pixel buffer[NCOLS][NROWS]; 76186681Sed 77186681Sedstatic int ptfd; 78186681Sed 79186681Sedstatic void 80186681Sedprintchar(const teken_pos_t *p) 81186681Sed{ 82186681Sed int y, x, attr = 0; 83187562Sed struct pixel *px; 84187562Sed char str[5] = { 0 }; 85186681Sed 86186681Sed assert(p->tp_row < NROWS); 87186681Sed assert(p->tp_col < NCOLS); 88186681Sed 89186681Sed getyx(stdscr, y, x); 90186681Sed 91223574Sed px = &buffer[p->tp_col][p->tp_row]; 92186681Sed 93187562Sed /* Convert Unicode to UTF-8. */ 94187562Sed if (px->c < 0x80) { 95187562Sed str[0] = px->c; 96187562Sed } else if (px->c < 0x800) { 97187562Sed str[0] = 0xc0 | (px->c >> 6); 98187562Sed str[1] = 0x80 | (px->c & 0x3f); 99187562Sed } else if (px->c < 0x10000) { 100187562Sed str[0] = 0xe0 | (px->c >> 12); 101187562Sed str[1] = 0x80 | ((px->c >> 6) & 0x3f); 102187562Sed str[2] = 0x80 | (px->c & 0x3f); 103187562Sed } else { 104187562Sed str[0] = 0xf0 | (px->c >> 18); 105187562Sed str[1] = 0x80 | ((px->c >> 12) & 0x3f); 106187562Sed str[2] = 0x80 | ((px->c >> 6) & 0x3f); 107187562Sed str[3] = 0x80 | (px->c & 0x3f); 108186681Sed } 109186681Sed 110186681Sed if (px->a.ta_format & TF_BOLD) 111186681Sed attr |= A_BOLD; 112186681Sed if (px->a.ta_format & TF_UNDERLINE) 113186681Sed attr |= A_UNDERLINE; 114186681Sed if (px->a.ta_format & TF_BLINK) 115186681Sed attr |= A_BLINK; 116196786Sed if (px->a.ta_format & TF_REVERSE) 117196786Sed attr |= A_REVERSE; 118186681Sed 119197522Sed bkgdset(attr | COLOR_PAIR(teken_256to8(px->a.ta_fgcolor) + 120197522Sed 8 * teken_256to8(px->a.ta_bgcolor))); 121187562Sed mvaddstr(p->tp_row, p->tp_col, str); 122186681Sed 123186681Sed move(y, x); 124186681Sed} 125186681Sed 126186681Sedstatic void 127186681Sedtest_bell(void *s __unused) 128186681Sed{ 129186681Sed 130186681Sed beep(); 131186681Sed} 132186681Sed 133186681Sedstatic void 134186681Sedtest_cursor(void *s __unused, const teken_pos_t *p) 135186681Sed{ 136186681Sed 137186681Sed move(p->tp_row, p->tp_col); 138186681Sed} 139186681Sed 140186681Sedstatic void 141186681Sedtest_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, 142186681Sed const teken_attr_t *a) 143186681Sed{ 144186681Sed 145186681Sed buffer[p->tp_col][p->tp_row].c = c; 146186681Sed buffer[p->tp_col][p->tp_row].a = *a; 147186681Sed printchar(p); 148186681Sed} 149186681Sed 150186681Sedstatic void 151186681Sedtest_fill(void *s, const teken_rect_t *r, teken_char_t c, 152186681Sed const teken_attr_t *a) 153186681Sed{ 154186681Sed teken_pos_t p; 155186681Sed 156186681Sed /* Braindead implementation of fill() - just call putchar(). */ 157186681Sed for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) 158186681Sed for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) 159186681Sed test_putchar(s, &p, c, a); 160186681Sed} 161186681Sed 162186681Sedstatic void 163186681Sedtest_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) 164186681Sed{ 165186681Sed int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ 166186681Sed teken_pos_t d; 167186681Sed 168186681Sed /* 169186681Sed * Copying is a little tricky. We must make sure we do it in 170186681Sed * correct order, to make sure we don't overwrite our own data. 171186681Sed */ 172223574Sed 173186681Sed nrow = r->tr_end.tp_row - r->tr_begin.tp_row; 174186681Sed ncol = r->tr_end.tp_col - r->tr_begin.tp_col; 175223574Sed 176186681Sed if (p->tp_row < r->tr_begin.tp_row) { 177186681Sed /* Copy from top to bottom. */ 178186681Sed if (p->tp_col < r->tr_begin.tp_col) { 179186681Sed /* Copy from left to right. */ 180186681Sed for (y = 0; y < nrow; y++) { 181186681Sed d.tp_row = p->tp_row + y; 182186681Sed for (x = 0; x < ncol; x++) { 183186681Sed d.tp_col = p->tp_col + x; 184186681Sed buffer[d.tp_col][d.tp_row] = 185186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 186186681Sed printchar(&d); 187186681Sed } 188186681Sed } 189186681Sed } else { 190186681Sed /* Copy from right to left. */ 191186681Sed for (y = 0; y < nrow; y++) { 192186681Sed d.tp_row = p->tp_row + y; 193186681Sed for (x = ncol - 1; x >= 0; x--) { 194186681Sed d.tp_col = p->tp_col + x; 195186681Sed buffer[d.tp_col][d.tp_row] = 196186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 197186681Sed printchar(&d); 198186681Sed } 199186681Sed } 200186681Sed } 201186681Sed } else { 202186681Sed /* Copy from bottom to top. */ 203186681Sed if (p->tp_col < r->tr_begin.tp_col) { 204186681Sed /* Copy from left to right. */ 205186681Sed for (y = nrow - 1; y >= 0; y--) { 206186681Sed d.tp_row = p->tp_row + y; 207186681Sed for (x = 0; x < ncol; x++) { 208186681Sed d.tp_col = p->tp_col + x; 209186681Sed buffer[d.tp_col][d.tp_row] = 210186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 211186681Sed printchar(&d); 212186681Sed } 213186681Sed } 214186681Sed } else { 215186681Sed /* Copy from right to left. */ 216186681Sed for (y = nrow - 1; y >= 0; y--) { 217186681Sed d.tp_row = p->tp_row + y; 218186681Sed for (x = ncol - 1; x >= 0; x--) { 219186681Sed d.tp_col = p->tp_col + x; 220186681Sed buffer[d.tp_col][d.tp_row] = 221186681Sed buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 222186681Sed printchar(&d); 223186681Sed } 224186681Sed } 225186681Sed } 226186681Sed } 227186681Sed} 228186681Sed 229186681Sedstatic void 230193940Sedtest_param(void *s __unused, int cmd, unsigned int value) 231186681Sed{ 232186681Sed 233186681Sed switch (cmd) { 234186681Sed case TP_SHOWCURSOR: 235186681Sed curs_set(value); 236186681Sed break; 237186681Sed case TP_KEYPADAPP: 238186681Sed keypad(stdscr, value ? TRUE : FALSE); 239186681Sed break; 240186681Sed } 241186681Sed} 242186681Sed 243186681Sedstatic void 244186681Sedtest_respond(void *s __unused, const void *buf, size_t len) 245186681Sed{ 246186681Sed 247186681Sed write(ptfd, buf, len); 248186681Sed} 249186681Sed 250186681Sedstatic void 251186681Sedredraw_border(void) 252186681Sed{ 253186681Sed unsigned int i; 254186681Sed 255186681Sed for (i = 0; i < NROWS; i++) 256186681Sed mvaddch(i, NCOLS, '|'); 257186681Sed for (i = 0; i < NCOLS; i++) 258186681Sed mvaddch(NROWS, i, '-'); 259186681Sed 260186681Sed mvaddch(NROWS, NCOLS, '+'); 261186681Sed} 262186681Sed 263186681Sedstatic void 264186681Sedredraw_all(void) 265186681Sed{ 266186681Sed teken_pos_t tp; 267186681Sed 268186681Sed for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) 269186681Sed for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) 270186681Sed printchar(&tp); 271186681Sed 272186681Sed redraw_border(); 273186681Sed} 274186681Sed 275186681Sedint 276186681Sedmain(int argc __unused, char *argv[] __unused) 277186681Sed{ 278186681Sed struct winsize ws; 279186681Sed teken_t t; 280186681Sed teken_pos_t tp; 281186681Sed fd_set rfds; 282186681Sed char b[256]; 283186681Sed ssize_t bl; 284187562Sed const int ccolors[8] = { 285187562Sed COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, 286187562Sed COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE 287187562Sed }; 288186681Sed int i, j; 289186681Sed 290187562Sed setlocale(LC_CTYPE, "UTF-8"); 291187562Sed 292186681Sed tp.tp_row = ws.ws_row = NROWS; 293186681Sed tp.tp_col = ws.ws_col = NCOLS; 294186681Sed 295186681Sed switch (forkpty(&ptfd, NULL, NULL, &ws)) { 296186681Sed case -1: 297186681Sed perror("forkpty"); 298186681Sed exit(1); 299186681Sed case 0: 300187367Sed setenv("TERM", "xterm", 1); 301186681Sed setenv("LC_CTYPE", "UTF-8", 0); 302186681Sed execlp("zsh", "-zsh", NULL); 303186681Sed execlp("bash", "-bash", NULL); 304186681Sed execlp("sh", "-sh", NULL); 305186681Sed _exit(1); 306186681Sed } 307186681Sed 308186681Sed teken_init(&t, &tf, NULL); 309186681Sed teken_set_winsize(&t, &tp); 310186681Sed 311186681Sed initscr(); 312186681Sed raw(); 313186681Sed start_color(); 314186681Sed for (i = 0; i < 8; i++) 315186681Sed for (j = 0; j < 8; j++) 316187469Sed init_pair(i + 8 * j, ccolors[i], ccolors[j]); 317186681Sed 318186681Sed redraw_border(); 319186681Sed 320186681Sed FD_ZERO(&rfds); 321186681Sed 322186681Sed for (;;) { 323186681Sed FD_SET(STDIN_FILENO, &rfds); 324186681Sed FD_SET(ptfd, &rfds); 325186681Sed 326186681Sed if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { 327186681Sed if (errno == EINTR) { 328186681Sed redraw_all(); 329186681Sed refresh(); 330186681Sed continue; 331186681Sed } 332186681Sed break; 333186681Sed } 334186681Sed 335186681Sed if (FD_ISSET(STDIN_FILENO, &rfds)) { 336186681Sed bl = read(STDIN_FILENO, b, sizeof b); 337186681Sed if (bl <= 0) 338186681Sed break; 339186681Sed write(ptfd, b, bl); 340186681Sed } 341186681Sed 342186681Sed if (FD_ISSET(ptfd, &rfds)) { 343186681Sed bl = read(ptfd, b, sizeof b); 344186681Sed if (bl <= 0) 345186681Sed break; 346186681Sed teken_input(&t, b, bl); 347186681Sed refresh(); 348186681Sed } 349186681Sed } 350186681Sed 351186681Sed endwin(); 352186681Sed 353186681Sed return (0); 354186681Sed} 355