1/* 2 * A braille interface to unix tty terminals 3 * 4 * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu 5 * Bill Barry barryb@dots.physics.orst.edu 6 * 7 * Copyright (c) 1995 by Science Access Project, Oregon State University. 8 * 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program (see the file COPYING); if not, write to the 22 * Free Software Foundation, Inc., 23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 24 * 25 **************************************************************** 26 */ 27 28#include <stdio.h> 29#include <fcntl.h> 30#include <sys/stat.h> 31 32#include "config.h" 33#include "screen.h" 34#include "extern.h" 35#include "braille.h" 36 37#ifdef HAVE_BRAILLE 38 39 40extern int bd_init_powerbraille_40 __P((void)); 41extern int bd_init_powerbraille_80 __P((void)); 42extern int bd_init_navigator_40 __P((void)); 43 44extern struct layer *flayer; 45extern struct display *displays, *display; 46extern char *rc_name; 47 48 49 50 51/* global variables */ 52 53struct braille_display bd; 54 55struct bd_type { 56 char *name; 57 int (*init) __P((void)); 58}; 59 60static struct bd_type bd_typelist[] = 61{ 62 {"powerbraille_40", bd_init_powerbraille_40}, 63 {"powerbraille_80", bd_init_powerbraille_80}, 64 {"navigator_40" , bd_init_navigator_40} 65}; 66 67static void position_braille_cursor __P((void)); 68static int initialize_braille_display_type __P((char *)); 69static int open_braille_device __P(()); 70static int load_braille_table __P((char *)); 71static void bd_signal __P((void)); 72static void bd_bc_left __P((void)); 73static void bd_bc_right __P((void)); 74static void bd_bc_up __P((void)); 75static void bd_bc_down __P((void)); 76static void bd_upper_left __P((void)); 77static void bd_upper_right __P((void)); 78static void bd_lower_left __P((void)); 79static void bd_lower_right __P((void)); 80static int bd_do_search __P((int, int, int)); 81static void bd_normalize __P((int, int)); 82static void bd_readev_fn __P((struct event *, char *)); 83static void bd_writeev_fn __P((struct event *, char *)); 84static void bd_selectev_fn __P((struct event *, char *)); 85 86static unsigned char btable_local [] = 87{ 88 0xC8,0xC1,0xC3,0xC9,0xD9,0xD1,0xCB,0xDB, 89 0xD3,0xCA,0xDA,0xC5,0xC7,0xCD,0xDD,0xD5, 90 0xCF,0xDF,0xD7,0xCE,0xDE,0xE5,0xE7,0xFA, 91 0xED,0xFD,0xF5,0xEA,0xF3,0xFB,0xD8,0xF8, 92 0x00,0x2E,0x10,0x3C,0x2B,0x29,0x2F,0x04, 93 0x37,0x3E,0x21,0x2C,0x20,0x24,0x28,0x0C, 94 0x34,0x02,0x06,0x12,0x32,0x22,0x16,0x36, 95 0x26,0x14,0x31,0x30,0x23,0x3F,0x1C,0x39, 96 0x48,0x41,0x43,0x49,0x59,0x51,0x4B,0x5B, 97 0x53,0x4A,0x5A,0x45,0x47,0x4D,0x5D,0x55, 98 0x4F,0x5F,0x57,0x4E,0x5E,0x65,0x67,0x7A, 99 0x6D,0x7D,0x75,0x6A,0x73,0x7B,0x58,0x38, 100 0x08,0x01,0x03,0x09,0x19,0x11,0x0B,0x1B, 101 0x13,0x0A,0x1A,0x05,0x07,0x0D,0x1D,0x15, 102 0x0F,0x1F,0x17,0x0E,0x1E,0x25,0x27,0x3A, 103 0x2D,0x3D,0x35,0x2A,0x33,0x3B,0x18,0x78, 104 0x88,0x81,0x83,0x89,0x99,0x91,0x8B,0x9B, 105 0x93,0x8A,0x9A,0x85,0x87,0x8D,0x9D,0x95, 106 0x8F,0x9F,0x97,0x8E,0x9E,0xA5,0xA7,0xBA, 107 0xAD,0xBD,0xB5,0xAA,0xB3,0xBB,0x98,0xB8, 108 0x40,0x6E,0x50,0x7C,0x6B,0x69,0x6F,0x44, 109 0x77,0x7E,0x61,0x6C,0x60,0x64,0x68,0x4C, 110 0x74,0x42,0x46,0x52,0x72,0x62,0x56,0x76, 111 0x66,0x54,0x71,0x70,0x63,0x7F,0x5C,0x79, 112 0xC0,0xEE,0xD0,0xFC,0xEB,0xE9,0xEF,0xC4, 113 0xF7,0xFE,0xE1,0xEC,0xE0,0xE4,0xE8,0xCC, 114 0xF4,0xC2,0xC6,0xD2,0xF2,0xE2,0xD6,0xF6, 115 0xE6,0xD4,0xF1,0xF0,0xE3,0xFF,0xDC,0xF9, 116 0x80,0xAE,0x90,0xBC,0xAB,0xA9,0xAF,0x84, 117 0xB7,0xBE,0xA1,0xAC,0xA0,0xA4,0xA8,0x8C, 118 0xB4,0x82,0x86,0x92,0xB2,0xA2,0x96,0xB6, 119 0xA6,0x94,0xB1,0xB0,0xA3,0xBF,0x9C,0xB9 120}; 121 122void 123InitBraille() 124{ 125 bd.bd_start_braille=0; 126 bd.bd_port = 0; 127 bd.bd_braille_table = SaveStr("internal us-braille.tbl"); 128 bd.bd_type = 0; 129 bd.bd_baud = 9600; 130 bd.bd_bell = 1; 131 bd.bd_eightdot = 1; 132 bd.bd_info = 0; 133 bd.bd_link = 1; 134 bd.bd_ncells = 0; 135 bd.bd_width = 0; 136 bd.bd_ncrc = 1; 137 bd.bd_scroll = 1; 138 bd.bd_skip = 0; 139 bd.bd_using_braille = 0; 140 bd.bd_obuflen = 0; 141 bd.bd_fd = -1; 142 bcopy((char *)btable_local, bd.bd_btable, 256); 143} 144 145static int 146initialize_braille_display_type(s) 147char *s; 148{ 149 int i; 150 151 for (i = 0; i < sizeof(bd_typelist)/sizeof(*bd_typelist); i++) 152 if (!strcmp(s, bd_typelist[i].name)) 153 break; 154 if (i == sizeof(bd_typelist)/sizeof(*bd_typelist)) 155 { 156 Msg(0, "No entry for bd_type: %s ", s); 157 return -1; 158 } 159 bd.bd_type = bd_typelist[i].name; 160 if ((*bd_typelist[i].init)()) 161 return -1; 162 163 if (!bd.bd_width) 164 bd.bd_width = bd.bd_ncells; 165 166 return 0; 167} 168 169void 170StartBraille() 171{ 172 bd.bd_dpy = displays; 173 174 debug("StartBraille called\n"); 175 evdeq(&bd.bd_readev); 176 evdeq(&bd.bd_writeev); 177 evdeq(&bd.bd_selectev); 178 bd.bd_using_braille = 0; 179 180 if (!bd.bd_start_braille) 181 return; 182 183 if (bd.bd_type == 0 || bd.bd_port == 0) 184 return; 185 186 if (bd.bd_fd < 0 && open_braille_device()) 187 { 188 Msg(0, "bd_port turned off"); 189 free(bd.bd_port); 190 bd.bd_port = 0; 191 return; 192 } 193 194 /* check if braille display is connected and turned on */ 195 if (bd.bd_response_test()) 196 { 197 Msg(0, "Make sure that braille display is connected and turned on. "); 198 Msg(0, "start_braille turned off"); 199 bd.bd_start_braille = 0; 200 } 201 else 202 { 203 bd.bd_using_braille = 1; 204 bd.bd_readev.fd = bd.bd_writeev.fd = bd.bd_fd; 205 bd.bd_readev.type = EV_READ; 206 bd.bd_writeev.type = EV_WRITE; 207 bd.bd_selectev.type = EV_ALWAYS; 208 bd.bd_readev.data = bd.bd_writeev.data = bd.bd_selectev.data = (char *)&bd; 209 bd.bd_readev.handler = bd_readev_fn; 210 bd.bd_writeev.handler = bd_writeev_fn; 211 bd.bd_selectev.handler = bd_selectev_fn; 212 evenq(&bd.bd_readev); 213 bd.bd_writeev.condpos = &bd.bd_obuflen; 214 bd.bd_writeev.condneg = 0; 215 evenq(&bd.bd_writeev); 216 bd.bd_selectev.pri = -20; 217 evenq(&bd.bd_selectev); 218 } 219} 220 221 222static int 223load_braille_table(tablename) 224char *tablename; 225{ 226 int i, j, c, p; 227 FILE *fp; 228 char buffer[80], a[10]; 229 230 if ((fp = secfopen(tablename, "r")) == 0) 231 { 232 Msg(errno, "Braille table not found: %s ", tablename); 233 return -1; 234 } 235 bzero(bd.bd_btable, 256); 236 /* format: 237 * Dec Hex Braille Description 238 * 7 07 (12-45--8) BEL 239 */ 240 while (fgets(buffer, sizeof(buffer), fp)) 241 { 242 if (buffer[0] == '#') 243 continue; 244 sscanf(buffer,"%d %x %8s", &i, &j, a); 245 if (i < 0 || i > 255) 246 continue; 247 for (j=1, p=1, c=0; j<9; j++, p*=2) 248 if (a[j] == '0' + j) 249 c += p; 250 bd.bd_btable[i] = c; 251 } 252 fclose(fp); 253 return 0; 254} 255 256 257static int 258open_braille_device(s) 259char *s; 260{ 261 char str[256]; 262 263 sprintf(str, "%d cs8 -istrip ixon ixoff", bd.bd_baud); 264 bd.bd_fd = OpenTTY(bd.bd_port, str); 265 if (bd.bd_fd == -1) 266 { 267 Msg(errno, "open comm port failed: %s ", bd.bd_port); 268 return -1; 269 } 270 fcntl(bd.bd_fd, F_SETFL, FNBLOCK); 271 return 0; 272} 273 274 275static void 276position_braille_cursor() 277{ 278 int sx = bd.bd_sx; 279 int bx = BD_FORE->w_bd_x; 280 int eol = BD_FORE->w_width; 281 int w = bd.bd_width; 282 283 if (bd.bd_scroll) 284 bx = sx - w + bd.bd_ncrc; /* keep rc centered in window */ 285 else 286 bx = w * (int)(sx / w); /* increase bc in integral steps */ 287 288 if (bx > eol - w) 289 bx = eol - w; 290 if (bx < 0) 291 bx = 0; 292 BD_FORE->w_bd_x = bx; 293 BD_FORE->w_bd_y = bd.bd_sy; 294} 295 296 297void 298RefreshBraille() 299{ 300 int i, y, xs, xe; 301 int cursor_pos; 302 303 if (!bd.bd_using_braille) 304 return; 305 if (!BD_FORE) 306 return; 307 bcopy(bd.bd_line, bd.bd_oline, bd.bd_ncells); 308 bd.bd_refreshing = 1; 309 flayer = bd.bd_dpy->d_forecv->c_layer; 310 bd.bd_sx = flayer->l_x; 311 bd.bd_sy = flayer->l_y; 312 display = bd.bd_dpy; 313 if ((D_obufp != D_obuf) && bd.bd_link) 314 { 315 /* jump to real cursor */ 316 debug("calling position_braille_cursor\n"); 317 position_braille_cursor(); 318 } 319 bclear(bd.bd_line, bd.bd_ncells); 320 321 y = BD_FORE->w_bd_y; 322 xs = BD_FORE->w_bd_x; 323 324 if (bd.bd_info & 1) 325 { 326 sprintf(bd.bd_line, "%02d%02d", (BD_FORE->w_bd_x + 1) % 100, (BD_FORE->w_bd_y + 1) % 100); 327 bd.bd_line[4] = ' '; 328 } 329 if (bd.bd_info & 2) 330 { 331 sprintf(bd.bd_line + bd.bd_ncells - 4, "%02d%02d",(bd.bd_sx +1) % 100, (bd.bd_sy +1) % 100); 332 } 333 334 xe = xs + bd.bd_width - 1; 335 336 if (xs > flayer->l_width - 1) 337 xs = flayer->l_width - 1; 338 if (xe > flayer->l_width - 1) 339 xe = flayer->l_width - 1; 340 341 if (D_status) 342 { 343 sprintf(bd.bd_line, "**%-*.*s", bd.bd_ncells - 2, bd.bd_ncells - 2, D_status_lastmsg ? D_status_lastmsg : "unknown msg"); 344 xs = xe = -1; 345 } 346 else if (xs <= xe) 347 { 348 LayRedisplayLine(-1, xs, xe, 1); 349 LayRedisplayLine(y, xs, xe, 1); 350 } 351 352 debug1("Braille: got >%s<\n", bd.bd_line); 353 354 bd.bd_refreshing = 0; 355 356 if (y == bd.bd_sy && xs <= bd.bd_sx && bd.bd_sx <= xe) 357 cursor_pos = bd.bd_sx - xs + (bd.bd_info & 1 ? 4 : 0); 358 else 359 cursor_pos = bd.bd_ncells; 360 for (i = 0; i < bd.bd_ncells; i++) 361 if (bd.bd_line[i] != bd.bd_oline[i]) 362 break; 363 if (bd.bd_cursorpos != cursor_pos || i < bd.bd_ncells) 364 bd.write_line_braille(bd.bd_line, bd.bd_ncells, cursor_pos); 365 bd.bd_cursorpos = cursor_pos; 366} 367 368 369/********************************************************************** 370 * 371 */ 372 373/* 374 * So, why is there a Flush() down below? The reason is simple: the 375 * cursor warp (if bd_link is on) checks the obuf to see if something 376 * happened. If there would be no Flush, screen would warp the 377 * bd cursor if a bd movement command tries to ring the bell. 378 * (In other words: this is a gross hack!) 379 */ 380static void 381bd_signal() 382{ 383 if (!bd.bd_bell) 384 return; 385 display = bd.bd_dpy; 386 if (D_obufp != D_obuf) 387 AddCStr(D_BL); 388 else 389 { 390 AddCStr(D_BL); 391 Flush(); 392 } 393} 394 395static int 396bd_do_search(y, xs, xe) 397int y, xs, xe; 398{ 399 int oy = BD_FORE->w_bd_y; 400 401 if (!bd.bd_skip) /* no skip mode, found it */ 402 { 403 if (xs > xe) 404 return 0; 405 bd.bd_searchmin = xs; 406 bd.bd_searchmax = xe; 407 return 1; 408 } 409 flayer = bd.bd_dpy->d_forecv->c_layer; 410 bd.bd_searchmax = -1; 411 bd.bd_searchmin = flayer->l_width; 412 if (xs <= xe) 413 { 414 BD_FORE->w_bd_y = y; /* stupid hack */ 415 bd.bd_refreshing = bd.bd_searching = 1; 416 bd.bd_searchstart = xs; 417 bd.bd_searchend = xe; 418 LayRedisplayLine(-1, xs, xe, 1); 419 LayRedisplayLine(y, xs, xe, 1); 420 bd.bd_refreshing = bd.bd_searching = 0; 421 BD_FORE->w_bd_y = oy; 422 } 423 return bd.bd_searchmax >= 0; 424} 425 426static void 427bd_normalize(x, y) 428int x, y; 429{ 430 if (x > BD_FORE->w_width - bd.bd_width) 431 x = BD_FORE->w_width - bd.bd_width; 432 if (x < 0) 433 x = 0; 434 if (y < 0) 435 { 436 bd_signal(); 437 y = 0; 438 } 439 if (y >= BD_FORE->w_height) 440 { 441 bd_signal(); 442 y = BD_FORE->w_height - 1; 443 } 444 if (x != BD_FORE->w_bd_x || y != BD_FORE->w_bd_y) 445 bd.bd_moved = 1; 446 BD_FORE->w_bd_x = x; 447 BD_FORE->w_bd_y = y; 448} 449 450static void 451bd_bc_left() 452{ 453 int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; 454 int ex; 455 456 ex = bx - 1; 457 bx = 0; 458 for (; by >= 0; by--) 459 { 460 if (bd_do_search(by, 0, ex)) 461 { 462 if (!bd.bd_skip && by != BD_FORE->w_bd_y) 463 bd_signal(); 464 bx = bd.bd_searchmax + 1 - bd.bd_width; 465 break; 466 } 467 ex = BD_FORE->w_width - 1; 468 } 469 bd_normalize(bx, by); 470} 471 472static void 473bd_bc_right() 474{ 475 int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; 476 int sx; 477 478 sx = bx + bd.bd_width; 479 bx = BD_FORE->w_width - bd.bd_width; 480 for (; by < BD_FORE->w_height; by++) 481 { 482 if (bd_do_search(by, sx, BD_FORE->w_width - 1)) 483 { 484 if (!bd.bd_skip && by != BD_FORE->w_bd_y) 485 bd_signal(); 486 bx = bd.bd_searchmin; 487 break; 488 } 489 sx = 0; 490 } 491 bd_normalize(bx, by); 492} 493 494static void 495bd_bc_up() 496{ 497 int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; 498 499 for (by--; by >= 0; by--) 500 if (bd_do_search(by, bx, bx + bd.bd_width - 1)) 501 break; 502 bd_normalize(bx, by); 503} 504 505static void 506bd_bc_down() 507{ 508 int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; 509 510 for (by++; by < BD_FORE->w_height; by++) 511 if (bd_do_search(by, bx, bx + bd.bd_width - 1)) 512 break; 513 bd_normalize(bx, by); 514} 515 516 517static void 518bd_upper_left() 519{ 520 bd_normalize(0, 0); 521} 522 523 524static void 525bd_upper_right() 526{ 527 bd_normalize(BD_FORE->w_width - bd.bd_width, 0); 528} 529 530 531static void 532bd_lower_left() 533{ 534 bd_normalize(0, BD_FORE->w_height - 1); 535} 536 537 538static void 539bd_lower_right() 540{ 541 bd_normalize(BD_FORE->w_width - bd.bd_width, BD_FORE->w_height -1); 542} 543 544/********************************************************************** 545 * 546 */ 547 548 549static void 550bd_check(x, c) 551int x, c; 552{ 553 if (c == ' ') 554 return; 555 if (x < bd.bd_searchstart || x > bd.bd_searchend) 556 return; 557 if (x > bd.bd_searchmax) 558 bd.bd_searchmax = x; 559 if (x < bd.bd_searchmin) 560 bd.bd_searchmin = x; 561} 562 563 564 565/*ARGSUSED*/ 566void 567BGotoPos(la, x, y) 568struct layer *la; 569int x, y; 570{ 571} 572 573/*ARGSUSED*/ 574void 575BCDisplayLine(la, ml, y, xs, xe, isblank) 576struct layer *la; 577struct mline *ml; 578int y, xs, xe; 579int isblank; 580{ 581 int x; 582 int sx, ex; 583 char *l; 584 585 if (y != BD_FORE->w_bd_y) 586 return; 587 if (bd.bd_searching) 588 { 589 for (x = xs; x <= xe; x++) 590 bd_check(x, ml->image[x]); 591 return; 592 } 593 l = bd.bd_line; 594 sx = BD_FORE->w_bd_x; 595 ex = sx + bd.bd_width - 1; 596 if (bd.bd_info & 1) 597 l += 4; 598 for (x = xs; x <= xe; x++) 599 if (x >= sx && x <= ex) 600 l[x - sx] = ml->image[x]; 601} 602 603/*ARGSUSED*/ 604void 605BPutChar(la, c, x, y) 606struct layer *la; 607struct mchar *c; 608int x, y; 609{ 610 int sx, ex; 611 char *l; 612 613 if (y != BD_FORE->w_bd_y) 614 return; 615 if (bd.bd_searching) 616 { 617 bd_check(x, c->image); 618 return; 619 } 620 l = bd.bd_line; 621 sx = BD_FORE->w_bd_x; 622 ex = sx + bd.bd_width - 1; 623 if (bd.bd_info & 1) 624 l += 4; 625 if (x >= sx && x <= ex) 626 l[x - sx] = c->image; 627} 628 629/*ARGSUSED*/ 630void 631BPutStr(la, s, n, r, x, y) 632struct layer *la; 633char *s; 634int n; 635struct mchar *r; 636int x, y; 637{ 638 int sx, ex; 639 char *l; 640 641 if (y != BD_FORE->w_bd_y) 642 return; 643 if (bd.bd_searching) 644 { 645 for (; n > 0; n--, s++, x++) 646 bd_check(x, *s); 647 return; 648 } 649 l = bd.bd_line; 650 sx = BD_FORE->w_bd_x; 651 ex = sx + bd.bd_width - 1; 652 if (bd.bd_info & 1) 653 l += 4; 654 for (; n > 0; n--, s++, x++) 655 if (x >= sx && x <= ex) 656 l[x - sx] = *s; 657} 658 659 660 661/********************************************************************** 662 * 663 */ 664 665static char *infonames[] = {"none", "bc", "sc", "bc+sc"}; 666 667void 668DoBrailleAction(act, msgok) 669struct action *act; 670int msgok; 671{ 672 int nr, dosig; 673 int n, l, o; 674 char *s, **args; 675 struct stat st; 676 677 nr = act->nr; 678 args = act->args; 679 dosig = display && !*rc_name; 680 681 switch(nr) 682 { 683 case RC_BD_BELL: 684 if (ParseSwitch(act, &bd.bd_bell) || !msgok) 685 { 686 bd_signal(); 687 break; 688 } 689 Msg(0, bd.bd_bell ? "bd_bell is on." : "bd_bell is off."); 690 break; 691 692 case RC_BD_EIGHTDOT: 693 if (ParseSwitch(act, &bd.bd_eightdot) || !msgok) 694 break; 695 Msg(0, "switched to %d-dots system.", bd.bd_eightdot ? 8 : 6); 696 break; 697 698 case RC_BD_INFO: 699 n = bd.bd_info; 700 if (*args) 701 { 702 if (strlen(*args) == 4) 703 n = args[0][n] - '0'; 704 else if (ParseNum(act, &n)) 705 break; 706 } 707 if (n < 0 && n > 3) 708 { 709 Msg(0, "Out of range; 0 <= bd_info >= 3 "); 710 break; 711 } 712 /* bd_width at the beginning is unknown */ 713 if (bd.bd_width == 0) 714 break; 715 716 o = (bd.bd_info * 2 + 2) & 12; 717 l = (n * 2 + 2) & 12; 718 if (l >= bd.bd_ncells) 719 { 720 Msg(0, "bd_info is too large for braille display."); 721 break; 722 } 723 if (l >= bd.bd_width + o) 724 { 725 Msg(0, "bd_info is too large for bd_width."); 726 break; 727 } 728 bd.bd_width += o - l; 729 bd.bd_info = n; 730 731 if (msgok) 732 Msg(0, "bd_info is %s.", infonames[n]); 733 position_braille_cursor(); 734 break; 735 736 case RC_BD_LINK: 737 if (*args == 0 && bd.bd_moved) 738 bd.bd_link = 0; 739 if (ParseSwitch(act, &bd.bd_link)) 740 break; 741 if (bd.bd_link) 742 { 743 bd.bd_moved = 0; 744 if (dosig) 745 bd_signal(); 746 position_braille_cursor(); 747 } 748 if (msgok) 749 Msg(0, bd.bd_link ? "bd_link is on." : "bd_link is off."); 750 break; 751 752 case RC_BD_SKIP: 753 if (ParseSwitch(act, &bd.bd_skip)) 754 break; 755 if (bd.bd_skip && dosig) 756 bd_signal(); 757 if (msgok) 758 Msg(0, bd.bd_skip ? "bd_skip is on." : "bd_skip is off."); 759 break; 760 761 case RC_BD_SCROLL: 762 if (ParseSwitch(act, &bd.bd_scroll) || !msgok) 763 { 764 position_braille_cursor(); 765 break; 766 } 767 Msg(0, bd.bd_scroll ? "bd_scroll is on." : "bd_scroll is off."); 768 break; 769 770 case RC_BD_NCRC: 771 n = bd.bd_ncrc; 772 if (*args) 773 { 774 if (args[0][0] == '+') 775 n = (n + atoi(*args + 1)) % bd.bd_width + 1; 776 else if (args[0][0] == '-') 777 n = (n - atoi(*args + 1)) % bd.bd_width + 1; 778 else if (ParseNum(act, &n)) 779 break; 780 } 781 if (n < 1 || n > bd.bd_width) 782 { 783 Msg(0, "Out of range; 1 <= bd_ncrc >= %d", bd.bd_width); 784 break; 785 } 786 bd.bd_ncrc = n; 787 if (msgok) 788 Msg(0, "bd_ncrc status is: %d ", bd.bd_ncrc); 789 position_braille_cursor(); 790 break; 791 792 case RC_BD_BRAILLE_TABLE: 793 s = 0; 794 if (*args) 795 { 796 if (ParseSaveStr(act, &s)) 797 break; 798 if (load_braille_table(s)) 799 { 800 free(s); 801 break; 802 } 803 if (bd.bd_braille_table) 804 free(bd.bd_braille_table); 805 bd.bd_braille_table = s; 806 } 807 if (msgok) 808 Msg(0, "bd_braille_table is: %s ", bd.bd_braille_table); 809 break; 810 811 case RC_BD_PORT: 812 s = 0; 813 if (*args) 814 { 815 if (ParseSaveStr(act, &s)) 816 break; 817 818 if (stat(s, &st) || !S_ISCHR(st.st_mode) || access(s, R_OK|W_OK)) 819 { 820 Msg(0, "Cannot access braille device port %s", s); 821 free(s); 822 break; 823 } 824 if (bd.bd_fd >= 0) 825 close(bd.bd_fd); 826 bd.bd_fd = -1; 827 if (bd.bd_port) 828 free(bd.bd_port); 829 bd.bd_port = s; 830 } 831 if (msgok) 832 Msg(0, "bd_port is: %s ", bd.bd_port ? bd.bd_port : "not set"); 833 StartBraille(); 834 break; 835 836 case RC_BD_TYPE: 837 s = 0; 838 if (*args) 839 if (ParseSaveStr(act, &s) || initialize_braille_display_type(s)) 840 break; 841 if (msgok) 842 Msg(0, "bd_type is: %s ", bd.bd_type ? bd.bd_type : "not set"); 843 StartBraille(); 844 break; 845 846 case RC_BD_START_BRAILLE: 847 if (ParseSwitch(act, &bd.bd_start_braille)) 848 break; 849 if (msgok) 850 Msg(0, bd.bd_start_braille ? "bd_start_braille is on." : "bd_start_braille is off."); 851 StartBraille(); 852 break; 853 854 case RC_BD_WIDTH: 855 n = bd.bd_width; 856 if (*args) 857 { 858 if (ParseNum(act, &n)) 859 break; 860 } 861 if (n <= 0) 862 { 863 Msg(0, "Invalid value for bd_width: %d ", n); 864 break; 865 } 866 l = (bd.bd_info * 2 + 2) & 12; 867 if (n > bd.bd_ncells - l || n < l) 868 { 869 Msg(0, "bd_info is too large for bd_width."); 870 break; 871 } 872 bd.bd_width = n; 873 if (msgok) 874 Msg(0, "bd_width is: %d ", bd.bd_width); 875 break; 876 877 case RC_BD_BC_LEFT: 878 bd_bc_left(); 879 break; 880 881 case RC_BD_BC_RIGHT: 882 bd_bc_right(); 883 break; 884 885 case RC_BD_BC_UP: 886 bd_bc_up(); 887 break; 888 889 case RC_BD_BC_DOWN: 890 bd_bc_down(); 891 break; 892 893 case RC_BD_UPPER_LEFT: 894 bd_upper_left(); 895 break; 896 897 case RC_BD_UPPER_RIGHT: 898 bd_upper_right(); 899 break; 900 901 case RC_BD_LOWER_LEFT: 902 bd_lower_left(); 903 break; 904 905 case RC_BD_LOWER_RIGHT: 906 bd_lower_right(); 907 break; 908 909 default: 910 break; 911 } 912} 913 914static void 915bd_readev_fn(ev, data) 916struct event *ev; 917char *data; 918{ 919 bd.buttonpress(); 920} 921 922static void 923bd_writeev_fn(ev, data) 924struct event *ev; 925char *data; 926{ 927 int len; 928 929 if (bd.bd_obuflen == 0) 930 return; 931 if ((len = write(bd.bd_fd, bd.bd_obuf, bd.bd_obuflen)) < 0) 932 len = bd.bd_obuflen; /* dead braille display */ 933 if ((bd.bd_obuflen -= len)) 934 bcopy(bd.bd_obuf + len, bd.bd_obuf, bd.bd_obuflen); 935} 936 937static void 938bd_selectev_fn(ev, data) 939struct event *ev; 940char *data; 941{ 942 RefreshBraille(); 943} 944 945#endif /* HAVE_BRAILLE */ 946