2 mdport.c - Machine Dependent Code for Porting Unix/Curses games
4 Copyright (C) 2005 Nicholas J. Kisseberth
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name(s) of the author(s) nor the names of other contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/types.h>
41 #elif defined(__DJGPP__)
45 #include <sys/utsname.h>
51 char *strdup(const char *s
);
57 #if defined(_WIN32) && !defined(__MINGW32__)
58 #define PATH_MAX MAX_PATH
72 #define MOD_MOVE(c) (toupper(c) )
80 term
= getenv("TERM");
83 setenv("TERM","interix",1);
85 #if defined(__DJGPP__) || defined(_WIN32)
88 #if defined(__CYGWIN__) || defined(__MSYS__)
97 return((CE
!= NULL
) && (*CE
!= 0));
98 #elif defined (clr_eol)
99 return((clr_eol
!= NULL
) && (*clr_eol
!= 0));
100 #elif !defined(__PDCURSES__)
101 return(clr_eol
!= NULL
);
113 static int md_standout_mode
= 0;
119 CONSOLE_SCREEN_BUFFER_INFO csbiInfo
;
123 if (md_standout_mode
== 0)
125 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
126 GetConsoleScreenBufferInfo(hStdout
, &csbiInfo
);
127 fgattr
= (csbiInfo
.wAttributes
& 0xF);
128 bgattr
= (csbiInfo
.wAttributes
& 0xF0);
129 SetConsoleTextAttribute(hStdout
,(fgattr
<< 4) | (bgattr
>> 4));
130 md_standout_mode
= 1;
133 tputs(SO
,0,md_putchar
);
142 CONSOLE_SCREEN_BUFFER_INFO csbiInfo
;
146 if (md_standout_mode
== 1)
148 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
149 GetConsoleScreenBufferInfo(hStdout
, &csbiInfo
);
150 fgattr
= (csbiInfo
.wAttributes
& 0xF);
151 bgattr
= (csbiInfo
.wAttributes
& 0xF0);
152 SetConsoleTextAttribute(hStdout
,(fgattr
<< 4) | (bgattr
>> 4));
153 md_standout_mode
= 0;
156 tputs(SE
,0,md_putchar
);
162 md_unlink_open_file(char *file
, int inf
)
167 return( _unlink(file
) );
169 return(unlink(file
));
174 md_unlink(char *file
)
178 return( _unlink(file
) );
180 return(unlink(file
));
185 md_creat(char *file
, int mode
)
189 mode
= _S_IREAD
| _S_IWRITE
;
190 fd
= _open(file
,O_CREAT
| O_EXCL
| O_WRONLY
, mode
);
192 fd
= open(file
,O_CREAT
| O_EXCL
| O_WRONLY
, mode
);
219 md_getusername(int uid
)
221 static char login
[80];
225 DWORD size
= UNLEN
+ 1;
226 TCHAR buffer
[UNLEN
+ 1];
229 if (uid
!= md_getuid())
230 strcpy(mybuffer
, "someone");
232 GetUserName(mybuffer
,&size
);
235 #if !defined(_WIN32) && !defined(DJGPP)
238 pw
= getpwuid(getuid());
243 if ((l
== NULL
) || (*l
== '\0'))
244 if ( (l
= getenv("USERNAME")) == NULL
)
245 if ( (l
= getenv("LOGNAME")) == NULL
)
246 if ( (l
= getenv("USER")) == NULL
)
258 static char homedir
[PATH_MAX
];
262 TCHAR szPath
[PATH_MAX
];
264 #if defined(_WIN32) || defined(DJGPP)
269 pw
= getpwuid(getuid());
273 if (strcmp(h
,"/") == 0)
278 if(SUCCEEDED(SHGetFolderPath(NULL
, CSIDL_PERSONAL
, NULL
, 0, szPath
)))
282 if ( (h
== NULL
) || (*h
== '\0') )
283 if ( (h
= getenv("HOME")) == NULL
)
286 strncpy(homedir
,h
,PATH_MAX
-1);
287 len
= strlen(homedir
);
289 if ((len
> 0) && (homedir
[len
-1] == slash
))
308 static char shell
[PATH_MAX
];
311 char *def
= "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
312 #elif defined(__DJGPP__)
313 char *def
= "C:\\COMMAND.COM";
315 char *def
= "/bin/sh";
317 pw
= getpwuid(getuid());
320 if ((s
== NULL
) || (*s
== '\0'))
321 if ( (s
= getenv("COMSPEC")) == NULL
)
322 if ( (s
= getenv("SHELL")) == NULL
)
323 if ( (s
= getenv("SystemRoot")) == NULL
)
326 strncpy(shell
,s
,PATH_MAX
);
327 shell
[PATH_MAX
-1] = 0;
335 #if (!defined(_WIN32) && !defined(__DJGPP__))
346 return((int)_spawnl(_P_WAIT
,sh
,"shell",NULL
,0));
347 #elif defined(__DJGPP__)
348 return ( spawnl(P_WAIT
,sh
,"shell",NULL
,0) );
350 while((pid
= fork()) < 0)
353 if (pid
== 0) /* Shell Process */
356 * Set back to original user, just in case
360 execl(sh
== NULL
? "/bin/sh" : sh
, "shell", "-i", (char *)0);
364 else /* Application */
366 myend
= signal(SIGINT
, SIG_IGN
);
368 myquit
= signal(SIGQUIT
, SIG_IGN
);
370 while (wait(&ret_status
) != pid
)
373 signal(SIGINT
, myquit
);
375 signal(SIGQUIT
, myend
);
384 directory_exists(char *dirname
)
388 if (stat(dirname
, &sb
) == 0) /* path exists */
389 return (sb
.st_mode
& S_IFDIR
);
397 static char path
[1024];
400 if ( (home
= getenv("ROGUEHOME")) != NULL
)
404 strncpy(path
, home
, PATH_MAX
- 20);
406 end
= &path
[strlen(path
)-1];
408 while( (end
>= path
) && ((*end
== '/') || (*end
== '\\')))
411 if (directory_exists(path
))
416 if (directory_exists("/var/games/roguelike"))
417 return("/var/games/roguelike");
418 if (directory_exists("/var/lib/roguelike"))
419 return("/var/lib/roguelike");
420 if (directory_exists("/var/roguelike"))
421 return("/var/roguelike");
422 if (directory_exists("/usr/games/lib"))
423 return("/usr/games/lib");
424 if (directory_exists("/games/roguelik"))
425 return("/games/roguelik");
426 if (directory_exists(md_gethomedir()))
427 return(md_gethomedir());
432 md_getrealname(int uid
)
434 static char uidstr
[20];
435 #if !defined(_WIN32) && !defined(DJGPP)
438 if ((pp
= getpwuid(uid
)) == NULL
)
440 sprintf(uidstr
,"%d", uid
);
446 sprintf(uidstr
,"%d", uid
);
451 extern char *xcrypt(char *key
, char *salt
);
454 md_crypt(char *key
, char *salt
)
456 return( xcrypt(key
,salt
) );
460 md_getpass(char *prompt
)
463 static char password_buffer
[9];
464 char *p
= password_buffer
;
469 /* If we can't prompt, abort */
470 if (fputs(prompt
, stderr
) < 0)
478 /* Get a character with no echo */
481 /* Exit on interrupt (^c or ^break) */
482 if (c
== '\003' || c
== 0x100)
485 /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
486 if (c
== '\r' || c
== '\n' || c
== '\004' || c
== '\032')
489 /* Back up on backspace */
494 else if (p
> password_buffer
)
499 /* Ignore DOS extended characters */
503 /* Add to password if it isn't full */
504 if (p
< password_buffer
+ max_length
- 1)
513 return password_buffer
;
515 return( (char *) getpass(prompt
) );
520 int md_endian
= 0x01020304;
523 md_ntohl(unsigned long int x
)
526 if ( *((char *)&md_endian
) == 0x01 )
529 return( ((x
& 0x000000ffU
) << 24) |
530 ((x
& 0x0000ff00U
) << 8) |
531 ((x
& 0x00ff0000U
) >> 8) |
532 ((x
& 0xff000000U
) >> 24) );
539 md_htonl(unsigned long int x
)
542 if ( *((char *)&md_endian
) == 0x01 )
545 return( ((x
& 0x000000ffU
) << 24) |
546 ((x
& 0x0000ff00U
) << 8) |
547 ((x
& 0x00ff0000U
) >> 8) |
548 ((x
& 0xff000000U
) >> 24) );
559 #elif defined(_WIN32)
562 struct utmpx
*up
=NULL
;
569 if (up
&& up
->ut_type
== USER_PROCESS
)
580 md_getloadavg(double *avg
)
582 #if defined(__GLIBC__) || defined(_BSD)
583 if (getloadavg(avg
, 3) == -1)
586 avg
[0] = avg
[1] = avg
[2] = 0.0;
602 md_srandom(unsigned x
)
617 return(lrand48() & 0x7fffffff);
632 md_strdup(const char *s
)
635 return( _strdup(s
) );
647 GlobalMemoryStatus(&stat
);
649 return((long)stat
.dwTotalPageFile
);
651 return( (long)sbrk(0) );
658 static char nodename
[80];
660 #if !defined(_WIN32) && !defined(__DJGPP__)
661 struct utsname ourname
;
663 if (uname(&ourname
) == 0)
664 n
= ourname
.nodename
;
666 if ((n
== NULL
) || (*n
== '\0'))
667 if ( (n
= getenv("COMPUTERNAME")) == NULL
)
668 if ( (n
= getenv("HOSTNAME")) == NULL
)
671 strncpy(nodename
, n
, 80);
681 return(_tty
.sg_erase
); /* process erase character */
682 #elif defined(USG5_0)
683 return(_tty
.c_cc
[VERASE
]); /* process erase character */
684 #else /* USG5_2 .... curses */
685 return( erasechar() ); /* process erase character */
693 return(_tty
.sg_kill
);
694 #elif defined(USG5_0)
695 return(_tty
.c_cc
[VKILL
]);
696 #else /* USG5_2 ..... curses */
697 return( killchar() );
703 * Print a readable version of a certain character
710 extern char *_unctrl
[]; /* Defined in curses library */
712 return _unctrl
[ch
&0177];
714 return( unctrl(ch
) );
723 #elif defined(USG5_0)
724 ioctl(_tty_ch
,TCFLSH
,0)
725 #else /* USG5_2.... curses */
731 Cursor/Keypad Support
733 Sadly Cursor/Keypad support is less straightforward than it should be.
735 The various terminal emulators/consoles choose to differentiate the
736 cursor and keypad keys (with modifiers) in different ways (if at all!).
737 Furthermore they use different code set sequences for each key only
738 a subset of which the various curses libraries recognize. Partly due
739 to incomplete termcap/terminfo entries and partly due to inherent
740 limitations of those terminal capability databases.
742 I give curses first crack at decoding the sequences. If it fails to decode
743 it we check for common ESC-prefixed sequences.
745 All cursor/keypad results are translated into standard rogue movement
748 Unmodified keys are translated to walk commands: hjklyubn
749 Modified (shift,control,alt) are translated to run commands: HJKLYUBN
751 Console and supported (differentiated) keys
752 Interix: Cursor Keys, Keypad, Ctl-Keypad
753 Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys
754 MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
755 Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
756 DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
758 Interix Console (raw, ncurses)
759 ==============================
760 normal shift ctrl alt
761 ESC [D, ESC F^, ESC [D, ESC [D /# Left #/
762 ESC [C, ESC F$, ESC [C, ESC [C /# Right #/
763 ESC [A, ESC F-, local win, ESC [A /# Up #/
764 ESC [B, ESC F+, local win, ESC [B /# Down #/
765 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
766 ESC [S, local win, ESC [S, ESC [S /# Page Up #/
767 ESC [T, local win, ESC [T, ESC [T /# Page Down #/
768 ESC [U, ESC [U, ESC [U, ESC [U /# End #/
769 ESC [D, ESC F^, ESC [D, O /# Keypad Left #/
770 ESC [C, ESC F$, ESC [C, O /# Keypad Right #/
771 ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/
772 ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/
773 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
774 ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/
775 ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/
776 ESC [U, ESC [U, ESC [-21, O /# Keypad End #/
777 nothing, nothing, nothing, O /# Kaypad 5 #/
779 Interix Console (term=interix, ncurses)
780 ==============================
781 KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/
782 KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/
783 KEY_UP, 0x146, local win, KEY_UP /# Up #/
784 KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/
785 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
786 KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/
787 KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/
788 KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/
789 KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/
790 KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/
791 KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/
792 KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/
793 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
794 KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/
795 KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/
796 KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/
797 nothing, nothing, nothing, O /# Keypad 5 #/
799 Cygwin Console (raw, ncurses)
800 ==============================
801 normal shift ctrl alt
802 ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/
803 ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/
804 ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/
805 ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/
806 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/
807 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/
808 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/
809 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/
810 ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/
811 ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/
812 ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/
813 ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/
814 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/
815 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/
816 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/
817 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/
818 ESC [-71, nothing, nothing, O /# Keypad 5 #/
820 Cygwin Console (term=cygwin, ncurses)
821 ==============================
822 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/
823 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/
824 KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/
825 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/
826 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/
827 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/
828 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/
829 KEY_END, KEY_END, KEY_END, ESC-360 /# End #/
830 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/
831 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/
832 KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/
833 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/
834 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/
835 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/
836 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/
837 KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/
838 ESC [G, nothing, nothing, O /# Keypad 5 #/
840 MSYS Console (raw, ncurses)
841 ==============================
842 normal shift ctrl alt
843 ESC OD, ESC [d, ESC Od nothing /# Left #/
844 ESC OE, ESC [e, ESC Oe, nothing /# Right #/
845 ESC OA, ESC [a, ESC Oa, nothing /# Up #/
846 ESC OB, ESC [b, ESC Ob, nothing /# Down #/
847 ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/
848 ESC [5~, local window, ESC [5^, nothing /# Page Up #/
849 ESC [6~, local window, ESC [6^, nothing /# Page Down #/
850 ESC [8~, ESC [8$, ESC [8^, nothing /# End #/
851 ESC OD, ESC [d, ESC Od O /# Keypad Left #/
852 ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/
853 ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/
854 ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/
855 ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/
856 ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/
857 ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/
858 ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/
859 11, 11, 11, O /# Keypad 5 #/
861 MSYS Console (term=rxvt, ncurses)
862 ==============================
863 normal shift ctrl alt
864 KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/
865 KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/
866 KEY_UP, 518, 519, nothing /# Up #/
867 KEY_DOWN, 511, 512, nothing /# Down #/
868 KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/
869 KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/
870 KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/
871 KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/
872 KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/
873 KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/
874 KEY_UP, 518, 519, O /# Keypad Up #/
875 KEY_DOWN, 511, 512, O /# Keypad Down #/
876 KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/
877 KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/
878 KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/
879 KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/
880 11, 11, 11, O /# Keypad 5 #/
882 Win32 Console (raw, pdcurses)
883 DJGPP Console (raw, pdcurses)
884 ==============================
885 normal shift ctrl alt
886 260, 391, 443, 493 /# Left #/
887 261, 400, 444, 492 /# Right #/
888 259, 547, 480, 490 /# Up #/
889 258, 548, 481, 491 /# Down #/
890 262, 388, 447, 524 /# Home #/
891 339, 396, 445, 526 /# Page Up #/
892 338, 394, 446, 520 /# Page Down #/
893 358, 384, 448, 518 /# End #/
894 452, 52('4'), 511, 521 /# Keypad Left #/
895 454, 54('6'), 513, 523 /# Keypad Right #/
896 450, 56('8'), 515, 525 /# Keypad Up #/
897 456, 50('2'), 509, 519 /# Keypad Down #/
898 449, 55('7'), 514, 524 /# Keypad Home #/
899 451, 57('9'), 516, 526 /# Keypad PgUp #/
900 457, 51('3'), 510, 520 /# Keypad PgDn #/
901 455, 49('1'), 508, 518 /# Keypad End #/
902 453, 53('5'), 512, 522 /# Keypad 5 #/
904 Win32 Console (pdcurses, MSVC/MingW32)
905 DJGPP Console (pdcurses)
906 ==============================
907 normal shift ctrl alt
908 KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/
909 KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/
910 KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/
911 KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/
912 KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/
913 KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/
914 KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/
915 KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/
916 KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/
917 KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/
918 KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/
919 KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/
920 KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/
921 KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/
922 KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/
923 KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/
924 KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/
927 ==============================
928 normal shift ctrl alt
929 ESC [D, ESC [D, ESC [D, ESC [D /# Left #/
930 ESC [C, ESC [C, ESC [C, ESC [C /# Right #/
931 ESC [A, ESC [A, ESC [A, ESC [A /# Up #/
932 ESC [B, ESC [B, ESC [B, ESC [B /# Down #/
933 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
934 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/
935 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/
936 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
937 ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/
938 ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/
939 ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/
940 ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/
941 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
942 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/
943 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/
944 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/
945 nothing, nothing, nothing, nothing /# Keypad 5 #/
947 Windows Telnet (term=xterm)
948 ==============================
949 normal shift ctrl alt
950 KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/
951 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/
952 KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/
953 KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/
954 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
955 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/
956 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/
957 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
958 KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/
959 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/
960 KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/
961 KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/
962 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
963 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/
964 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/
965 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
966 ESC [-71, nothing, nothing, O /# Keypad 5 #/
969 ==============================
970 normal shift ctrl alt
971 ESC [D, ESC [D, ESC OD, ESC [D /# Left #/
972 ESC [C, ESC [C, ESC OC, ESC [C /# Right #/
973 ESC [A, ESC [A, ESC OA, ESC [A /# Up #/
974 ESC [B, ESC [B, ESC OB, ESC [B /# Down #/
975 ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/
976 ESC [5~, local win, local win, ESC [5~ /# Page Up #/
977 ESC [6~, local win, local win, ESC [6~ /# Page Down #/
978 ESC [4~, ESC [4~, local win, ESC [4~ /# End #/
979 ESC [D, ESC [D, ESC [D, O /# Keypad Left #/
980 ESC [C, ESC [C, ESC [C, O /# Keypad Right #/
981 ESC [A, ESC [A, ESC [A, O /# Keypad Up #/
982 ESC [B, ESC [B, ESC [B, O /# Keypad Down #/
983 ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/
984 ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/
985 ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/
986 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
987 nothing, nothing, nothing, O /# Keypad 5 #/
990 ==============================
991 normal shift ctrl alt
992 KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/
993 KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/
994 KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/
995 KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/
996 ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/
997 KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/
998 KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/
999 ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/
1000 ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/
1001 ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/
1002 ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/
1003 ESC Or, ESC Or, ESC Or, O /# Keypad Down #/
1004 ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/
1005 ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/
1006 ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/
1007 ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/
1008 ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/
1017 md_readchar(WINDOW
*win
)
1021 int mode
= M_NORMAL
;
1022 int mode2
= M_NORMAL
;
1028 if (ch
== ERR
) /* timed out waiting for valid sequence */
1029 { /* flush input so far and start over */
1037 if (mode
== M_TRAIL
)
1039 if (ch
== '^') /* msys console : 7,5,6,8: modified*/
1040 ch
= MOD_MOVE( toupper(lastch
) );
1042 if (ch
== '~') /* cygwin console: 1,5,6,4: normal */
1043 ch
= tolower(lastch
); /* windows telnet: 1,5,6,4: normal */
1044 /* msys console : 7,5,6,8: normal */
1046 if (mode2
== M_ESC
) /* cygwin console: 1,5,6,4: modified*/
1047 ch
= MOD_MOVE( toupper(ch
) );
1060 if ((ch
== 'F') || (ch
== 'O') || (ch
== '['))
1069 /* Cygwin Console */
1071 case KEY_LEFT
: ch
= MOD_MOVE('H'); break;
1072 case KEY_RIGHT
: ch
= MOD_MOVE('L'); break;
1073 case KEY_UP
: ch
= MOD_MOVE('K'); break;
1074 case KEY_DOWN
: ch
= MOD_MOVE('J'); break;
1075 case KEY_HOME
: ch
= MOD_MOVE('Y'); break;
1076 case KEY_PPAGE
: ch
= MOD_MOVE('U'); break;
1077 case KEY_NPAGE
: ch
= MOD_MOVE('N'); break;
1078 case KEY_END
: ch
= MOD_MOVE('B'); break;
1086 if (mode
== M_KEYPAD
)
1090 /* ESC F - Interix Console codes */
1091 case '^': ch
= MOD_MOVE('H'); break; /* Shift-Left */
1092 case '$': ch
= MOD_MOVE('L'); break; /* Shift-Right */
1094 /* ESC [ - Interix Console codes */
1095 case 'H': ch
= 'y'; break; /* Home */
1096 case 1: ch
= MOD_MOVE('K'); break; /* Ctl-Keypad Up */
1097 case 2: ch
= MOD_MOVE('J'); break; /* Ctl-Keypad Down */
1098 case 3: ch
= MOD_MOVE('L'); break; /* Ctl-Keypad Right */
1099 case 4: ch
= MOD_MOVE('H'); break; /* Ctl-Keypad Left */
1100 case 263: ch
= MOD_MOVE('Y'); break; /* Ctl-Keypad Home */
1101 case 19: ch
= MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */
1102 case 20: ch
= MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */
1103 case 21: ch
= MOD_MOVE('B'); break; /* Ctl-Keypad End */
1105 /* ESC [ - Cygwin Console codes */
1106 case 'G': ch
= '.'; break; /* Keypad 5 */
1107 case '7': lastch
= 'Y'; mode
=M_TRAIL
; break; /* Ctl-Home */
1108 case '5': lastch
= 'U'; mode
=M_TRAIL
; break; /* Ctl-PgUp */
1109 case '6': lastch
= 'N'; mode
=M_TRAIL
; break; /* Ctl-PgDn */
1111 /* ESC [ - Win32 Telnet, PuTTY */
1112 case '1': lastch
= 'y'; mode
=M_TRAIL
; break; /* Home */
1113 case '4': lastch
= 'b'; mode
=M_TRAIL
; break; /* End */
1116 case 'D': ch
= MOD_MOVE('H'); break;
1117 case 'C': ch
= MOD_MOVE('L'); break;
1118 case 'A': ch
= MOD_MOVE('K'); break;
1119 case 'B': ch
= MOD_MOVE('J'); break;
1120 case 't': ch
= 'h'; break;
1121 case 'v': ch
= 'l'; break;
1122 case 'x': ch
= 'k'; break;
1123 case 'r': ch
= 'j'; break;
1124 case 'w': ch
= 'y'; break;
1125 case 'y': ch
= 'u'; break;
1126 case 's': ch
= 'n'; break;
1127 case 'q': ch
= 'b'; break;
1128 case 'u': ch
= '.'; break;
1131 if (mode
!= M_KEYPAD
)
1144 case KEY_LEFT
: ch
= 'h'; break;
1145 case KEY_DOWN
: ch
= 'j'; break;
1146 case KEY_UP
: ch
= 'k'; break;
1147 case KEY_RIGHT
: ch
= 'l'; break;
1148 case KEY_HOME
: ch
= 'y'; break;
1149 case KEY_PPAGE
: ch
= 'u'; break;
1150 case KEY_END
: ch
= 'b'; break;
1152 case KEY_LL
: ch
= 'b'; break;
1154 case KEY_NPAGE
: ch
= 'n'; break;
1157 case KEY_B1
: ch
= 'h'; break;
1158 case KEY_C2
: ch
= 'j'; break;
1159 case KEY_A2
: ch
= 'k'; break;
1160 case KEY_B3
: ch
= 'l'; break;
1162 case KEY_A1
: ch
= 'y'; break;
1163 case KEY_A3
: ch
= 'u'; break;
1164 case KEY_C1
: ch
= 'b'; break;
1165 case KEY_C3
: ch
= 'n'; break;
1166 /* next should be '.', but for problem with putty/linux */
1167 case KEY_B2
: ch
= 'u'; break;
1170 case KEY_SRIGHT
: ch
= MOD_MOVE('L'); break;
1171 case KEY_SLEFT
: ch
= MOD_MOVE('H'); break;
1173 case KEY_SUP
: ch
= MOD_MOVE('K'); break;
1174 case KEY_SDOWN
: ch
= MOD_MOVE('J'); break;
1176 case KEY_SHOME
: ch
= MOD_MOVE('Y'); break;
1177 case KEY_SPREVIOUS
:ch
= MOD_MOVE('U'); break;
1178 case KEY_SEND
: ch
= MOD_MOVE('B'); break;
1179 case KEY_SNEXT
: ch
= MOD_MOVE('N'); break;
1181 case 0x146 : ch
= MOD_MOVE('K'); break; /* Shift-Up */
1182 case 0x145 : ch
= MOD_MOVE('J'); break; /* Shift-Down */
1185 case CTL_RIGHT
: ch
= MOD_MOVE('L'); break;
1186 case CTL_LEFT
: ch
= MOD_MOVE('H'); break;
1187 case CTL_UP
: ch
= MOD_MOVE('K'); break;
1188 case CTL_DOWN
: ch
= MOD_MOVE('J'); break;
1189 case CTL_HOME
: ch
= MOD_MOVE('Y'); break;
1190 case CTL_PGUP
: ch
= MOD_MOVE('U'); break;
1191 case CTL_END
: ch
= MOD_MOVE('B'); break;
1192 case CTL_PGDN
: ch
= MOD_MOVE('N'); break;
1195 case KEY_EOL
: ch
= MOD_MOVE('B'); break;
1199 /* MSYS rxvt console */
1200 case 511 : ch
= MOD_MOVE('J'); break; /* Shift Dn */
1201 case 512 : ch
= MOD_MOVE('J'); break; /* Ctl Down */
1202 case 514 : ch
= MOD_MOVE('H'); break; /* Ctl Left */
1203 case 516 : ch
= MOD_MOVE('L'); break; /* Ctl Right*/
1204 case 518 : ch
= MOD_MOVE('K'); break; /* Shift Up */
1205 case 519 : ch
= MOD_MOVE('K'); break; /* Ctl Up */
1209 case CTL_PAD1
: ch
= MOD_MOVE('B'); break;
1210 case CTL_PAD2
: ch
= MOD_MOVE('J'); break;
1211 case CTL_PAD3
: ch
= MOD_MOVE('N'); break;
1212 case CTL_PAD4
: ch
= MOD_MOVE('H'); break;
1213 case CTL_PAD5
: ch
= '.'; break;
1214 case CTL_PAD6
: ch
= MOD_MOVE('L'); break;
1215 case CTL_PAD7
: ch
= MOD_MOVE('Y'); break;
1216 case CTL_PAD8
: ch
= MOD_MOVE('K'); break;
1217 case CTL_PAD9
: ch
= MOD_MOVE('U'); break;
1221 case ALT_RIGHT
: ch
= MOD_MOVE('L'); break;
1222 case ALT_LEFT
: ch
= MOD_MOVE('H'); break;
1223 case ALT_DOWN
: ch
= MOD_MOVE('J'); break;
1224 case ALT_HOME
: ch
= MOD_MOVE('Y'); break;
1225 case ALT_PGUP
: ch
= MOD_MOVE('U'); break;
1226 case ALT_END
: ch
= MOD_MOVE('B'); break;
1227 case ALT_PGDN
: ch
= MOD_MOVE('N'); break;
1231 case ALT_PAD1
: ch
= MOD_MOVE('B'); break;
1232 case ALT_PAD2
: ch
= MOD_MOVE('J'); break;
1233 case ALT_PAD3
: ch
= MOD_MOVE('N'); break;
1234 case ALT_PAD4
: ch
= MOD_MOVE('H'); break;
1235 case ALT_PAD5
: ch
= '.'; break;
1236 case ALT_PAD6
: ch
= MOD_MOVE('L'); break;
1237 case ALT_PAD7
: ch
= MOD_MOVE('Y'); break;
1238 case ALT_PAD8
: ch
= MOD_MOVE('K'); break;
1239 case ALT_PAD9
: ch
= MOD_MOVE('U'); break;
1246 nocbreak(); /* disable halfdelay mode if on */