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