1/* 2 * 3 * This is a test program for the PDCurses screen package for IBM PC type 4 * machines. 5 * 6 * This program was written by John Burnell (johnb@kea.am.dsir.govt.nz) 7 * wrs(5/28/93) -- modified to be consistent (perform identically) with either 8 * PDCurses or under Unix System V, R4 9 * 10 * $Id: testcurs.c,v 1.39 2008/08/03 17:58:09 tom Exp $ 11 */ 12 13#include <test.priv.h> 14 15#if defined(XCURSES) 16char *XCursesProgramName = "testcurs"; 17#endif 18 19static int initTest(WINDOW **); 20static void display_menu(int, int); 21static void inputTest(WINDOW *); 22static void introTest(WINDOW *); 23static void outputTest(WINDOW *); 24static void padTest(WINDOW *); 25static void scrollTest(WINDOW *); 26#if defined(PDCURSES) && !defined(XCURSES) 27static void resizeTest(WINDOW *); 28#endif 29 30struct commands { 31 NCURSES_CONST char *text; 32 void (*function) (WINDOW *); 33}; 34typedef struct commands COMMAND; 35 36static const COMMAND command[] = 37{ 38 {"General Test", introTest}, 39 {"Pad Test", padTest}, 40#if defined(PDCURSES) && !defined(XCURSES) 41 {"Resize Test", resizeTest}, 42#endif 43 {"Scroll Test", scrollTest}, 44 {"Input Test", inputTest}, 45 {"Output Test", outputTest} 46}; 47#define MAX_OPTIONS (int) SIZEOF(command) 48 49#if !HAVE_STRDUP 50#define strdup my_strdup 51static char * 52strdup(char *s) 53{ 54 char *p = typeMalloc(char, strlen(s) + 1); 55 if (p) 56 strcpy(p, s); 57 return (p); 58} 59#endif /* not HAVE_STRDUP */ 60 61static int width, height; 62 63int 64main( 65 int argc GCC_UNUSED, 66 char *argv[]GCC_UNUSED) 67{ 68 WINDOW *win; 69 int key; 70 int old_option = (-1); 71 int new_option = 0; 72 bool quit = FALSE; 73 int n; 74 75 setlocale(LC_ALL, ""); 76 77#ifdef PDCDEBUG 78 PDC_debug("testcurs started\n"); 79#endif 80 if (!initTest(&win)) 81 ExitProgram(EXIT_FAILURE); 82 83 erase(); 84 display_menu(old_option, new_option); 85 for (;;) { 86#ifdef A_COLOR 87 if (has_colors()) { 88 init_pair(1, COLOR_WHITE, COLOR_BLUE); 89 wbkgd(win, COLOR_PAIR(1)); 90 } else 91 wbkgd(win, A_REVERSE); 92#else 93 wbkgd(win, A_REVERSE); 94#endif 95 werase(win); 96 97 noecho(); 98 keypad(stdscr, TRUE); 99 raw(); 100 key = getch(); 101 if (key < KEY_MIN && key > 0 && isalpha(key)) { 102 if (islower(key)) 103 key = toupper(key); 104 for (n = 0; n < MAX_OPTIONS; ++n) { 105 if (key == command[n].text[0]) { 106 display_menu(old_option, new_option = n); 107 key = ' '; 108 break; 109 } 110 } 111 } 112 switch (key) { 113 case 10: 114 case 13: 115 case KEY_ENTER: 116 erase(); 117 refresh(); 118 (*command[new_option].function) (win); 119 erase(); 120 display_menu(old_option, new_option); 121 break; 122 case KEY_UP: 123 new_option = ((new_option == 0) 124 ? new_option 125 : new_option - 1); 126 display_menu(old_option, new_option); 127 break; 128 case KEY_DOWN: 129 new_option = ((new_option == (MAX_OPTIONS - 1)) 130 ? new_option 131 : new_option + 1); 132 display_menu(old_option, new_option); 133 break; 134 case 'Q': 135 case 'q': 136 quit = TRUE; 137 break; 138 default: 139 beep(); 140 break; 141 case ' ': 142 break; 143 } 144 if (quit == TRUE) 145 break; 146 } 147 148 delwin(win); 149 150 endwin(); 151#ifdef XCURSES 152 XCursesExit(); 153#endif 154 ExitProgram(EXIT_SUCCESS); 155} 156 157static void 158Continue(WINDOW *win) 159{ 160 int y1 = getmaxy(win); 161 int x1 = getmaxx(win); 162 int y0 = y1 < 10 ? y1 : 10; 163 int x0 = 1; 164 chtype save; 165 166 save = mvwinch(win, y0, x1 - 1); 167 168 mvwaddstr(win, y0, x0, " Press any key to continue"); 169 wclrtoeol(win); 170 getyx(win, y0, x0); 171 172 mvwaddch(win, y0, x1 - 1, save); 173 174 wmove(win, y0, x0); 175 raw(); 176 wgetch(win); 177} 178 179static int 180initTest(WINDOW **win) 181{ 182#ifdef PDCDEBUG 183 PDC_debug("initTest called\n"); 184#endif 185#ifdef TRACE 186 trace(TRACE_MAXIMUM); 187#endif 188 initscr(); 189#ifdef PDCDEBUG 190 PDC_debug("after initscr()\n"); 191#endif 192#ifdef A_COLOR 193 if (has_colors()) 194 start_color(); 195#endif 196 width = 60; 197 height = 13; /* Create a drawing window */ 198 *win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2); 199 if (*win == NULL) { 200 endwin(); 201 return 0; 202 } 203 return 1; 204} 205 206static void 207introTest(WINDOW *win) 208{ 209 wmove(win, height / 2 - 5, width / 2); 210 wvline(win, ACS_VLINE, 10); 211 wmove(win, height / 2, width / 2 - 10); 212 whline(win, ACS_HLINE, 20); 213 Continue(win); 214 215 beep(); 216 werase(win); 217 218 box(win, ACS_VLINE, ACS_HLINE); 219 wrefresh(win); 220 cbreak(); 221 mvwaddstr(win, 1, 1, 222 "You should have rectangle in the middle of the screen"); 223 mvwaddstr(win, 2, 1, "You should have heard a beep"); 224 Continue(win); 225 return; 226} 227 228static void 229scrollTest(WINDOW *win) 230{ 231 int i; 232 int half; 233 int OldY; 234 NCURSES_CONST char *Message = "The window will now scroll slowly"; 235 236 wclear(win); 237 OldY = getmaxy(win); 238 half = OldY / 2; 239 mvwprintw(win, OldY - 2, 1, Message); 240 wrefresh(win); 241 scrollok(win, TRUE); 242 for (i = 1; i <= OldY; i++) { 243 napms(600); 244 scroll(win); 245 wrefresh(win); 246 } 247 248 werase(win); 249 for (i = 1; i < OldY; i++) { 250 mvwprintw(win, i, 1, "Line %d", i); 251 } 252 mvwprintw(win, OldY - 2, 1, "The top of the window will scroll"); 253 wmove(win, 1, 1); 254 wsetscrreg(win, 0, half - 1); 255 box(win, ACS_VLINE, ACS_HLINE); 256 wrefresh(win); 257 for (i = 1; i <= half; i++) { 258 napms(600); 259 scroll(win); 260 box(win, ACS_VLINE, ACS_HLINE); 261 wrefresh(win); 262 } 263 264 werase(win); 265 for (i = 1; i < OldY; i++) { 266 mvwprintw(win, i, 1, "Line %d", i); 267 } 268 mvwprintw(win, 1, 1, "The bottom of the window will scroll"); 269 wmove(win, OldY - 2, 1); 270 wsetscrreg(win, half, --OldY); 271 box(win, ACS_VLINE, ACS_HLINE); 272 wrefresh(win); 273 for (i = half; i <= OldY; i++) { 274 napms(600); 275 wscrl(win, -1); 276 box(win, ACS_VLINE, ACS_HLINE); 277 wrefresh(win); 278 } 279 wsetscrreg(win, 0, OldY); 280} 281 282static void 283inputTest(WINDOW *win) 284{ 285 int answered; 286 int repeat; 287 int w, h, bx, by, sw, sh, i, c, num; 288 char buffer[80]; 289 WINDOW *subWin; 290 wclear(win); 291 292 getmaxyx(win, h, w); 293 getbegyx(win, by, bx); 294 sw = w / 3; 295 sh = h / 3; 296 if ((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL) 297 return; 298 299#ifdef A_COLOR 300 if (has_colors()) { 301 init_pair(2, COLOR_WHITE, COLOR_RED); 302 wbkgd(subWin, COLOR_PAIR(2) | A_BOLD); 303 } else 304 wbkgd(subWin, A_BOLD); 305#else 306 wbkgd(subWin, A_BOLD); 307#endif 308 box(subWin, ACS_VLINE, ACS_HLINE); 309 wrefresh(win); 310 311 nocbreak(); 312 mvwaddstr(win, 2, 1, "Press some keys for 5 seconds"); 313 mvwaddstr(win, 1, 1, "Pressing ^C should do nothing"); 314 wrefresh(win); 315 316 werase(subWin); 317 box(subWin, ACS_VLINE, ACS_HLINE); 318 for (i = 0; i < 5; i++) { 319 mvwprintw(subWin, 1, 1, "Time = %d", i); 320 wrefresh(subWin); 321 napms(1000); 322 flushinp(); 323 } 324 325 delwin(subWin); 326 werase(win); 327 flash(); 328 wrefresh(win); 329 napms(500); 330 331 mvwaddstr(win, 2, 1, "Press a key, followed by ENTER"); 332 wmove(win, 9, 10); 333 wrefresh(win); 334 echo(); 335 noraw(); 336 wgetch(win); 337 flushinp(); 338 339 wmove(win, 9, 10); 340 wdelch(win); 341 mvwaddstr(win, 4, 1, "The character should now have been deleted"); 342 Continue(win); 343 344 wclear(win); 345 mvwaddstr(win, 1, 1, "Press keys (or mouse buttons) to show their names"); 346 mvwaddstr(win, 2, 1, "Press spacebar to finish"); 347 wrefresh(win); 348 349 keypad(win, TRUE); 350 raw(); 351 noecho(); 352 353#if HAVE_TYPEAHEAD 354 typeahead(-1); 355#endif 356 357#if defined(PDCURSES) 358 mouse_set(ALL_MOUSE_EVENTS); 359#endif 360 361 for (;;) { 362 wmove(win, 3, 5); 363 c = wgetch(win); 364 wclrtobot(win); 365 if (c >= KEY_MIN) 366 wprintw(win, "Key Pressed: %s", keyname(c)); 367 else if (isprint(c)) 368 wprintw(win, "Key Pressed: %c", c); 369 else 370 wprintw(win, "Key Pressed: %s", unctrl(UChar(c))); 371#if defined(PDCURSES) 372 if (c == KEY_MOUSE) { 373 int button = 0; 374 request_mouse_pos(); 375 if (BUTTON_CHANGED(1)) 376 button = 1; 377 else if (BUTTON_CHANGED(2)) 378 button = 2; 379 else if (BUTTON_CHANGED(3)) 380 button = 3; 381 else 382 button = 0; 383 wmove(win, 4, 18); 384 wprintw(win, "Button %d: ", button); 385 if (MOUSE_MOVED) 386 wprintw(win, "moved: "); 387 else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_PRESSED) 388 wprintw(win, "pressed: "); 389 else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_DOUBLE_CLICKED) 390 wprintw(win, "double: "); 391 else 392 wprintw(win, "released: "); 393 wprintw(win, " Position: Y: %d X: %d", MOUSE_Y_POS, MOUSE_X_POS); 394 } 395#endif 396 wrefresh(win); 397 if (c == ' ') 398 break; 399 } 400#if 0 401 nodelay(win, TRUE); 402 wgetch(win); 403 nodelay(win, FALSE); 404#endif 405#if defined(PDCURSES) 406 mouse_set(0L); 407#endif 408 refresh(); 409 410 repeat = 0; 411 do { 412 static const char *fmt[] = 413 { 414 "%d %10s", 415 "%d %[a-zA-Z]s", 416 "%d %[][a-zA-Z]s", 417 "%d %[^0-9]" 418 }; 419 const char *format = fmt[repeat % SIZEOF(fmt)]; 420 421 wclear(win); 422 mvwaddstr(win, 3, 2, "The window should have moved"); 423 mvwaddstr(win, 4, 2, 424 "This text should have appeared without you pressing a key"); 425 mvwprintw(win, 6, 2, 426 "Scanning with format \"%s\"", format); 427 mvwin(win, 2 + 2 * (repeat % 4), 1 + 2 * (repeat % 4)); 428 erase(); 429 refresh(); 430 wrefresh(win); 431 echo(); 432 noraw(); 433 num = 0; 434 *buffer = 0; 435 answered = mvwscanw(win, 7, 6, strdup(format), &num, buffer); 436 mvwprintw(win, 8, 6, 437 "String: %s Number: %d (%d values read)", 438 buffer, num, answered); 439 Continue(win); 440 ++repeat; 441 } while (answered > 0); 442} 443 444static void 445outputTest(WINDOW *win) 446{ 447 WINDOW *win1; 448 char Buffer[80]; 449 chtype ch; 450 int by, bx; 451 452#if !HAVE_TIGETSTR 453#if HAVE_TGETENT 454 char tc_buffer[4096]; 455 char tc_parsed[4096]; 456 char *area_pointer = tc_parsed; 457 tgetent(tc_buffer, getenv("TERM")); 458#else 459#define tgetstr(a,b) 0 460#endif 461#endif /* !HAVE_TIGETSTR */ 462 463 nl(); 464 wclear(win); 465 mvwaddstr(win, 1, 1, 466 "You should now have a screen in the upper left corner, and this text should have wrapped"); 467 mvwin(win, 2, 1); 468 waddstr(win, "\nThis text should be down\n"); 469 waddstr(win, "and broken into two here ^"); 470 Continue(win); 471 472 wclear(win); 473 wattron(win, A_BOLD); 474 mvwaddstr(win, 1, 1, "A new window will appear with this text in it"); 475 mvwaddstr(win, 8, 1, "Press any key to continue"); 476 wrefresh(win); 477 wgetch(win); 478 479 getbegyx(win, by, bx); 480 481 if (LINES < 24 || COLS < 75) { 482 mvwaddstr(win, 5, 1, 483 "Some tests have been skipped as they require a"); 484 mvwaddstr(win, 6, 1, "display of at least 24 LINES by 75 COLUMNS"); 485 Continue(win); 486 } else { 487 win1 = newwin(10, 50, 14, 25); 488 if (win1 == NULL) { 489 endwin(); 490 return; 491 } 492#ifdef A_COLOR 493 if (has_colors()) { 494 init_pair(3, COLOR_BLUE, COLOR_WHITE); 495 wbkgd(win1, COLOR_PAIR(3)); 496 } else 497 wbkgd(win1, A_NORMAL); 498#else 499 wbkgd(win1, A_NORMAL); 500#endif 501 wclear(win1); 502 mvwaddstr(win1, 5, 1, 503 "This text should appear; using overlay option"); 504 copywin(win, win1, 0, 0, 0, 0, 9, 49, TRUE); 505 506#if defined(PDCURSES) && !defined(XCURSES) 507 box(win1, 0xb3, 0xc4); 508#else 509 box(win1, ACS_VLINE, ACS_HLINE); 510#endif 511 wmove(win1, 8, 26); 512 wrefresh(win1); 513 wgetch(win1); 514 515 wclear(win1); 516 wattron(win1, A_BLINK); 517 mvwaddstr(win1, 4, 1, 518 "This blinking text should appear in only the second window"); 519 wattroff(win1, A_BLINK); 520 mvwin(win1, by, bx); 521 overlay(win, win1); 522 mvwin(win1, 14, 25); 523 wmove(win1, 8, 26); 524 wrefresh(win1); 525 wgetch(win1); 526 delwin(win1); 527 } 528 529 clear(); 530 wclear(win); 531 wrefresh(win); 532 mvwaddstr(win, 6, 2, "This line shouldn't appear"); 533 mvwaddstr(win, 4, 2, "Only half of the next line is visible"); 534 mvwaddstr(win, 5, 2, "Only half of the next line is visible"); 535 wmove(win, 6, 1); 536 wclrtobot(win); 537 wmove(win, 5, 20); 538 wclrtoeol(win); 539 mvwaddstr(win, 8, 2, "This line also shouldn't appear"); 540 wmove(win, 8, 1); 541 wdeleteln(win); 542 Continue(win); 543 544 wmove(win, 5, 9); 545 ch = winch(win); 546 547 wclear(win); 548 wmove(win, 6, 2); 549 waddstr(win, "The next char should be l: "); 550 winsch(win, ch); 551 Continue(win); 552 553#if HAVE_WINSSTR 554 mvwinsstr(win, 6, 2, "A1B2C3D4E5"); 555 Continue(win); 556#endif 557 558 wmove(win, 5, 1); 559 winsertln(win); 560 mvwaddstr(win, 5, 2, "The lines below should have moved down"); 561 Continue(win); 562 563 wclear(win); 564 wmove(win, 2, 2); 565 wprintw(win, "This is a formatted string in a window: %d %s\n", 42, 566 "is it"); 567 mvwaddstr(win, 10, 1, "Enter a string: "); 568 wrefresh(win); 569 noraw(); 570 echo(); 571 *Buffer = 0; 572 wscanw(win, "%s", Buffer); 573 574 printw("This is a formatted string in stdscr: %d %s\n", 42, "is it"); 575 mvaddstr(10, 1, "Enter a string: "); 576 *Buffer = 0; 577 scanw("%s", Buffer); 578 579 if (TIGETSTR("cvvis", "vs") != 0) { 580 wclear(win); 581 curs_set(2); 582 mvwaddstr(win, 1, 1, "The cursor should appear as a block (visible)"); 583 Continue(win); 584 } 585 586 if (TIGETSTR("civis", "vi") != 0) { 587 wclear(win); 588 curs_set(0); 589 mvwaddstr(win, 1, 1, 590 "The cursor should have disappeared (invisible)"); 591 Continue(win); 592 } 593 594 if (TIGETSTR("cnorm", "ve") != 0) { 595 wclear(win); 596 curs_set(1); 597 mvwaddstr(win, 1, 1, "The cursor should be an underline (normal)"); 598 Continue(win); 599 } 600#ifdef A_COLOR 601 if (has_colors()) { 602 wclear(win); 603 mvwaddstr(win, 1, 1, "Colors should change after you press a key"); 604 Continue(win); 605 init_pair(1, COLOR_RED, COLOR_WHITE); 606 wrefresh(win); 607 } 608#endif 609 610 werase(win); 611 612#if HAVE_TERMNAME 613 mvwaddstr(win, 1, 1, "Information About Your Terminal"); 614 mvwaddstr(win, 3, 1, termname()); 615 mvwaddstr(win, 4, 1, longname()); 616 if (termattrs() & A_BLINK) 617 mvwaddstr(win, 5, 1, "This terminal supports blinking."); 618 else 619 mvwaddstr(win, 5, 1, "This terminal does NOT support blinking."); 620#endif 621 622 mvwaddnstr(win, 7, 5, "Have a nice day!ok", 16); 623 wrefresh(win); 624 625 mvwinnstr(win, 7, 5, Buffer, 18); 626 mvaddstr(LINES - 2, 10, Buffer); 627 refresh(); 628 Continue(win); 629} 630 631#if defined(PDCURSES) && !defined(XCURSES) 632static void 633resizeTest(WINDOW *dummy GCC_UNUSED) 634{ 635 WINDOW *win1; 636 637 savetty(); 638 639 clear(); 640 refresh(); 641# if defined(OS2) 642 resize_term(50, 120); 643# else 644 resize_term(50, 80); 645# endif 646 647 win1 = newwin(10, 50, 14, 25); 648 if (win1 == NULL) { 649 endwin(); 650 return; 651 } 652#ifdef A_COLOR 653 if (has_colors()) { 654 init_pair(3, COLOR_BLUE, COLOR_WHITE); 655 wattrset(win1, COLOR_PAIR(3)); 656 } 657#endif 658 wclear(win1); 659 660 mvwaddstr(win1, 1, 1, "The screen may now have 50 lines"); 661 Continue(win1); 662 663 wclear(win1); 664 resetty(); 665 666 mvwaddstr(win1, 1, 1, "The screen should now be reset"); 667 Continue(win1); 668 669 delwin(win1); 670 671 clear(); 672 refresh(); 673 674} 675#endif 676 677static void 678padTest(WINDOW *dummy GCC_UNUSED) 679{ 680 WINDOW *pad, *spad; 681 682 if ((pad = newpad(50, 100)) != 0) { 683 wattron(pad, A_REVERSE); 684 mvwaddstr(pad, 5, 2, "This is a new pad"); 685 wattrset(pad, A_NORMAL); 686 mvwaddstr(pad, 8, 0, 687 "The end of this line should be truncated here:except now"); 688 mvwaddstr(pad, 11, 1, "This line should not appear.It will now"); 689 wmove(pad, 10, 1); 690 wclrtoeol(pad); 691 mvwaddstr(pad, 10, 1, " Press any key to continue"); 692 prefresh(pad, 0, 0, 0, 0, 10, 45); 693 keypad(pad, TRUE); 694 raw(); 695 wgetch(pad); 696 697 spad = subpad(pad, 12, 25, 6, 52); 698 mvwaddstr(spad, 2, 2, "This is a new subpad"); 699 box(spad, 0, 0); 700 prefresh(pad, 0, 0, 0, 0, 15, 75); 701 keypad(pad, TRUE); 702 raw(); 703 wgetch(pad); 704 705 mvwaddstr(pad, 35, 2, "This is displayed at line 35 in the pad"); 706 mvwaddstr(pad, 40, 1, " Press any key to continue"); 707 prefresh(pad, 30, 0, 0, 0, 10, 45); 708 keypad(pad, TRUE); 709 raw(); 710 wgetch(pad); 711 712 delwin(pad); 713 } 714} 715 716static void 717display_menu(int old_option, int new_option) 718{ 719 int i; 720 721 assert((new_option >= 0) && (new_option < MAX_OPTIONS)); 722 723 attrset(A_NORMAL); 724 mvaddstr(3, 20, "PDCurses Test Program"); 725 726 for (i = 0; i < (int) MAX_OPTIONS; i++) 727 mvaddstr(5 + i, 25, command[i].text); 728 729 if ((old_option >= 0) && (old_option < MAX_OPTIONS)) 730 mvaddstr(5 + old_option, 25, command[old_option].text); 731 732 attrset(A_REVERSE); 733 mvaddstr(5 + new_option, 25, command[new_option].text); 734 attrset(A_NORMAL); 735 mvaddstr(13, 3, 736 "Use Up and Down Arrows to select - Enter to run - Q to quit"); 737 refresh(); 738} 739