teken_demo.c revision 187367
10SN/A/*- 22362SN/A * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> 30SN/A * All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 72362SN/A * are met: 80SN/A * 1. Redistributions of source code must retain the above copyright 92362SN/A * notice, this list of conditions and the following disclaimer. 100SN/A * 2. Redistributions in binary form must reproduce the above copyright 110SN/A * notice, this list of conditions and the following disclaimer in the 120SN/A * documentation and/or other materials provided with the distribution. 130SN/A * 140SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 200SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212362SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222362SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232362SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240SN/A * SUCH DAMAGE. 250SN/A * 260SN/A * $FreeBSD: head/sys/dev/syscons/teken/teken_demo.c 187367 2009-01-17 16:37:13Z ed $ 270SN/A */ 280SN/A 290SN/A#include <sys/ioctl.h> 300SN/A 310SN/A#include <assert.h> 320SN/A#include <errno.h> 330SN/A#include <inttypes.h> 340SN/A#include <stdio.h> 350SN/A#include <stdlib.h> 360SN/A#include <unistd.h> 370SN/A 380SN/A#include <ncurses.h> 390SN/A#if defined(__FreeBSD__) 400SN/A#include <libutil.h> 410SN/A#elif defined(__linux__) 420SN/A#include <pty.h> 430SN/A#else 440SN/A#include <util.h> 450SN/A#endif 460SN/A 470SN/A#include "teken.h" 480SN/A 490SN/Astatic tf_bell_t test_bell; 500SN/Astatic tf_cursor_t test_cursor; 510SN/Astatic tf_putchar_t test_putchar; 520SN/Astatic tf_fill_t test_fill; 530SN/Astatic tf_copy_t test_copy; 540SN/Astatic tf_param_t test_param; 550SN/Astatic tf_respond_t test_respond; 560SN/A 570SN/Astatic teken_funcs_t tf = { 580SN/A .tf_bell = test_bell, 590SN/A .tf_cursor = test_cursor, 600SN/A .tf_putchar = test_putchar, 610SN/A .tf_fill = test_fill, 620SN/A .tf_copy = test_copy, 630SN/A .tf_param = test_param, 640SN/A .tf_respond = test_respond, 650SN/A}; 660SN/A 670SN/Astruct pixel { 680SN/A teken_char_t c; 690SN/A teken_attr_t a; 700SN/A}; 710SN/A 720SN/A#define NCOLS 80 730SN/A#define NROWS 25 740SN/Astruct pixel buffer[NCOLS][NROWS]; 750SN/A 760SN/Astatic int ptfd; 770SN/A 780SN/Astatic void 790SN/Aprintchar(const teken_pos_t *p) 800SN/A{ 810SN/A int y, x, attr = 0; 820SN/A struct pixel *px, pt; 830SN/A 840SN/A assert(p->tp_row < NROWS); 850SN/A assert(p->tp_col < NCOLS); 860SN/A 870SN/A getyx(stdscr, y, x); 880SN/A 890SN/A px = &buffer[p->tp_col][p->tp_row]; 900SN/A 910SN/A if (px->c >= 0x80) { 920SN/A /* Mark UTF-8 chars (we don't support it). */ 930SN/A px = &pt; 940SN/A px->c = '?'; 950SN/A px->a.ta_format = TF_BOLD; 960SN/A px->a.ta_fgcolor = TC_BROWN; 970SN/A px->a.ta_bgcolor = TC_RED; 980SN/A } 990SN/A 1000SN/A if (px->a.ta_format & TF_BOLD) 1010SN/A attr |= A_BOLD; 1020SN/A if (px->a.ta_format & TF_UNDERLINE) 1030SN/A attr |= A_UNDERLINE; 1040SN/A if (px->a.ta_format & TF_BLINK) 1050SN/A attr |= A_BLINK; 1060SN/A 1070SN/A bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor + 1)); 1080SN/A mvaddch(p->tp_row, p->tp_col, px->c); 1090SN/A 1100SN/A move(y, x); 1110SN/A} 1120SN/A 1130SN/Astatic void 1140SN/Atest_bell(void *s __unused) 1150SN/A{ 1160SN/A 1170SN/A beep(); 1180SN/A} 1190SN/A 1200SN/Astatic void 1210SN/Atest_cursor(void *s __unused, const teken_pos_t *p) 1220SN/A{ 1230SN/A 1240SN/A move(p->tp_row, p->tp_col); 1250SN/A} 1260SN/A 1270SN/Astatic void 1280SN/Atest_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, 1290SN/A const teken_attr_t *a) 1300SN/A{ 1310SN/A 1320SN/A buffer[p->tp_col][p->tp_row].c = c; 1330SN/A buffer[p->tp_col][p->tp_row].a = *a; 1340SN/A printchar(p); 1350SN/A} 1360SN/A 1370SN/Astatic void 1380SN/Atest_fill(void *s, const teken_rect_t *r, teken_char_t c, 1390SN/A const teken_attr_t *a) 1400SN/A{ 1410SN/A teken_pos_t p; 1420SN/A 1430SN/A /* Braindead implementation of fill() - just call putchar(). */ 1440SN/A for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) 1450SN/A for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) 1460SN/A test_putchar(s, &p, c, a); 1470SN/A} 1480SN/A 1490SN/Astatic void 1500SN/Atest_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) 1510SN/A{ 1520SN/A int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ 1530SN/A teken_pos_t d; 1540SN/A 1550SN/A /* 1560SN/A * Copying is a little tricky. We must make sure we do it in 1570SN/A * correct order, to make sure we don't overwrite our own data. 1580SN/A */ 1590SN/A 1600SN/A nrow = r->tr_end.tp_row - r->tr_begin.tp_row; 1610SN/A ncol = r->tr_end.tp_col - r->tr_begin.tp_col; 1620SN/A 1630SN/A if (p->tp_row < r->tr_begin.tp_row) { 1640SN/A /* Copy from top to bottom. */ 1650SN/A if (p->tp_col < r->tr_begin.tp_col) { 1660SN/A /* Copy from left to right. */ 1670SN/A for (y = 0; y < nrow; y++) { 1680SN/A d.tp_row = p->tp_row + y; 1690SN/A for (x = 0; x < ncol; x++) { 1700SN/A d.tp_col = p->tp_col + x; 1710SN/A buffer[d.tp_col][d.tp_row] = 1720SN/A buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 1730SN/A printchar(&d); 1740SN/A } 1750SN/A } 1760SN/A } else { 1770SN/A /* Copy from right to left. */ 1780SN/A for (y = 0; y < nrow; y++) { 1790SN/A d.tp_row = p->tp_row + y; 1800SN/A for (x = ncol - 1; x >= 0; x--) { 1810SN/A d.tp_col = p->tp_col + x; 1820SN/A buffer[d.tp_col][d.tp_row] = 1830SN/A buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 1840SN/A printchar(&d); 1850SN/A } 1860SN/A } 1870SN/A } 1880SN/A } else { 1890SN/A /* Copy from bottom to top. */ 1900SN/A if (p->tp_col < r->tr_begin.tp_col) { 1910SN/A /* Copy from left to right. */ 1920SN/A for (y = nrow - 1; y >= 0; y--) { 1930SN/A d.tp_row = p->tp_row + y; 1940SN/A for (x = 0; x < ncol; x++) { 1950SN/A d.tp_col = p->tp_col + x; 1960SN/A buffer[d.tp_col][d.tp_row] = 1970SN/A buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 1980SN/A printchar(&d); 1990SN/A } 2000SN/A } 2010SN/A } else { 2020SN/A /* Copy from right to left. */ 2030SN/A for (y = nrow - 1; y >= 0; y--) { 2040SN/A d.tp_row = p->tp_row + y; 2050SN/A for (x = ncol - 1; x >= 0; x--) { 2060SN/A d.tp_col = p->tp_col + x; 2070SN/A buffer[d.tp_col][d.tp_row] = 2080SN/A buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; 2090SN/A printchar(&d); 2100SN/A } 2110SN/A } 2120SN/A } 2130SN/A } 2140SN/A} 2150SN/A 2160SN/Astatic void 2170SN/Atest_param(void *s __unused, int cmd, int value) 2180SN/A{ 2190SN/A 2200SN/A switch (cmd) { 2210SN/A case TP_SHOWCURSOR: 2220SN/A curs_set(value); 2230SN/A break; 2240SN/A case TP_KEYPADAPP: 2250SN/A keypad(stdscr, value ? TRUE : FALSE); 2260SN/A break; 2270SN/A } 2280SN/A} 2290SN/A 2300SN/Astatic void 2310SN/Atest_respond(void *s __unused, const void *buf, size_t len) 2320SN/A{ 2330SN/A 2340SN/A write(ptfd, buf, len); 2350SN/A} 2360SN/A 2370SN/Astatic void 2380SN/Aredraw_border(void) 2390SN/A{ 2400SN/A unsigned int i; 2410SN/A 2420SN/A for (i = 0; i < NROWS; i++) 2430SN/A mvaddch(i, NCOLS, '|'); 2440SN/A for (i = 0; i < NCOLS; i++) 2450SN/A mvaddch(NROWS, i, '-'); 2460SN/A 2470SN/A mvaddch(NROWS, NCOLS, '+'); 2480SN/A} 2490SN/A 2500SN/Astatic void 2510SN/Aredraw_all(void) 2520SN/A{ 2530SN/A teken_pos_t tp; 2540SN/A 2550SN/A for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) 2560SN/A for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) 2570SN/A printchar(&tp); 2580SN/A 2590SN/A redraw_border(); 2600SN/A} 2610SN/A 2620SN/Aint 2630SN/Amain(int argc __unused, char *argv[] __unused) 2640SN/A{ 2650SN/A struct winsize ws; 2660SN/A teken_t t; 2670SN/A teken_pos_t tp; 2680SN/A fd_set rfds; 2690SN/A char b[256]; 2700SN/A ssize_t bl; 2710SN/A const int ccolors[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; 2720SN/A int i, j; 2730SN/A 2740SN/A tp.tp_row = ws.ws_row = NROWS; 2750SN/A tp.tp_col = ws.ws_col = NCOLS; 2760SN/A 2770SN/A switch (forkpty(&ptfd, NULL, NULL, &ws)) { 2780SN/A case -1: 2790SN/A perror("forkpty"); 2800SN/A exit(1); 2810SN/A case 0: 2820SN/A#ifdef TEKEN_XTERM 2830SN/A setenv("TERM", "xterm", 1); 2840SN/A#else /* !TEKEN_XTERM */ 2850SN/A setenv("TERM", "cons25", 1); 2860SN/A#endif /* TEKEN_XTERM */ 2870SN/A#ifdef TEKEN_UTF8 2880SN/A setenv("LC_CTYPE", "UTF-8", 0); 2890SN/A#endif /* TEKEN_UTF8 */ 2900SN/A execlp("zsh", "-zsh", NULL); 2910SN/A execlp("bash", "-bash", NULL); 2920SN/A execlp("sh", "-sh", NULL); 2930SN/A _exit(1); 2940SN/A } 2950SN/A 2960SN/A teken_init(&t, &tf, NULL); 2970SN/A teken_set_winsize(&t, &tp); 2980SN/A 2990SN/A initscr(); 3000SN/A raw(); 3010SN/A start_color(); 3020SN/A for (i = 0; i < 8; i++) 3030SN/A for (j = 0; j < 8; j++) 3040SN/A init_pair(i + 8 * j + 1, ccolors[i], ccolors[j]); 3050SN/A 3060SN/A redraw_border(); 307 308 FD_ZERO(&rfds); 309 310 for (;;) { 311 FD_SET(STDIN_FILENO, &rfds); 312 FD_SET(ptfd, &rfds); 313 314 if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { 315 if (errno == EINTR) { 316 redraw_all(); 317 refresh(); 318 continue; 319 } 320 break; 321 } 322 323 if (FD_ISSET(STDIN_FILENO, &rfds)) { 324 bl = read(STDIN_FILENO, b, sizeof b); 325 if (bl <= 0) 326 break; 327 write(ptfd, b, bl); 328 } 329 330 if (FD_ISSET(ptfd, &rfds)) { 331 bl = read(ptfd, b, sizeof b); 332 if (bl <= 0) 333 break; 334 teken_input(&t, b, bl); 335 refresh(); 336 } 337 } 338 339 endwin(); 340 341 return (0); 342} 343