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)
94 return((CE
!= NULL
) && (*CE
!= 0));
95 #elif defined (clr_eol)
96 return((clr_eol
!= NULL
) && (*clr_eol
!= 0));
97 #elif !defined(__PDCURSES__)
98 return(clr_eol
!= NULL
);
110 static int md_standout_mode
= 0;
116 CONSOLE_SCREEN_BUFFER_INFO csbiInfo
;
120 if (md_standout_mode
== 0)
122 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
123 GetConsoleScreenBufferInfo(hStdout
, &csbiInfo
);
124 fgattr
= (csbiInfo
.wAttributes
& 0xF);
125 bgattr
= (csbiInfo
.wAttributes
& 0xF0);
126 SetConsoleTextAttribute(hStdout
,(fgattr
<< 4) | (bgattr
>> 4));
127 md_standout_mode
= 1;
130 tputs(SO
,0,md_putchar
);
139 CONSOLE_SCREEN_BUFFER_INFO csbiInfo
;
143 if (md_standout_mode
== 1)
145 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
146 GetConsoleScreenBufferInfo(hStdout
, &csbiInfo
);
147 fgattr
= (csbiInfo
.wAttributes
& 0xF);
148 bgattr
= (csbiInfo
.wAttributes
& 0xF0);
149 SetConsoleTextAttribute(hStdout
,(fgattr
<< 4) | (bgattr
>> 4));
150 md_standout_mode
= 0;
153 tputs(SE
,0,md_putchar
);
159 md_unlink_open_file(char *file
, int inf
)
164 return( _unlink(file
) );
166 return(unlink(file
));
171 md_unlink(char *file
)
175 return( _unlink(file
) );
177 return(unlink(file
));
182 md_creat(char *file
, int mode
)
186 mode
= _S_IREAD
| _S_IWRITE
;
187 fd
= _open(file
,O_CREAT
| O_EXCL
| O_WRONLY
, mode
);
189 fd
= open(file
,O_CREAT
| O_EXCL
| O_WRONLY
, mode
);
216 md_getusername(int uid
)
218 static char login
[80];
222 DWORD size
= UNLEN
+ 1;
223 TCHAR buffer
[UNLEN
+ 1];
226 if (uid
!= md_getuid())
227 strcpy(mybuffer
, "someone");
229 GetUserName(mybuffer
,&size
);
232 #if !defined(_WIN32) && !defined(DJGPP)
235 pw
= getpwuid(getuid());
240 if ((l
== NULL
) || (*l
== '\0'))
241 if ( (l
= getenv("USERNAME")) == NULL
)
242 if ( (l
= getenv("LOGNAME")) == NULL
)
243 if ( (l
= getenv("USER")) == NULL
)
255 static char homedir
[PATH_MAX
];
259 TCHAR szPath
[PATH_MAX
];
261 #if defined(_WIN32) || defined(DJGPP)
266 pw
= getpwuid(getuid());
270 if (strcmp(h
,"/") == 0)
275 if(SUCCEEDED(SHGetFolderPath(NULL
, CSIDL_PERSONAL
, NULL
, 0, szPath
)))
279 if ( (h
== NULL
) || (*h
== '\0') )
280 if ( (h
= getenv("HOME")) == NULL
)
283 strncpy(homedir
,h
,PATH_MAX
-1);
284 len
= strlen(homedir
);
286 if ((len
> 0) && (homedir
[len
-1] == slash
))
305 static char shell
[PATH_MAX
];
308 char *def
= "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
309 #elif defined(__DJGPP__)
310 char *def
= "C:\\COMMAND.COM";
312 char *def
= "/bin/sh";
314 pw
= getpwuid(getuid());
317 if ((s
== NULL
) || (*s
== '\0'))
318 if ( (s
= getenv("COMSPEC")) == NULL
)
319 if ( (s
= getenv("SHELL")) == NULL
)
320 if ( (s
= getenv("SystemRoot")) == NULL
)
323 strncpy(shell
,s
,PATH_MAX
);
324 shell
[PATH_MAX
-1] = 0;
332 #if (!defined(_WIN32) && !defined(__DJGPP__))
343 return((int)_spawnl(_P_WAIT
,sh
,"shell",NULL
,0));
344 #elif defined(__DJGPP__)
345 return ( spawnl(P_WAIT
,sh
,"shell",NULL
,0) );
347 while((pid
= fork()) < 0)
350 if (pid
== 0) /* Shell Process */
353 * Set back to original user, just in case
357 execl(sh
== NULL
? "/bin/sh" : sh
, "shell", "-i", (char *)0);
361 else /* Application */
363 myend
= signal(SIGINT
, SIG_IGN
);
365 myquit
= signal(SIGQUIT
, SIG_IGN
);
367 while (wait(&ret_status
) != pid
)
370 signal(SIGINT
, myquit
);
372 signal(SIGQUIT
, myend
);
381 directory_exists(char *dirname
)
385 if (stat(dirname
, &sb
) == 0) /* path exists */
386 return (sb
.st_mode
& S_IFDIR
);
394 static char path
[1024];
397 if ( (home
= getenv("ROGUEHOME")) != NULL
)
401 strncpy(path
, home
, PATH_MAX
- 20);
403 end
= &path
[strlen(path
)-1];
405 while( (end
>= path
) && ((*end
== '/') || (*end
== '\\')))
408 if (directory_exists(path
))
413 if (directory_exists("/var/games/roguelike"))
414 return("/var/games/roguelike");
415 if (directory_exists("/var/lib/roguelike"))
416 return("/var/lib/roguelike");
417 if (directory_exists("/var/roguelike"))
418 return("/var/roguelike");
419 if (directory_exists("/usr/games/lib"))
420 return("/usr/games/lib");
421 if (directory_exists("/games/roguelik"))
422 return("/games/roguelik");
423 if (directory_exists(md_gethomedir()))
424 return(md_gethomedir());
429 md_getrealname(int uid
)
431 static char uidstr
[20];
432 #if !defined(_WIN32) && !defined(DJGPP)
435 if ((pp
= getpwuid(uid
)) == NULL
)
437 sprintf(uidstr
,"%d", uid
);
443 sprintf(uidstr
,"%d", uid
);
448 extern char *xcrypt(char *key
, char *salt
);
451 md_crypt(char *key
, char *salt
)
453 return( xcrypt(key
,salt
) );
457 md_getpass(char *prompt
)
460 static char password_buffer
[9];
461 char *p
= password_buffer
;
466 /* If we can't prompt, abort */
467 if (fputs(prompt
, stderr
) < 0)
475 /* Get a character with no echo */
478 /* Exit on interrupt (^c or ^break) */
479 if (c
== '\003' || c
== 0x100)
482 /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
483 if (c
== '\r' || c
== '\n' || c
== '\004' || c
== '\032')
486 /* Back up on backspace */
491 else if (p
> password_buffer
)
496 /* Ignore DOS extended characters */
500 /* Add to password if it isn't full */
501 if (p
< password_buffer
+ max_length
- 1)
510 return password_buffer
;
512 return( (char *) getpass(prompt
) );
517 int md_endian
= 0x01020304;
520 md_ntohl(unsigned long int x
)
523 if ( *((char *)&md_endian
) == 0x01 )
526 return( ((x
& 0x000000ffU
) << 24) |
527 ((x
& 0x0000ff00U
) << 8) |
528 ((x
& 0x00ff0000U
) >> 8) |
529 ((x
& 0xff000000U
) >> 24) );
536 md_htonl(unsigned long int x
)
539 if ( *((char *)&md_endian
) == 0x01 )
542 return( ((x
& 0x000000ffU
) << 24) |
543 ((x
& 0x0000ff00U
) << 8) |
544 ((x
& 0x00ff0000U
) >> 8) |
545 ((x
& 0xff000000U
) >> 24) );
556 #elif defined(_WIN32)
559 struct utmpx
*up
=NULL
;
566 if (up
&& up
->ut_type
== USER_PROCESS
)
577 md_getloadavg(double *avg
)
579 #if defined(__GLIBC__) || defined(_BSD)
580 if (getloadavg(avg
, 3) == -1)
583 avg
[0] = avg
[1] = avg
[2] = 0.0;
599 md_srandom(unsigned x
)
614 return(lrand48() & 0x7fffffff);
629 md_strdup(const char *s
)
632 return( _strdup(s
) );
644 GlobalMemoryStatus(&stat
);
646 return((long)stat
.dwTotalPageFile
);
648 return( (long)sbrk(0) );
655 static char nodename
[80];
657 #if !defined(_WIN32) && !defined(__DJGPP__)
658 struct utsname ourname
;
660 if (uname(&ourname
) == 0)
661 n
= ourname
.nodename
;
663 if ((n
== NULL
) || (*n
== '\0'))
664 if ( (n
= getenv("COMPUTERNAME")) == NULL
)
665 if ( (n
= getenv("HOSTNAME")) == NULL
)
668 strncpy(nodename
, n
, 80);
678 return(_tty
.sg_erase
); /* process erase character */
679 #elif defined(USG5_0)
680 return(_tty
.c_cc
[VERASE
]); /* process erase character */
681 #else /* USG5_2 .... curses */
682 return( erasechar() ); /* process erase character */
690 return(_tty
.sg_kill
);
691 #elif defined(USG5_0)
692 return(_tty
.c_cc
[VKILL
]);
693 #else /* USG5_2 ..... curses */
694 return( killchar() );
700 * Print a readable version of a certain character
707 extern char *_unctrl
[]; /* Defined in curses library */
709 return _unctrl
[ch
&0177];
711 return( unctrl(ch
) );
720 #elif defined(USG5_0)
721 ioctl(_tty_ch
,TCFLSH
,0)
722 #else /* USG5_2.... curses */
728 Cursor/Keypad Support
730 Sadly Cursor/Keypad support is less straightforward than it should be.
732 The various terminal emulators/consoles choose to differentiate the
733 cursor and keypad keys (with modifiers) in different ways (if at all!).
734 Furthermore they use different code set sequences for each key only
735 a subset of which the various curses libraries recognize. Partly due
736 to incomplete termcap/terminfo entries and partly due to inherent
737 limitations of those terminal capability databases.
739 I give curses first crack at decoding the sequences. If it fails to decode
740 it we check for common ESC-prefixed sequences.
742 All cursor/keypad results are translated into standard rogue movement
745 Unmodified keys are translated to walk commands: hjklyubn
746 Modified (shift,control,alt) are translated to run commands: HJKLYUBN
748 Console and supported (differentiated) keys
749 Interix: Cursor Keys, Keypad, Ctl-Keypad
750 Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys
751 MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
752 Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
753 DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
755 Interix Console (raw, ncurses)
756 ==============================
757 normal shift ctrl alt
758 ESC [D, ESC F^, ESC [D, ESC [D /# Left #/
759 ESC [C, ESC F$, ESC [C, ESC [C /# Right #/
760 ESC [A, ESC F-, local win, ESC [A /# Up #/
761 ESC [B, ESC F+, local win, ESC [B /# Down #/
762 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
763 ESC [S, local win, ESC [S, ESC [S /# Page Up #/
764 ESC [T, local win, ESC [T, ESC [T /# Page Down #/
765 ESC [U, ESC [U, ESC [U, ESC [U /# End #/
766 ESC [D, ESC F^, ESC [D, O /# Keypad Left #/
767 ESC [C, ESC F$, ESC [C, O /# Keypad Right #/
768 ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/
769 ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/
770 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
771 ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/
772 ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/
773 ESC [U, ESC [U, ESC [-21, O /# Keypad End #/
774 nothing, nothing, nothing, O /# Kaypad 5 #/
776 Interix Console (term=interix, ncurses)
777 ==============================
778 KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/
779 KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/
780 KEY_UP, 0x146, local win, KEY_UP /# Up #/
781 KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/
782 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
783 KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/
784 KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/
785 KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/
786 KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/
787 KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/
788 KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/
789 KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/
790 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
791 KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/
792 KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/
793 KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/
794 nothing, nothing, nothing, O /# Keypad 5 #/
796 Cygwin Console (raw, ncurses)
797 ==============================
798 normal shift ctrl alt
799 ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/
800 ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/
801 ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/
802 ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/
803 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/
804 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/
805 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/
806 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/
807 ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/
808 ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/
809 ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/
810 ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/
811 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/
812 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/
813 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/
814 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/
815 ESC [-71, nothing, nothing, O /# Keypad 5 #/
817 Cygwin Console (term=cygwin, ncurses)
818 ==============================
819 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/
820 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/
821 KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/
822 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/
823 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/
824 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/
825 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/
826 KEY_END, KEY_END, KEY_END, ESC-360 /# End #/
827 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/
828 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/
829 KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/
830 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/
831 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/
832 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/
833 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/
834 KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/
835 ESC [G, nothing, nothing, O /# Keypad 5 #/
837 MSYS Console (raw, ncurses)
838 ==============================
839 normal shift ctrl alt
840 ESC OD, ESC [d, ESC Od nothing /# Left #/
841 ESC OE, ESC [e, ESC Oe, nothing /# Right #/
842 ESC OA, ESC [a, ESC Oa, nothing /# Up #/
843 ESC OB, ESC [b, ESC Ob, nothing /# Down #/
844 ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/
845 ESC [5~, local window, ESC [5^, nothing /# Page Up #/
846 ESC [6~, local window, ESC [6^, nothing /# Page Down #/
847 ESC [8~, ESC [8$, ESC [8^, nothing /# End #/
848 ESC OD, ESC [d, ESC Od O /# Keypad Left #/
849 ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/
850 ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/
851 ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/
852 ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/
853 ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/
854 ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/
855 ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/
856 11, 11, 11, O /# Keypad 5 #/
858 MSYS Console (term=rxvt, ncurses)
859 ==============================
860 normal shift ctrl alt
861 KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/
862 KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/
863 KEY_UP, 518, 519, nothing /# Up #/
864 KEY_DOWN, 511, 512, nothing /# Down #/
865 KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/
866 KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/
867 KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/
868 KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/
869 KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/
870 KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/
871 KEY_UP, 518, 519, O /# Keypad Up #/
872 KEY_DOWN, 511, 512, O /# Keypad Down #/
873 KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/
874 KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/
875 KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/
876 KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/
877 11, 11, 11, O /# Keypad 5 #/
879 Win32 Console (raw, pdcurses)
880 DJGPP Console (raw, pdcurses)
881 ==============================
882 normal shift ctrl alt
883 260, 391, 443, 493 /# Left #/
884 261, 400, 444, 492 /# Right #/
885 259, 547, 480, 490 /# Up #/
886 258, 548, 481, 491 /# Down #/
887 262, 388, 447, 524 /# Home #/
888 339, 396, 445, 526 /# Page Up #/
889 338, 394, 446, 520 /# Page Down #/
890 358, 384, 448, 518 /# End #/
891 452, 52('4'), 511, 521 /# Keypad Left #/
892 454, 54('6'), 513, 523 /# Keypad Right #/
893 450, 56('8'), 515, 525 /# Keypad Up #/
894 456, 50('2'), 509, 519 /# Keypad Down #/
895 449, 55('7'), 514, 524 /# Keypad Home #/
896 451, 57('9'), 516, 526 /# Keypad PgUp #/
897 457, 51('3'), 510, 520 /# Keypad PgDn #/
898 455, 49('1'), 508, 518 /# Keypad End #/
899 453, 53('5'), 512, 522 /# Keypad 5 #/
901 Win32 Console (pdcurses, MSVC/MingW32)
902 DJGPP Console (pdcurses)
903 ==============================
904 normal shift ctrl alt
905 KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/
906 KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/
907 KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/
908 KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/
909 KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/
910 KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/
911 KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/
912 KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/
913 KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/
914 KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/
915 KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/
916 KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/
917 KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/
918 KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/
919 KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/
920 KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/
921 KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/
924 ==============================
925 normal shift ctrl alt
926 ESC [D, ESC [D, ESC [D, ESC [D /# Left #/
927 ESC [C, ESC [C, ESC [C, ESC [C /# Right #/
928 ESC [A, ESC [A, ESC [A, ESC [A /# Up #/
929 ESC [B, ESC [B, ESC [B, ESC [B /# Down #/
930 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
931 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/
932 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/
933 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
934 ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/
935 ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/
936 ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/
937 ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/
938 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
939 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/
940 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/
941 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/
942 nothing, nothing, nothing, nothing /# Keypad 5 #/
944 Windows Telnet (term=xterm)
945 ==============================
946 normal shift ctrl alt
947 KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/
948 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/
949 KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/
950 KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/
951 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
952 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/
953 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/
954 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
955 KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/
956 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/
957 KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/
958 KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/
959 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
960 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/
961 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/
962 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
963 ESC [-71, nothing, nothing, O /# Keypad 5 #/
966 ==============================
967 normal shift ctrl alt
968 ESC [D, ESC [D, ESC OD, ESC [D /# Left #/
969 ESC [C, ESC [C, ESC OC, ESC [C /# Right #/
970 ESC [A, ESC [A, ESC OA, ESC [A /# Up #/
971 ESC [B, ESC [B, ESC OB, ESC [B /# Down #/
972 ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/
973 ESC [5~, local win, local win, ESC [5~ /# Page Up #/
974 ESC [6~, local win, local win, ESC [6~ /# Page Down #/
975 ESC [4~, ESC [4~, local win, ESC [4~ /# End #/
976 ESC [D, ESC [D, ESC [D, O /# Keypad Left #/
977 ESC [C, ESC [C, ESC [C, O /# Keypad Right #/
978 ESC [A, ESC [A, ESC [A, O /# Keypad Up #/
979 ESC [B, ESC [B, ESC [B, O /# Keypad Down #/
980 ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/
981 ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/
982 ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/
983 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
984 nothing, nothing, nothing, O /# Keypad 5 #/
987 ==============================
988 normal shift ctrl alt
989 KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/
990 KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/
991 KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/
992 KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/
993 ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/
994 KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/
995 KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/
996 ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/
997 ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/
998 ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/
999 ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/
1000 ESC Or, ESC Or, ESC Or, O /# Keypad Down #/
1001 ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/
1002 ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/
1003 ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/
1004 ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/
1005 ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/
1014 md_readchar(WINDOW
*win
)
1018 int mode
= M_NORMAL
;
1019 int mode2
= M_NORMAL
;
1025 if (ch
== ERR
) /* timed out waiting for valid sequence */
1026 { /* flush input so far and start over */
1034 if (mode
== M_TRAIL
)
1036 if (ch
== '^') /* msys console : 7,5,6,8: modified*/
1037 ch
= MOD_MOVE( toupper(lastch
) );
1039 if (ch
== '~') /* cygwin console: 1,5,6,4: normal */
1040 ch
= tolower(lastch
); /* windows telnet: 1,5,6,4: normal */
1041 /* msys console : 7,5,6,8: normal */
1043 if (mode2
== M_ESC
) /* cygwin console: 1,5,6,4: modified*/
1044 ch
= MOD_MOVE( toupper(ch
) );
1057 if ((ch
== 'F') || (ch
== 'O') || (ch
== '['))
1066 /* Cygwin Console */
1068 case KEY_LEFT
: ch
= MOD_MOVE('H'); break;
1069 case KEY_RIGHT
: ch
= MOD_MOVE('L'); break;
1070 case KEY_UP
: ch
= MOD_MOVE('K'); break;
1071 case KEY_DOWN
: ch
= MOD_MOVE('J'); break;
1072 case KEY_HOME
: ch
= MOD_MOVE('Y'); break;
1073 case KEY_PPAGE
: ch
= MOD_MOVE('U'); break;
1074 case KEY_NPAGE
: ch
= MOD_MOVE('N'); break;
1075 case KEY_END
: ch
= MOD_MOVE('B'); break;
1083 if (mode
== M_KEYPAD
)
1087 /* ESC F - Interix Console codes */
1088 case '^': ch
= MOD_MOVE('H'); break; /* Shift-Left */
1089 case '$': ch
= MOD_MOVE('L'); break; /* Shift-Right */
1091 /* ESC [ - Interix Console codes */
1092 case 'H': ch
= 'y'; break; /* Home */
1093 case 1: ch
= MOD_MOVE('K'); break; /* Ctl-Keypad Up */
1094 case 2: ch
= MOD_MOVE('J'); break; /* Ctl-Keypad Down */
1095 case 3: ch
= MOD_MOVE('L'); break; /* Ctl-Keypad Right */
1096 case 4: ch
= MOD_MOVE('H'); break; /* Ctl-Keypad Left */
1097 case 263: ch
= MOD_MOVE('Y'); break; /* Ctl-Keypad Home */
1098 case 19: ch
= MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */
1099 case 20: ch
= MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */
1100 case 21: ch
= MOD_MOVE('B'); break; /* Ctl-Keypad End */
1102 /* ESC [ - Cygwin Console codes */
1103 case 'G': ch
= '.'; break; /* Keypad 5 */
1104 case '7': lastch
= 'Y'; mode
=M_TRAIL
; break; /* Ctl-Home */
1105 case '5': lastch
= 'U'; mode
=M_TRAIL
; break; /* Ctl-PgUp */
1106 case '6': lastch
= 'N'; mode
=M_TRAIL
; break; /* Ctl-PgDn */
1108 /* ESC [ - Win32 Telnet, PuTTY */
1109 case '1': lastch
= 'y'; mode
=M_TRAIL
; break; /* Home */
1110 case '4': lastch
= 'b'; mode
=M_TRAIL
; break; /* End */
1113 case 'D': ch
= MOD_MOVE('H'); break;
1114 case 'C': ch
= MOD_MOVE('L'); break;
1115 case 'A': ch
= MOD_MOVE('K'); break;
1116 case 'B': ch
= MOD_MOVE('J'); break;
1117 case 't': ch
= 'h'; break;
1118 case 'v': ch
= 'l'; break;
1119 case 'x': ch
= 'k'; break;
1120 case 'r': ch
= 'j'; break;
1121 case 'w': ch
= 'y'; break;
1122 case 'y': ch
= 'u'; break;
1123 case 's': ch
= 'n'; break;
1124 case 'q': ch
= 'b'; break;
1125 case 'u': ch
= '.'; break;
1128 if (mode
!= M_KEYPAD
)
1141 case KEY_LEFT
: ch
= 'h'; break;
1142 case KEY_DOWN
: ch
= 'j'; break;
1143 case KEY_UP
: ch
= 'k'; break;
1144 case KEY_RIGHT
: ch
= 'l'; break;
1145 case KEY_HOME
: ch
= 'y'; break;
1146 case KEY_PPAGE
: ch
= 'u'; break;
1147 case KEY_END
: ch
= 'b'; break;
1149 case KEY_LL
: ch
= 'b'; break;
1151 case KEY_NPAGE
: ch
= 'n'; break;
1154 case KEY_B1
: ch
= 'h'; break;
1155 case KEY_C2
: ch
= 'j'; break;
1156 case KEY_A2
: ch
= 'k'; break;
1157 case KEY_B3
: ch
= 'l'; break;
1159 case KEY_A1
: ch
= 'y'; break;
1160 case KEY_A3
: ch
= 'u'; break;
1161 case KEY_C1
: ch
= 'b'; break;
1162 case KEY_C3
: ch
= 'n'; break;
1163 /* next should be '.', but for problem with putty/linux */
1164 case KEY_B2
: ch
= 'u'; break;
1167 case KEY_SRIGHT
: ch
= MOD_MOVE('L'); break;
1168 case KEY_SLEFT
: ch
= MOD_MOVE('H'); break;
1170 case KEY_SUP
: ch
= MOD_MOVE('K'); break;
1171 case KEY_SDOWN
: ch
= MOD_MOVE('J'); break;
1173 case KEY_SHOME
: ch
= MOD_MOVE('Y'); break;
1174 case KEY_SPREVIOUS
:ch
= MOD_MOVE('U'); break;
1175 case KEY_SEND
: ch
= MOD_MOVE('B'); break;
1176 case KEY_SNEXT
: ch
= MOD_MOVE('N'); break;
1178 case 0x146 : ch
= MOD_MOVE('K'); break; /* Shift-Up */
1179 case 0x145 : ch
= MOD_MOVE('J'); break; /* Shift-Down */
1182 case CTL_RIGHT
: ch
= MOD_MOVE('L'); break;
1183 case CTL_LEFT
: ch
= MOD_MOVE('H'); break;
1184 case CTL_UP
: ch
= MOD_MOVE('K'); break;
1185 case CTL_DOWN
: ch
= MOD_MOVE('J'); break;
1186 case CTL_HOME
: ch
= MOD_MOVE('Y'); break;
1187 case CTL_PGUP
: ch
= MOD_MOVE('U'); break;
1188 case CTL_END
: ch
= MOD_MOVE('B'); break;
1189 case CTL_PGDN
: ch
= MOD_MOVE('N'); break;
1192 case KEY_EOL
: ch
= MOD_MOVE('B'); break;
1196 /* MSYS rxvt console */
1197 case 511 : ch
= MOD_MOVE('J'); break; /* Shift Dn */
1198 case 512 : ch
= MOD_MOVE('J'); break; /* Ctl Down */
1199 case 514 : ch
= MOD_MOVE('H'); break; /* Ctl Left */
1200 case 516 : ch
= MOD_MOVE('L'); break; /* Ctl Right*/
1201 case 518 : ch
= MOD_MOVE('K'); break; /* Shift Up */
1202 case 519 : ch
= MOD_MOVE('K'); break; /* Ctl Up */
1206 case CTL_PAD1
: ch
= MOD_MOVE('B'); break;
1207 case CTL_PAD2
: ch
= MOD_MOVE('J'); break;
1208 case CTL_PAD3
: ch
= MOD_MOVE('N'); break;
1209 case CTL_PAD4
: ch
= MOD_MOVE('H'); break;
1210 case CTL_PAD5
: ch
= '.'; break;
1211 case CTL_PAD6
: ch
= MOD_MOVE('L'); break;
1212 case CTL_PAD7
: ch
= MOD_MOVE('Y'); break;
1213 case CTL_PAD8
: ch
= MOD_MOVE('K'); break;
1214 case CTL_PAD9
: ch
= MOD_MOVE('U'); break;
1218 case ALT_RIGHT
: ch
= MOD_MOVE('L'); break;
1219 case ALT_LEFT
: ch
= MOD_MOVE('H'); break;
1220 case ALT_DOWN
: ch
= MOD_MOVE('J'); break;
1221 case ALT_HOME
: ch
= MOD_MOVE('Y'); break;
1222 case ALT_PGUP
: ch
= MOD_MOVE('U'); break;
1223 case ALT_END
: ch
= MOD_MOVE('B'); break;
1224 case ALT_PGDN
: ch
= MOD_MOVE('N'); break;
1228 case ALT_PAD1
: ch
= MOD_MOVE('B'); break;
1229 case ALT_PAD2
: ch
= MOD_MOVE('J'); break;
1230 case ALT_PAD3
: ch
= MOD_MOVE('N'); break;
1231 case ALT_PAD4
: ch
= MOD_MOVE('H'); break;
1232 case ALT_PAD5
: ch
= '.'; break;
1233 case ALT_PAD6
: ch
= MOD_MOVE('L'); break;
1234 case ALT_PAD7
: ch
= MOD_MOVE('Y'); break;
1235 case ALT_PAD8
: ch
= MOD_MOVE('K'); break;
1236 case ALT_PAD9
: ch
= MOD_MOVE('U'); break;
1243 nocbreak(); /* disable halfdelay mode if on */