1 | //////////////////////////////////////////////////////////////////////
|
2 | //
|
3 | // Time-stamp: "28.12.09 09:34 getch.cpp klaus?wachtler.de"
|
4 | //
|
5 | // der folgende Teil kann komplett fuer sich als Ersatz von
|
6 | // Sleep(), _kbhit() und _getch() verwendet werden, wie es unter
|
7 | // NT oder allen DOS-C-Compilern verwendet wird.
|
8 | //
|
9 |
|
10 | #include <sys/time.h>
|
11 | #include <sys/types.h>
|
12 | #include <termios.h>
|
13 | #include <unistd.h>
|
14 | #include <stdio.h>
|
15 | #include <stdlib.h>
|
16 |
|
17 | #include "getch.h"
|
18 |
|
19 |
|
20 | /* Sleep() wartet die angegebene Anzahl Millisekunden (im Gegensatz
|
21 | * zu ANSI-sleep(), das kennt nur ganze Sekunden).
|
22 | */
|
23 |
|
24 | #ifdef __cplusplus
|
25 | extern "C"
|
26 | #endif
|
27 | void Sleep( int msec )
|
28 | {
|
29 | struct timeval
|
30 | timeout;
|
31 |
|
32 | timeout.tv_sec = msec/1000;
|
33 | timeout.tv_usec = msec%1000;
|
34 |
|
35 | select( 0, NULL, NULL, NULL, &timeout );
|
36 | }
|
37 |
|
38 | // In einer struct termios wird eine Terminalkonfiguration
|
39 | // gespeichert.
|
40 | // Davon brauchen wir zwei: eine fuer den Originalzustand,
|
41 | // und eine zum aendern.
|
42 | static struct termios term_neu,
|
43 | term_original;
|
44 |
|
45 | // Darin wird die Aenderung der Terminaleinstellungen gemerkt,
|
46 | // damit sie nur einmal stattfinden:
|
47 | static int _conio_initialisiert = 0;
|
48 |
|
49 | // Bei Programmende soll automatisch die Originalkonfiguration
|
50 | // wiederhergestellt werden:
|
51 | static void _exit_conio( void )
|
52 | {
|
53 | if( _conio_initialisiert )
|
54 | {
|
55 | tcsetattr( 0, TCSANOW, &term_original );
|
56 | _conio_initialisiert = 0;
|
57 | }
|
58 | }
|
59 |
|
60 | // Diese Funktion macht beim ersten Aufruf folgendes:
|
61 | // - Merken der Originalkonfiguration von stdin (file id=0)
|
62 | // - Installieren von _exit_conio() mit atexit()
|
63 | // Bei jedem Aufruf zudem:
|
64 | // - Ausschalten von ECHO und ICANON (u.a. Zeilenpufferung)
|
65 | #ifdef __cplusplus
|
66 | extern "C"
|
67 | #endif
|
68 | void _init_conio( void )
|
69 | {
|
70 | if( !_conio_initialisiert )
|
71 | {
|
72 | // Dies passiert nur beim ersten Aufruf
|
73 |
|
74 | // Originalkonfiguration holen:
|
75 | tcgetattr( 0, &term_original ); // 0 ist stdin
|
76 | // komplett kopieren:
|
77 | term_neu = term_original;
|
78 | // ICANON und ECHO ausschalten:
|
79 | term_neu.c_lflag = term_neu.c_lflag & ~(ICANON | ECHO);
|
80 | // Bei Programmende wieder aufraeumen lassen:
|
81 | atexit( _exit_conio );
|
82 | // In _conio_initialisiert merken, dass wir schon etwas getan
|
83 | // haben:
|
84 | _conio_initialisiert++;
|
85 | }
|
86 |
|
87 | // bei jedem Aufruf die eigene Terminalkonfiguration
|
88 | // fuer stdin (file id = 0) passend setzen:
|
89 | tcsetattr( 0, TCSANOW, &term_neu );
|
90 | }
|
91 |
|
92 | // _kbhit() liefert true, wenn mindestens ein Zeichen im
|
93 | // Tastaturpuffer steht
|
94 | #ifdef __cplusplus
|
95 | extern "C"
|
96 | #endif
|
97 | int _kbhit( void )
|
98 | {
|
99 | fd_set
|
100 | lesen_set;
|
101 |
|
102 | struct timeval
|
103 | timeout;
|
104 |
|
105 | _init_conio();
|
106 |
|
107 | FD_ZERO( &lesen_set );
|
108 | FD_SET( 0, &lesen_set ); // 0 ist std-Eingabe
|
109 |
|
110 | timeout.tv_sec = 0;
|
111 | timeout.tv_usec = 0;
|
112 |
|
113 | if( select( 1,
|
114 | &lesen_set, // set fuer "Lesen"
|
115 | NULL, // kein set fuer "Schreiben"
|
116 | NULL, // kein set fuer "out of band data"
|
117 | &timeout
|
118 | )
|
119 | ==-1
|
120 | )
|
121 | {
|
122 | // select macht Bloedsinn!
|
123 | return 0;
|
124 | }
|
125 | else
|
126 | {
|
127 | // in lesen_set steht jetzt an der Stelle [0], ob gelesen
|
128 | // werden kann:
|
129 | return FD_ISSET( 0, &lesen_set );
|
130 | }
|
131 | }
|
132 |
|
133 | // liefert ein Zeichen von der Tastatur (oder EOF bei Fehler)
|
134 | #ifdef __cplusplus
|
135 | extern "C"
|
136 | #endif
|
137 | int _getch( void )
|
138 | {
|
139 | char c;
|
140 |
|
141 | _init_conio();
|
142 |
|
143 | return ( read( 0, &c, 1 )==1 ) ? (int)(unsigned char)c : EOF;
|
144 | }
|
145 | //
|
146 | // Ende von Sleep(), _kbhit(), und _getch() fuer __unix__.
|
147 | //
|
148 | //////////////////////////////////////////////////////////////////////
|