OLD | NEW |
(Empty) | |
| 1 /*- |
| 2 * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> |
| 3 * All rights reserved. |
| 4 * |
| 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions |
| 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. |
| 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 24 * SUCH DAMAGE. |
| 25 * |
| 26 * $FreeBSD: head/sys/teken/demo/teken_demo.c 259667 2013-12-20 21:31:50Z ed $ |
| 27 */ |
| 28 |
| 29 #include <sys/ioctl.h> |
| 30 |
| 31 #include <assert.h> |
| 32 #include <errno.h> |
| 33 #include <inttypes.h> |
| 34 #include <locale.h> |
| 35 #include <stdio.h> |
| 36 #include <stdlib.h> |
| 37 #include <unistd.h> |
| 38 |
| 39 #include <ncurses.h> |
| 40 #if defined(__FreeBSD__) |
| 41 #include <libutil.h> |
| 42 #elif defined(__linux__) |
| 43 #include <pty.h> |
| 44 #else |
| 45 #include <util.h> |
| 46 #endif |
| 47 |
| 48 #include <teken.h> |
| 49 |
| 50 static tf_bell_t test_bell; |
| 51 static tf_cursor_t test_cursor; |
| 52 static tf_putchar_t test_putchar; |
| 53 static tf_fill_t test_fill; |
| 54 static tf_copy_t test_copy; |
| 55 static tf_param_t test_param; |
| 56 static tf_respond_t test_respond; |
| 57 |
| 58 static teken_funcs_t tf = { |
| 59 .tf_bell = test_bell, |
| 60 .tf_cursor = test_cursor, |
| 61 .tf_putchar = test_putchar, |
| 62 .tf_fill = test_fill, |
| 63 .tf_copy = test_copy, |
| 64 .tf_param = test_param, |
| 65 .tf_respond = test_respond, |
| 66 }; |
| 67 |
| 68 struct pixel { |
| 69 teken_char_t c; |
| 70 teken_attr_t a; |
| 71 }; |
| 72 |
| 73 #define NCOLS 80 |
| 74 #define NROWS 24 |
| 75 struct pixel buffer[NCOLS][NROWS]; |
| 76 |
| 77 static int ptfd; |
| 78 |
| 79 static void |
| 80 printchar(const teken_pos_t *p) |
| 81 { |
| 82 int y, x, attr = 0; |
| 83 struct pixel *px; |
| 84 char str[5] = { 0 }; |
| 85 |
| 86 assert(p->tp_row < NROWS); |
| 87 assert(p->tp_col < NCOLS); |
| 88 |
| 89 px = &buffer[p->tp_col][p->tp_row]; |
| 90 /* No need to print right hand side of CJK character manually. */ |
| 91 if (px->a.ta_format & TF_CJK_RIGHT) |
| 92 return; |
| 93 |
| 94 /* Convert Unicode to UTF-8. */ |
| 95 if (px->c < 0x80) { |
| 96 str[0] = px->c; |
| 97 } else if (px->c < 0x800) { |
| 98 str[0] = 0xc0 | (px->c >> 6); |
| 99 str[1] = 0x80 | (px->c & 0x3f); |
| 100 } else if (px->c < 0x10000) { |
| 101 str[0] = 0xe0 | (px->c >> 12); |
| 102 str[1] = 0x80 | ((px->c >> 6) & 0x3f); |
| 103 str[2] = 0x80 | (px->c & 0x3f); |
| 104 } else { |
| 105 str[0] = 0xf0 | (px->c >> 18); |
| 106 str[1] = 0x80 | ((px->c >> 12) & 0x3f); |
| 107 str[2] = 0x80 | ((px->c >> 6) & 0x3f); |
| 108 str[3] = 0x80 | (px->c & 0x3f); |
| 109 } |
| 110 |
| 111 if (px->a.ta_format & TF_BOLD) |
| 112 attr |= A_BOLD; |
| 113 if (px->a.ta_format & TF_UNDERLINE) |
| 114 attr |= A_UNDERLINE; |
| 115 if (px->a.ta_format & TF_BLINK) |
| 116 attr |= A_BLINK; |
| 117 if (px->a.ta_format & TF_REVERSE) |
| 118 attr |= A_REVERSE; |
| 119 |
| 120 bkgdset(attr | COLOR_PAIR(teken_256to8(px->a.ta_fgcolor) + |
| 121 8 * teken_256to8(px->a.ta_bgcolor))); |
| 122 getyx(stdscr, y, x); |
| 123 mvaddstr(p->tp_row, p->tp_col, str); |
| 124 move(y, x); |
| 125 } |
| 126 |
| 127 static void |
| 128 test_bell(void *s __unused) |
| 129 { |
| 130 |
| 131 beep(); |
| 132 } |
| 133 |
| 134 static void |
| 135 test_cursor(void *s __unused, const teken_pos_t *p) |
| 136 { |
| 137 |
| 138 move(p->tp_row, p->tp_col); |
| 139 } |
| 140 |
| 141 static void |
| 142 test_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, |
| 143 const teken_attr_t *a) |
| 144 { |
| 145 |
| 146 buffer[p->tp_col][p->tp_row].c = c; |
| 147 buffer[p->tp_col][p->tp_row].a = *a; |
| 148 printchar(p); |
| 149 } |
| 150 |
| 151 static void |
| 152 test_fill(void *s, const teken_rect_t *r, teken_char_t c, |
| 153 const teken_attr_t *a) |
| 154 { |
| 155 teken_pos_t p; |
| 156 |
| 157 /* Braindead implementation of fill() - just call putchar(). */ |
| 158 for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_ro
w++) |
| 159 for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col;
p.tp_col++) |
| 160 test_putchar(s, &p, c, a); |
| 161 } |
| 162 |
| 163 static void |
| 164 test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) |
| 165 { |
| 166 int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ |
| 167 teken_pos_t d; |
| 168 |
| 169 /* |
| 170 * Copying is a little tricky. We must make sure we do it in |
| 171 * correct order, to make sure we don't overwrite our own data. |
| 172 */ |
| 173 |
| 174 nrow = r->tr_end.tp_row - r->tr_begin.tp_row; |
| 175 ncol = r->tr_end.tp_col - r->tr_begin.tp_col; |
| 176 |
| 177 if (p->tp_row < r->tr_begin.tp_row) { |
| 178 /* Copy from top to bottom. */ |
| 179 if (p->tp_col < r->tr_begin.tp_col) { |
| 180 /* Copy from left to right. */ |
| 181 for (y = 0; y < nrow; y++) { |
| 182 d.tp_row = p->tp_row + y; |
| 183 for (x = 0; x < ncol; x++) { |
| 184 d.tp_col = p->tp_col + x; |
| 185 buffer[d.tp_col][d.tp_row] = |
| 186 buffer[r->tr_begin.tp_col + x][r->tr
_begin.tp_row + y]; |
| 187 printchar(&d); |
| 188 } |
| 189 } |
| 190 } else { |
| 191 /* Copy from right to left. */ |
| 192 for (y = 0; y < nrow; y++) { |
| 193 d.tp_row = p->tp_row + y; |
| 194 for (x = ncol - 1; x >= 0; x--) { |
| 195 d.tp_col = p->tp_col + x; |
| 196 buffer[d.tp_col][d.tp_row] = |
| 197 buffer[r->tr_begin.tp_col + x][r->tr
_begin.tp_row + y]; |
| 198 printchar(&d); |
| 199 } |
| 200 } |
| 201 } |
| 202 } else { |
| 203 /* Copy from bottom to top. */ |
| 204 if (p->tp_col < r->tr_begin.tp_col) { |
| 205 /* Copy from left to right. */ |
| 206 for (y = nrow - 1; y >= 0; y--) { |
| 207 d.tp_row = p->tp_row + y; |
| 208 for (x = 0; x < ncol; x++) { |
| 209 d.tp_col = p->tp_col + x; |
| 210 buffer[d.tp_col][d.tp_row] = |
| 211 buffer[r->tr_begin.tp_col + x][r->tr
_begin.tp_row + y]; |
| 212 printchar(&d); |
| 213 } |
| 214 } |
| 215 } else { |
| 216 /* Copy from right to left. */ |
| 217 for (y = nrow - 1; y >= 0; y--) { |
| 218 d.tp_row = p->tp_row + y; |
| 219 for (x = ncol - 1; x >= 0; x--) { |
| 220 d.tp_col = p->tp_col + x; |
| 221 buffer[d.tp_col][d.tp_row] = |
| 222 buffer[r->tr_begin.tp_col + x][r->tr
_begin.tp_row + y]; |
| 223 printchar(&d); |
| 224 } |
| 225 } |
| 226 } |
| 227 } |
| 228 } |
| 229 |
| 230 static void |
| 231 test_param(void *s __unused, int cmd, unsigned int value) |
| 232 { |
| 233 |
| 234 switch (cmd) { |
| 235 case TP_SHOWCURSOR: |
| 236 curs_set(value); |
| 237 break; |
| 238 case TP_KEYPADAPP: |
| 239 keypad(stdscr, value ? TRUE : FALSE); |
| 240 break; |
| 241 } |
| 242 } |
| 243 |
| 244 static void |
| 245 test_respond(void *s __unused, const void *buf, size_t len) |
| 246 { |
| 247 |
| 248 write(ptfd, buf, len); |
| 249 } |
| 250 |
| 251 static void |
| 252 redraw_border(void) |
| 253 { |
| 254 unsigned int i; |
| 255 |
| 256 for (i = 0; i < NROWS; i++) |
| 257 mvaddch(i, NCOLS, '|'); |
| 258 for (i = 0; i < NCOLS; i++) |
| 259 mvaddch(NROWS, i, '-'); |
| 260 |
| 261 mvaddch(NROWS, NCOLS, '+'); |
| 262 } |
| 263 |
| 264 static void |
| 265 redraw_all(void) |
| 266 { |
| 267 teken_pos_t tp; |
| 268 |
| 269 for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) |
| 270 for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) |
| 271 printchar(&tp); |
| 272 |
| 273 redraw_border(); |
| 274 } |
| 275 |
| 276 int |
| 277 main(int argc __unused, char *argv[] __unused) |
| 278 { |
| 279 struct winsize ws; |
| 280 teken_t t; |
| 281 teken_pos_t tp; |
| 282 fd_set rfds; |
| 283 char b[256]; |
| 284 ssize_t bl; |
| 285 const int ccolors[8] = { |
| 286 COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, |
| 287 COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE |
| 288 }; |
| 289 int i, j; |
| 290 |
| 291 setlocale(LC_CTYPE, "UTF-8"); |
| 292 |
| 293 tp.tp_row = ws.ws_row = NROWS; |
| 294 tp.tp_col = ws.ws_col = NCOLS; |
| 295 |
| 296 switch (forkpty(&ptfd, NULL, NULL, &ws)) { |
| 297 case -1: |
| 298 perror("forkpty"); |
| 299 exit(1); |
| 300 case 0: |
| 301 setenv("TERM", "xterm", 1); |
| 302 setenv("LC_CTYPE", "UTF-8", 0); |
| 303 execlp("zsh", "-zsh", NULL); |
| 304 execlp("bash", "-bash", NULL); |
| 305 execlp("sh", "-sh", NULL); |
| 306 _exit(1); |
| 307 } |
| 308 |
| 309 teken_init(&t, &tf, NULL); |
| 310 teken_set_winsize(&t, &tp); |
| 311 |
| 312 initscr(); |
| 313 raw(); |
| 314 start_color(); |
| 315 for (i = 0; i < 8; i++) |
| 316 for (j = 0; j < 8; j++) |
| 317 init_pair(i + 8 * j, ccolors[i], ccolors[j]); |
| 318 |
| 319 redraw_border(); |
| 320 |
| 321 FD_ZERO(&rfds); |
| 322 |
| 323 for (;;) { |
| 324 FD_SET(STDIN_FILENO, &rfds); |
| 325 FD_SET(ptfd, &rfds); |
| 326 |
| 327 if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { |
| 328 if (errno == EINTR) { |
| 329 redraw_all(); |
| 330 refresh(); |
| 331 continue; |
| 332 } |
| 333 break; |
| 334 } |
| 335 |
| 336 if (FD_ISSET(STDIN_FILENO, &rfds)) { |
| 337 bl = read(STDIN_FILENO, b, sizeof b); |
| 338 if (bl <= 0) |
| 339 break; |
| 340 write(ptfd, b, bl); |
| 341 } |
| 342 |
| 343 if (FD_ISSET(ptfd, &rfds)) { |
| 344 bl = read(ptfd, b, sizeof b); |
| 345 if (bl <= 0) |
| 346 break; |
| 347 teken_input(&t, b, bl); |
| 348 refresh(); |
| 349 } |
| 350 } |
| 351 |
| 352 endwin(); |
| 353 |
| 354 return (0); |
| 355 } |
OLD | NEW |