00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00057
00058 #include <cxxtls/cursorwindow.h>
00059 #include <cxxtls/sequence_map.h>
00060 #include <string>
00061 #include <stdlib.h>
00062 #include <unistd.h>
00063 #include <signal.h>
00064 #include <algorithm>
00065 #include <cxxtls/file.h>
00066 #include <cxxtls/user.h>
00067 #include <cxxtls/machine.h>
00068 #include <iostream>
00069 #include <fstream>
00070 #include <portable_io.h>
00071
00072 #include <cxxtls/cursesinterface.h>
00073
00074
00075 extern "C"
00076 {
00077 #ifndef _XOPEN_SOURCE_EXTENDED
00078 #define _XOPEN_SOURCE_EXTENDED
00079 #endif
00080
00081 #define NOMACROS
00082 #include <curses.h>
00083
00084 #undef clear
00085 int clear();
00086
00087 }
00088
00089 #include <term.h>
00090 #include <termios.h>
00091
00092 namespace cxxtls
00093 {
00094
00095
00096 namespace CursesInterface
00097 {
00098 bool screen_resize_occurred=0;
00099
00100
00101 #ifdef _MSC_VER
00102 mouse_info read_mouse_info() { return mouse_location(0,0,0); }
00103 #endif
00104
00105 long line_chars[lcCOUNT];
00106
00107 char* _map_kf1 ;
00108 char* _map_kf2 ;
00109 char* _map_kf3 ;
00110 char* _map_kf4 ;
00111 char* _map_kf5 ;
00112 char* _map_kf6 ;
00113 char* _map_kf7 ;
00114 char* _map_kf8 ;
00115 char* _map_kf9 ;
00116 char* _map_kf10 ;
00117 char* _map_kf11 ;
00118 char* _map_kf12 ;
00119 char* _map_khom ;
00120 char* _map_kend ;
00121 char* _map_kic ;
00122 char* _map_kdc ;
00123 char* _map_kpr ;
00124 char* _map_knx ;
00125 char* _map_kup ;
00126 char* _map_kdn ;
00127 char* _map_klf ;
00128 char* _map_krt ;
00129 char* _map_kbtab;
00130
00131 void map_init_key_strings()
00132 {
00133 _map_kf1 = key_f1;
00134 _map_kf2 = key_f2;
00135 _map_kf3 = key_f3;
00136 _map_kf4 = key_f4;
00137 _map_kf5 = key_f5;
00138 _map_kf6 = key_f6;
00139 _map_kf7 = key_f7;
00140 _map_kf8 = key_f8;
00141 _map_kf9 = key_f9;
00142 _map_kf10 = key_f10;
00143 _map_kf11 = key_f11;
00144 _map_kf12 = key_f12;
00145 _map_khom = key_home;
00146 _map_kend = key_end;
00147 _map_kic = key_ic;
00148 _map_kdc = key_dc;
00149 _map_kpr = key_ppage;
00150 _map_knx = key_npage;
00151 _map_kup = key_up;
00152 _map_kdn = key_down;
00153 _map_klf = key_left;
00154 _map_krt = key_right;
00155 _map_kbtab= key_btab;
00156
00157
00158 }
00159
00160 typedef Sequence_Map<char,int> SEQMAP;
00161 typedef SEQMAP::search SEARCH;
00162 typedef SEQMAP::sequence SEQUENCE;
00163
00164 SEQMAP key_sequences;
00165
00166 void insert_key_sequence(char const *s, int code)
00167 {
00168 if(s == 0)
00169 return;
00170
00171 SEQUENCE seq(key_sequences, code);
00172
00173 while(*s)
00174 {
00175 seq += *s++;
00176 }
00177
00178 seq.complete();
00179
00180 }
00181
00182 void create_key_sequences_map();
00183
00184
00185 sigset_t winch_blocker;
00186
00187 void make_xterm_terminfo_file(FileName const &dir);
00188
00189
00190 #ifdef __linux
00191 static bool quit_occurred;
00192 static bool susp_occurred;
00193 static bool int_occurred;
00194
00195 extern "C"
00196 {
00197 static void quit_handler(int)
00198 {
00199 quit_occurred=1;
00200 signal(SIGQUIT, quit_handler);
00201 }
00202 }
00203
00204 extern "C"
00205 {
00206 static void susp_handler(int)
00207 {
00208 susp_occurred=1;
00209 signal(SIGTSTP, susp_handler);
00210 }
00211 }
00212
00213
00214 extern "C"
00215 {
00216 static void int_handler(int)
00217 {
00218 int_occurred=1;
00219 signal(SIGINT, int_handler);
00220 }
00221 }
00222
00223
00224
00225
00226 #endif
00227
00228
00229 void openCursesTerminal()
00230 {
00231 #ifdef __linux
00232 quit_occurred = false;
00233 susp_occurred = false;
00234 int_occurred = false;
00235 #endif
00236
00237 if(getenv("WAIT_FOR_DEBUGGER"))
00238 {
00239 printf("waiting for debugger to attach and single step this program\n");
00240
00241 int stop=1;
00242
00243 while(stop)
00244 {
00245 sleep(1);
00246 }
00247
00248 }
00249
00250 static bool first_time=true;
00251 if(first_time)
00252 {
00253
00254 first_time =false;
00255
00256
00257 char const *termname = getenv("TERM");
00258
00259 if( termname == 0
00260 || ( termname[0] != 'x'
00261 && termname != std::string("cygwin")
00262 )
00263 )
00264 {
00265 std::cerr << "Error, right now I only support TERM=xterm" << std::endl;
00266 exit(1);
00267 }
00268
00269 UserInfo me = UserInfo::get();
00270
00271 if(me.name_ == "")
00272 {
00273 std::cerr << "Error, couldn't get user id info -- system error" << std::endl;
00274 exit(1);
00275 }
00276
00277 FileName tooldir = me.home_dir_ + "/.tools_home";
00278
00279 if( !tooldir.is_dir() )
00280 {
00281
00282
00283 if(tooldir.mkdir())
00284 {
00285 std::cerr << "Error, couldn't create " << tooldir << std::endl;
00286 exit(1);
00287 }
00288
00289 }
00290
00291 MachineInfo host = MachineInfo::get();
00292
00293 if(host.hostname_ == "")
00294 {
00295 std::cerr << "Error, couldn't get hostname" << std::endl;
00296 exit(1);
00297 }
00298
00299 FileName hostdir = tooldir + "/" + host.hostname_;
00300
00301 if(!hostdir.is_dir())
00302 {
00303
00304
00305 if(hostdir.mkdir())
00306 {
00307 std::cerr << "Error, couldn't create " << hostdir << std::endl;
00308 exit(1);
00309 }
00310
00311 }
00312
00313 make_xterm_terminfo_file(hostdir);
00314
00315 FileName terminfodir = hostdir;
00316 terminfodir += "/terminfo";
00317
00318 if(!terminfodir.is_dir())
00319 {
00320
00321
00322 if(terminfodir.mkdir())
00323 {
00324 std::cerr << "Error, couldn't create " << terminfodir << std::endl;
00325 exit(1);
00326 }
00327
00328 }
00329
00330 FileName xterm_info_file = terminfodir;
00331 xterm_info_file += "/x/xterm";
00332
00333 std::string command("TERMINFO=");
00334
00335 command += terminfodir;
00336 command += " ";
00337 command += "/usr/bin/tic ";
00338 command += hostdir + "/xterm.info";
00339
00340 if(!xterm_info_file.exists())
00341 {
00342 int err = system(command.c_str());
00343
00344 (void)err;
00345 }
00346
00347 if(!xterm_info_file.exists())
00348 {
00349
00350
00351
00352
00353
00354
00355
00356 int uid = getuid();
00357
00358 if(uid == 0)
00359 {
00360 command="mkdir -p " + terminfodir + "/x" + "\n";
00361
00362 int rc;
00363
00364 rc = system(command.c_str());
00365
00366 command="ln -s /usr/share/terminfo/x/xterm " + xterm_info_file + "\n";
00367
00368 rc = system(command.c_str());
00369
00370 rc=rc;
00371
00372 }
00373
00374 if(!xterm_info_file.exists())
00375 {
00376 std::cerr << "Error, command '" << command << "', did not create" << std::endl
00377 << "file " << xterm_info_file << std::endl;
00378
00379 exit(1);
00380 }
00381 }
00382
00383 static char * envstring=0;
00384
00385 std::string tmp1("TERMINFO=");
00386 tmp1 += terminfodir;
00387
00388 char const *tmp2 = tmp1.c_str();
00389
00390 int l = strlen(tmp2);
00391
00392 envstring = new char[l+1];
00393
00394 strcpy(envstring, tmp2);
00395
00396 putenv(envstring);
00397
00398 }
00399
00400
00401
00402 initscr();
00403
00404 raw();
00405 noecho();
00406 meta(stdscr, TRUE);
00407
00408 halfdelay(10);
00409
00410 intrflush(stdscr,FALSE);
00411 keypad(stdscr,TRUE);
00412 typeahead(0);
00413
00414
00415 #ifdef __linux
00416
00417
00418 static struct termios override_termios;
00419
00420 tcgetattr(0, &override_termios);
00421
00422 cfmakeraw(&override_termios);
00423
00424 override_termios.c_cc[VQUIT]=0;
00425 override_termios.c_cc[VSUSP]=0;
00426
00427 override_termios.c_cc[VMIN]=1;
00428 override_termios.c_cc[VTIME]=10;
00429
00430 tcsetattr(0, TCSANOW, &override_termios);
00431
00432 #else
00433
00434 termios io_info;
00435
00436
00437 tcgetattr(0, &io_info);
00438
00439 io_info.c_cc[VMIN]=1;
00440 io_info.c_cc[VTIME]=10;
00441 tcsetattr(0, TCSANOW, &io_info);
00442
00443
00444 #endif
00445
00446
00447
00448
00449 sigemptyset(&winch_blocker);
00450
00451 sigaddset(&winch_blocker, SIGWINCH);
00452
00453 sigprocmask(SIG_BLOCK, &winch_blocker, 0);
00454
00455
00456
00457 siginterrupt(SIGWINCH, true);
00458 siginterrupt(SIGALRM, true);
00459
00460 #ifdef __linux
00461 siginterrupt(SIGQUIT, true);
00462 siginterrupt(SIGTSTP, true);
00463 siginterrupt(SIGINT, true);
00464 #endif
00465
00466 map_init_key_strings();
00467 create_key_sequences_map();
00468
00469 using namespace CursesInterface;
00470
00471 line_chars[UL_CORNER] = ACS_ULCORNER;
00472 line_chars[LL_CORNER] = ACS_LLCORNER;
00473 line_chars[UR_CORNER] = ACS_URCORNER;
00474 line_chars[LR_CORNER] = ACS_LRCORNER;
00475 line_chars[HL_MIDDLE] = ACS_HLINE;
00476 line_chars[VL_MIDDLE] = ACS_VLINE;
00477 line_chars[PL_BOX ] = ACS_PLUS;
00478 line_chars[TE_LEFT ] = ACS_LTEE;
00479 line_chars[TE_RIGHT ] = ACS_RTEE;
00480 line_chars[TE_BOTTOM] = ACS_BTEE;
00481 line_chars[TE_TOP ] = ACS_TTEE;
00482
00483 }
00484
00485 void closeCursesTerminal()
00486 {
00487 attrset(0);
00488 clear();
00489 refresh();
00490 endwin();
00491 #ifdef __linux
00492 resetterm();
00493 #endif
00494
00495 if(screen_resize_occurred)
00496 {
00497
00498
00499 for(int i = 0; i < 100; ++i)
00500 {
00501 std::cout << "\n";
00502 }
00503
00504 }
00505
00506 }
00507
00508 #undef key_up
00509 #undef key_down
00510 #undef key_left
00511 #undef key_right
00512 #undef key_sup
00513 #undef key_sdown
00514 #undef key_sleft
00515 #undef key_sright
00516 #undef key_prior
00517 #undef key_next
00518 #undef key_ic
00519 #undef key_dc
00520 #undef key_home
00521 #undef key_end
00522 #undef key_btab
00523 #undef key_f1
00524 #undef key_f2
00525 #undef key_f3
00526 #undef key_f4
00527 #undef key_f5
00528 #undef key_f6
00529 #undef key_f7
00530 #undef key_f8
00531 #undef key_f9
00532 #undef key_f10
00533 #undef key_f11
00534 #undef key_f12
00535 #undef erase
00536
00537 int mapCursesKey(int curses_key)
00538 {
00539 switch(curses_key)
00540 {
00541 case KEY_UP: return CursorWindow::key_up;
00542 case KEY_DOWN: return CursorWindow::key_down;
00543 case KEY_LEFT: return CursorWindow::key_left;
00544 case KEY_RIGHT: return CursorWindow::key_right;
00545 case KEY_SLEFT: return CursorWindow::key_sleft;
00546 case KEY_SRIGHT:return CursorWindow::key_sright;
00547 case KEY_PPAGE: return CursorWindow::key_prior;
00548 case KEY_NPAGE: return CursorWindow::key_next;
00549 case KEY_IC: return CursorWindow::key_ic;
00550 case KEY_DC: return CursorWindow::key_dc;
00551 case KEY_HOME: return CursorWindow::key_home;
00552 case KEY_SHOME: return CursorWindow::key_home;
00553 case KEY_END: return CursorWindow::key_end;
00554 case KEY_BTAB: return CursorWindow::key_btab;
00555
00556
00557 #ifdef __linux
00558 case 0x7f: return CursorWindow::key_bs;
00559 case KEY_BACKSPACE: return CursorWindow::key_bs;
00560 #endif
00561
00562 case KEY_F(1): return CursorWindow::key_f1;
00563 case KEY_F(2): return CursorWindow::key_f2;
00564 case KEY_F(3): return CursorWindow::key_f3;
00565 case KEY_F(4): return CursorWindow::key_f4;
00566 case KEY_F(5): return CursorWindow::key_f5;
00567 case KEY_F(6): return CursorWindow::key_f6;
00568 case KEY_F(7): return CursorWindow::key_f7;
00569 case KEY_F(8): return CursorWindow::key_f8;
00570 case KEY_F(9): return CursorWindow::key_f9;
00571 case KEY_F(10): return CursorWindow::key_f10;
00572 case KEY_F(11): return CursorWindow::key_f11;
00573 case KEY_F(12): return CursorWindow::key_f12;
00574 }
00575
00576 return curses_key;
00577 }
00578
00579
00580
00581 void getCursesCursor(int *row, int *col)
00582 {
00583 getyx(stdscr, *row, *col);
00584 }
00585
00586 void getCursesScreenSize(int *row, int *col)
00587 {
00588 getmaxyx(stdscr, *row, *col);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 void setCursesAttributes( int a )
00602 {
00603
00604
00605 int att=0;
00606
00607 switch(a)
00608 {
00609 case CursorWindow::reversed:
00610 att = A_REVERSE;
00611 break;
00612
00613 case CursorWindow::underlined:
00614 att = A_UNDERLINE;
00615 break;
00616
00617 case CursorWindow::blinking:
00618 att = A_BLINK;
00619 break;
00620
00621 case CursorWindow::bold:
00622 att = A_BOLD;
00623 break;
00624
00625 case CursorWindow::reverse_ul:
00626 att = A_REVERSE | A_UNDERLINE;
00627 break;
00628
00629 case CursorWindow::reverse_bold:
00630 att = A_REVERSE | A_BOLD;
00631 break;
00632
00633 case CursorWindow::rev_ul_bold:
00634 att = A_REVERSE | A_UNDERLINE | A_BOLD;
00635 break;
00636
00637 case CursorWindow::bold_ul:
00638 att = A_UNDERLINE | A_BOLD;
00639 break;
00640
00641
00642
00643 default:
00644 break;
00645 }
00646
00647 (void)attrset(att);
00648
00649 }
00650
00651
00652 void paintCharString(char const *r, int count, int a, int row, int col)
00653 {
00654 setCursesAttributes(a);
00655
00656 while(count--)
00657 {
00658 int c = *r++;
00659
00660 if(c < ' ' || (c & 0xff) > 0x7f)
00661 {
00662 c = '`';
00663 }
00664
00665 mvaddch(row, col++, c);
00666 }
00667 }
00668
00669 void paintCharString(long c, int count, int a, int row, int col)
00670 {
00671 if(c < ' ' || (c & 0xff) > 0x7f)
00672 {
00673 c = '`';
00674 }
00675
00676 setCursesAttributes(a);
00677
00678 while(count--)
00679 {
00680 mvaddch(row, col++, c);
00681 }
00682 }
00683
00684
00685
00686 void refreshCursesWindow()
00687 {
00688 refresh();
00689 }
00690
00691 void beepCursesTerminal()
00692 {
00693 beep();
00694 }
00695
00696
00697 void moveCursesCursor(int row, int col)
00698 {
00699 move(row,col);
00700 }
00701
00702
00703 void make_xterm_terminfo_file(FileName const &dir)
00709 {
00710 FileName filename = dir;
00711 filename += "/xterm.info";
00712
00713 if(filename.exists())
00714 return;
00715
00716 std::fstream f(filename.c_str(), std::ios::out);
00717
00718 if(f.bad())
00719 {
00720 std::cerr << "Error creating file " << filename << std::endl;
00721 exit(1);
00722 }
00723
00724 #ifdef LINUX
00725 char const *terminfo =
00726 "# Reconstructed via infocmp from file: /usr/share/terminfo/x/xterm \n"
00727 "xterm|xterm terminal emulator (X Window System), \n"
00728 " am, bce, km, mc5i, mir, msgr, xenl, \n"
00729 " colors#8, cols#80, it#8, lines#24, pairs#64, \n"
00730 " acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, \n"
00731 " bel=^G, blink=\\E[5m, bold=\\E[1m, cbt=\\E[Z, civis=\\E[?25l, \n"
00732 " clear=\\E[H\\E[2J, cnorm=\\E[?25h, cr=^M, \n"
00733 " csr=\\E[%i%p1%d;%p2%dr, cub=\\E[%p1%dD, cub1=^H, \n"
00734 " cud=\\E[%p1%dB, cud1=^J, cuf=\\E[%p1%dC, cuf1=\\E[C, \n"
00735 " cup=\\E[%i%p1%d;%p2%dH, cuu=\\E[%p1%dA, cuu1=\\E[A, \n"
00736 " cvvis=\\E[?25h, dch=\\E[%p1%dP, dch1=\\E[P, dl=\\E[%p1%dM, \n"
00737 " dl1=\\E[M, ech=\\E[%p1%dX, ed=\\E[J, el=\\E[K, el1=\\E[1K, \n"
00738 " enacs=\\E(B\\E)0, flash=\\E[?5h$<100/>\\E[?5l, home=\\E[H, \n"
00739 " hpa=\\E[%i%p1%dG, ht=^I, hts=\\EH, ich=\\E[%p1%d@, ich1=\\E[@, \n"
00740 " il=\\E[%p1%dL, il1=\\E[L, ind=^J, invis=\\E[8m, \n"
00741 " is2=\\E[!p\\E[?3;4l\\E[4l\\E>, kBEG=\\EOu, kDC=\\EOn, \n"
00742 " kEND=\\EOq, kHOM=\\EOw, kIC=\\EOp, kLFT=\\EOt, kNXT=\\EOr, \n"
00743 " kPRV=\\EOx, kRIT=\\EOv, ka1=\\EOH, ka3=\\E[5~, kb2=\\EOE, \n"
00744 " kbeg=\\EOE, kbs=\\177, kc1=\\EOF, kc3=\\E[6~, kcub1=\\EOD, \n"
00745 " kcud1=\\EOB, kcuf1=\\EOC, kcuu1=\\EOA, kdch1=\\E[3~, kend=\\EOF, \n"
00746 " kent=\\EOM, kf0=\\E[21~, kf1=\\E[11~, kf10=\\E[21~, \n"
00747 " kf11=\\E[23~, kf12=\\E[24~, kf13=\\E[25~, kf14=\\E[26~, \n"
00748 " kf15=\\E[28~, kf16=\\E[29~, kf17=\\E[31~, kf18=\\E[32~, \n"
00749 " kf19=\\E[33~, kf2=\\E[12~, kf20=\\E[34~, kf21=\\E[35~, \n"
00750 " kf22=\\E[36~, kf3=\\E[13~, kf4=\\E[14~, kf5=\\E[15~, kf54=\\EOo, \n"
00751 " kf55=\\EOj, kf56=\\EOm, kf57=\\EOk, kf58=\\EOl, kf6=\\E[17~, \n"
00752 " kf7=\\E[18~, kf8=\\E[19~, kf9=\\E[20~, kfnd=\\E[1~, khome=\\EOH, \n"
00753 " kich1=\\E[2~, kind=\\EOs, kmous=\\E[M, knp=\\E[6~, kpp=\\E[5~, \n"
00754 " kri=\\EOy, kslt=\\E[4~, mc0=\\E[i, mc4=\\E[4i, mc5=\\E[5i, \n"
00755 " op=\\E[39;49m, rc=\\E8, rev=\\E[7m, ri=\\EM, rmacs=^O, \n"
00756 " rmam=\\E[?7l, rmcup=\\E[?1047l\\E[?1048l, rmir=\\E[4l, \n"
00757 " rmkx=\\E[?1l\\E>, rmso=\\E[27m, rmul=\\E[24m, \n"
00758 " rs1=\\Ec\\E[?67;9l, rs2=\\E[!p\\E[?3;4l\\E[4l\\E>, sc=\\E7, \n"
00759 " setab=\\E[4%p1%dm, setaf=\\E[3%p1%dm, \n"
00760 " setb=\\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, \n"
00761 " setf=\\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, \n"
00762 " sgr=\\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m%?%p9%t\\016%e\\017%;, \n"
00763 " sgr0=\\E[m\\017, smacs=^N, smam=\\E[?7h, \n"
00764 " smcup=\\E[?1048h\\E[?1047h, smir=\\E[4h, smkx=\\E[?1h\\E=, \n"
00765 " smso=\\E[7m, smul=\\E[4m, tbc=\\E[3g, u6=\\E[%i%d;%dR, \n"
00766 " u7=\\E[6n, u8=\\E[?1;2c, u9=\\E[c, vpa=\\E[%i%p1%dd, \n"
00767 ;
00768
00769 #else
00770 char const *terminfo =
00771 "# Reconstructed via infocmp from file: /usr/share/lib/terminfo/x/xterm \n"
00772 "xterm|vs100|lowells extended xterm terminal emulator, \n"
00773 " am, km, mir, msgr, xenl, \n"
00774 " cols#80, it#8, lines#65, \n"
00775 " acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, \n"
00776 " bel=^G, blink=\\E[5m, bold=\\E[1m, clear=\\E[H\\E[2J, \n"
00777 " cr=\\r, csr=\\E[%i%p1%d;%p2%dr, cub=\\E[%p1%dD, cub1=\\b, \n"
00778 " cud=\\E[%p1%dB, cud1=\\n, cuf=\\E[%p1%dC, cuf1=\\E[C, \n"
00779 " cup=\\E[%i%p1%d;%p2%dH, cuu=\\E[%p1%dA, cuu1=\\E[A, \n"
00780 " dch=\\E[%p1%dP, dch1=\\E[P, dl=\\E[%p1%dM, dl1=\\E[M, \n"
00781 " ed=\\E[J, el=\\E[K, el1=\\E[1K$<3>, enacs=\\E(B\\E)0, \n"
00782 " home=\\E[H, ht=\\t, hts=\\EH, ich=\\E[%p1%d@, ich1=\\E[@, \n"
00783 " il=\\E[%p1%dL, il1=\\E[L, ind=\\n, ka1=\\EOq, ka3=\\EOs, \n"
00784 " kb2=\\EOr, kbs=\\b, kc1=\\EOp, kc3=\\EOn, kcub1=\\EOD, \n"
00785 " kcud1=\\EOB, kcuf1=\\EOC, kcuu1=\\EOA, kent=\\EOM, \n"
00786 " kf1=\\E[11~, \n"
00787 " kf10=\\E[21~, \n"
00788 " kf2=\\E[12~, \n"
00789 " kf3=\\E[13~, \n"
00790 " kf4=\\E[14~, \n"
00791 " kf5=\\E[15~, \n"
00792 " kf6=\\E[17~, \n"
00793 " kf7=\\E[18~, \n"
00794 " kf8=\\E[19~, \n"
00795 " kf9=\\E[20~, \n"
00796 " rc=\\E8, \n"
00797 " rev=\\E[7m, \n"
00798 " khome=\\E[1~, \n"
00799 " kend=\\E[4~, \n"
00800 " kll=\\E[E;, \n"
00801 " kpp=\\E[5~, \n"
00802 " knp=\\E[6~, \n"
00803 " kich1=\\E[2~, \n"
00804 " kf11=\\E[23~, \n"
00805 " kf12=\\E[24~, \n"
00806 " kcbt=\\E[TAB;, \n"
00807 " kLFT=\\E[LEFT;, \n"
00808 " kRIT=\\E[RIGHT;, \n"
00809 " kPRV=\\E[prior;, \n"
00810 " kNXT=\\E[next;, \n"
00811 " kdch1=\\177, \n"
00812 " ri=\\EM, rmacs=^O, rmkx=\\E[?1l\\E>, rmso=\\E[m, \n"
00813 " rmul=\\E[m, \n"
00814 " rs1=\\E>\\E[1;3;4;5;6l\\E[?7h\\E[m\\E[r\\E[2J\\E[H, rs2=@, \n"
00815 " sc=\\E7, \n"
00816 " sgr=\\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t^N%e^O%;, \n"
00817 " sgr0=\\E[m, smacs=^N, smkx=\\E[?1h\\E=, smso=\\E[7m, \n"
00818 " smul=\\E[4m, tbc=\\E[3g, \n"
00819 " kHOM=\\E[H, \n"
00820 " kEND=\\E[E, \n"
00821 ;
00822 #endif
00823
00824 f.write(terminfo, strlen(terminfo));
00825
00826 if(f.bad())
00827 {
00828 std::cerr << "Error creating " << filename << std::endl;
00829 exit(1);
00830 }
00831
00832 f.close();
00833
00834 std::cerr << "\n\n\n\n"
00835 << "Since this is the first time you have run this program as this\n"
00836 << "user on this host, the special purpose curses TERMINFO database\n"
00837 << "is created for you in \n\n "
00838 << dir
00839 << "/xterm.info\n\n"
00840 << "If you wish to change the keyboard bindings used by curses\n"
00841 << "You can edit that file then remove\n\n "
00842 << dir
00843 << "terminfo/x/xterm\n\n"
00844 << "to get the database automatically rebuilt the next\n"
00845 << "you run this program.\n\n"
00846 ;
00847
00848 std::cerr << "Press enter to continue:" << std::endl;
00849 std::cerr.flush();
00850 std::cin.get();
00851
00852 std::cerr << "\n\n\n\n"
00853 << "You should have received documentation about configuring\n"
00854 << "curses with this program. If you have a source distribution\n"
00855 << "look in the etc sub-directory directory for a README file.\n\n"
00856 << "If you are using an X windows emulator you will need to\n"
00857 << "make sure that your emulator passes the Home, End, Page Up,\n"
00858 << "and Page Down keys through as a string not as functions!\n"
00859 << "You'll also want to make the backspace key send ^H not ^?\n"
00860 << "and perhaps modify your shell startup to use \n\n "
00861 << "stty erase '^H'\n\n"
00862 ;
00863
00864 std::cerr << "Press enter to continue:" << std::endl;
00865 std::cerr.flush();
00866 std::cin.get();
00867
00868 std::cerr << "\n\n\n\n"
00869 << "Note: you should have received an Xterm file which is used\n"
00870 << "by X windows to define key bindings for your xterm program.\n"
00871 << "If you choose not use the one provided, you must ensure that\n"
00872 << "all the function keys you like using are set up in both\n"
00873 << "$HOME/Xterm and $HOME/.tools_dir/<OS>/xterm.info.\n\n"
00874 << "If your keys still don't work after making sure of all the\n"
00875 << "above, check to see if you are setting your xmodmap key bindings\n"
00876 << "in some way that conflicts with Xterm and xterm.info.\n\nGood luck!\n\n"
00877 ;
00878
00879
00880 std::cerr << "Press enter to continue:" << std::endl;
00881 std::cerr.flush();
00882 std::cin.get();
00883
00884 }
00885
00886
00887
00888
00889 void create_key_sequences_map()
00890 {
00891 insert_key_sequence(CursesInterface::_map_kf1 , CursorWindow::key_f1);
00892 insert_key_sequence(CursesInterface::_map_kf2 , CursorWindow::key_f2);
00893 insert_key_sequence(CursesInterface::_map_kf3 , CursorWindow::key_f3);
00894 insert_key_sequence(CursesInterface::_map_kf4 , CursorWindow::key_f4);
00895 insert_key_sequence(CursesInterface::_map_kf5 , CursorWindow::key_f5);
00896 insert_key_sequence(CursesInterface::_map_kf6 , CursorWindow::key_f6);
00897 insert_key_sequence(CursesInterface::_map_kf7 , CursorWindow::key_f7);
00898 insert_key_sequence(CursesInterface::_map_kf8 , CursorWindow::key_f8);
00899 insert_key_sequence(CursesInterface::_map_kf9 , CursorWindow::key_f9);
00900 insert_key_sequence(CursesInterface::_map_kf10 , CursorWindow::key_f10);
00901 insert_key_sequence(CursesInterface::_map_kf11 , CursorWindow::key_f11);
00902 insert_key_sequence(CursesInterface::_map_kf12 , CursorWindow::key_f12);
00903 insert_key_sequence(CursesInterface::_map_khom , CursorWindow::key_home);
00904 insert_key_sequence(CursesInterface::_map_kend , CursorWindow::key_end);
00905 insert_key_sequence(CursesInterface::_map_kic , CursorWindow::key_ic);
00906 insert_key_sequence(CursesInterface::_map_kdc , CursorWindow::key_dc);
00907 insert_key_sequence(CursesInterface::_map_kpr , CursorWindow::key_prior);
00908 insert_key_sequence(CursesInterface::_map_knx , CursorWindow::key_next);
00909 insert_key_sequence(CursesInterface::_map_kup , CursorWindow::key_up);
00910 insert_key_sequence(CursesInterface::_map_kdn , CursorWindow::key_down);
00911 insert_key_sequence(CursesInterface::_map_klf , CursorWindow::key_left);
00912 insert_key_sequence(CursesInterface::_map_krt , CursorWindow::key_right);
00913 insert_key_sequence(CursesInterface::_map_kbtab, CursorWindow::key_btab);
00914
00915 {
00916 static char extra_home [] = { 0x1b, '[', 'H', 0 };
00917 static char extra_end [] = { 0x1b, '[', 'F', 0 };
00918 static char extra_btab [] = { 0x1b, '[', 'Z', 0 };
00919
00920 insert_key_sequence(extra_home, CursorWindow::key_home);
00921 insert_key_sequence(extra_end, CursorWindow::key_end);
00922 insert_key_sequence(extra_btab, CursorWindow::key_btab);
00923
00924
00925 #ifdef __linux
00926 static char extra_bs [] = { 0x7f, 0 };
00927 insert_key_sequence(extra_bs, CursorWindow::key_bs);
00928 #else
00929 static char extra_dc [] = { 0x7f, 0 };
00930 insert_key_sequence(extra_dc, CursorWindow::key_dc);
00931
00932 static char extra_dc1 [] = { 0x1b, '[', '3', '~', 0 };
00933 insert_key_sequence(extra_dc1, CursorWindow::key_dc);
00934
00935 static char extra_bs [] = { 0x008, 0 };
00936 insert_key_sequence(extra_bs, CursorWindow::key_bs);
00937 #endif
00938
00939 }
00940
00941 {
00942 static char extra_home1[] = { 0x1b, 'O', 'H', 0 };
00943 static char extra_end1 [] = { 0x1b, 'O', 'F', 0 };
00944 static char extra_btab1[] = { 0x1b, 'O', 'Z', 0 };
00945
00946
00947 insert_key_sequence(extra_home1, CursorWindow::key_home);
00948 insert_key_sequence(extra_end1, CursorWindow::key_end);
00949 insert_key_sequence(extra_btab1, CursorWindow::key_btab);
00950 }
00951
00952
00953 {
00954 static char extra_f1[] = { 0x1b, 'O', 'P', 0 };
00955 static char extra_f2[] = { 0x1b, 'O', 'Q', 0 };
00956 static char extra_f3[] = { 0x1b, 'O', 'R', 0 };
00957 static char extra_f4[] = { 0x1b, 'O', 'S', 0 };
00958 static char extra_end [] = { 0x1b, '[', 'E', 0 };
00959
00960 insert_key_sequence(extra_f1, CursorWindow::key_f1);
00961 insert_key_sequence(extra_f2, CursorWindow::key_f2);
00962 insert_key_sequence(extra_f3, CursorWindow::key_f3);
00963 insert_key_sequence(extra_f4, CursorWindow::key_f4);
00964 insert_key_sequence(extra_end, CursorWindow::key_end);
00965 }
00966
00967
00968 {
00969 static char extra_home1[] = { 0x1b, '[', '1', '~', 0 };
00970 static char extra_end1 [] = { 0x1b, '[', '4', '~', 0 };
00971
00972 insert_key_sequence(extra_home1, CursorWindow::key_home);
00973 insert_key_sequence(extra_end1, CursorWindow::key_end);
00974 }
00975
00976
00977 {
00978 SEARCH search(key_sequences);
00979
00980 if(!search(0x1b))
00981 {
00982 closeCursesTerminal();
00983 printf("couldn't find the Esc key in the sequence!");
00984 exit(1);
00985 }
00986 ++search;
00987
00988 if(!search('['))
00989 {
00990 closeCursesTerminal();
00991 printf("couldn't find the '[' key in the!");
00992 exit(1);
00993 }
00994 ++search;
00995
00996 if(!search('H'))
00997 {
00998 closeCursesTerminal();
00999 printf("couldn't find the 'H' sequence!");
01000 exit(1);
01001 }
01002 ++search;
01003
01004 int code=0;
01005
01006 if(!search.finished(&code))
01007 {
01008 closeCursesTerminal();
01009 printf("couldn't find the home sequence!");
01010 exit(1);
01011 }
01012
01013 if(code != CursorWindow::key_home)
01014 {
01015 closeCursesTerminal();
01016 printf("wrong key code returned");
01017 exit(1);
01018 }
01019
01020 }
01021
01022
01023 }
01024
01025
01026 int alarm_occurred=0;
01027
01028 int read_key_char()
01029
01030
01031 {
01032 char buffer[1];
01033
01034 while(winch_occurred == 0 &&
01035 read(0, &buffer, 1) < 1 &&
01036 alarm_occurred == 0
01037 #ifdef __linux
01038 &&
01039 quit_occurred == 0 &&
01040 susp_occurred == 0 &&
01041 int_occurred == 0
01042 #endif
01043 )
01044 {
01045 usleep(100000);
01046 }
01047
01048
01049 if(alarm_occurred)
01050 {
01051 alarm_occurred = 0;
01052 return 0;
01053 }
01054
01055 if(winch_occurred)
01056 {
01057 return -1;
01058 }
01059
01060 alarm_occurred=0;
01061
01062 #ifdef __linux
01063 if(quit_occurred)
01064 {
01065 quit_occurred=0;
01066 buffer[0] = 0x1c;
01067 }
01068
01069 if(susp_occurred)
01070 {
01071 susp_occurred=0;
01072 buffer[0] = 0x1a;
01073 }
01074
01075 if(int_occurred)
01076 {
01077 int_occurred=0;
01078 buffer[0] = 3;
01079 }
01080 #endif
01081
01082
01083 return buffer[0];
01084
01085 }
01086
01087
01088 #undef refresh
01089
01090 extern "C" void alarm_handler(int signum)
01091 {
01092 alarm_occurred=1;
01093 signal(SIGALRM, alarm_handler);
01094 }
01095
01096 extern "C"
01097 {
01098 static void sigwinch_handler(int)
01099 {
01100 winch_occurred=1;
01101 screen_resize_occurred=true;
01102 }
01103 }
01104
01105
01106 static std::string _saved;
01107
01108 int read_mapped_key(CursorWindow &w)
01109
01110
01111
01112 {
01113
01114 if(_saved.size())
01115 {
01116
01117
01118
01119 int rv = _saved[0];
01120
01121 _saved.erase(_saved.begin());
01122
01123 return rv;
01124 }
01125
01126 if(resize_requested)
01127 return -1;
01128
01129 refresh();
01130
01131 signal(SIGWINCH, sigwinch_handler);
01132
01133 signal(SIGALRM, alarm_handler);
01134
01135 #ifdef __linux
01136 signal(SIGQUIT, quit_handler);
01137 signal(SIGTSTP, susp_handler);
01138 signal(SIGINT, int_handler);
01139 #endif
01140
01141 SEARCH search_term = key_sequences;
01142
01143
01144 int c;
01145
01146 int code;
01147
01148
01149 for(;;)
01150 {
01151 sigprocmask(SIG_UNBLOCK, &winch_blocker, 0);
01152
01153 c = read_key_char();
01154
01155
01156 sigprocmask(SIG_BLOCK, &winch_blocker, 0);
01157
01158 if(c == 0x1b)
01159 {
01160
01161 alarm_occurred=0;
01162 ualarm(900000,0);
01163
01164
01165
01166 }
01167 else
01168 {
01169 ualarm(0,0);
01170
01171 }
01172
01173 if(winch_occurred || resize_requested || c == -1)
01174 {
01175 _saved.resize(0);
01176
01177 closeCursesTerminal();
01178 openCursesTerminal();
01179 refresh();
01180
01181 return -1;
01182 }
01183
01184 if( c == 0 || !search_term(c) )
01185 {
01186
01187
01188
01189 if(c == 0x1b)
01190 {
01191
01192
01193 if( _saved.size() && _saved[0] == 0x1b )
01194 {
01195
01196
01197 SEARCH new_term = key_sequences;
01198
01199 new_term(c);
01200
01201 ++new_term;
01202
01203 search_term = new_term;
01204
01205 _saved.resize(0);
01206 _saved += (char)(0x1b);
01207
01208 continue;
01209
01210 }
01211
01212 }
01213
01214 if(c != 0)
01215 _saved += (char)(c);
01216
01217 if(_saved.size())
01218 {
01219 int rv = _saved[0];
01220
01221 _saved.erase(_saved.begin());
01222
01223 return rv;
01224 }
01225
01226 continue;
01227 }
01228
01229 ++search_term;
01230
01231 _saved += (char)(c);
01232
01233 if(search_term.finished(&code))
01234 {
01235 _saved.resize(0);
01236 return code;
01237 }
01238 }
01239
01240 }
01241
01242 };
01243
01244 }