1 /*
2 * io.c -- melt input/output
3 * Copyright (C) 2002-2015 Meltytech, LLC
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 /* System header files */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #ifndef _WIN32
30 #include <termios.h>
31 #else
32 // MinGW defines struct timespec in pthread.h
33 #include <pthread.h>
34 // for nanosleep()
35 #include <framework/mlt_types.h>
36 #include <windows.h>
37 #endif
38 #include <unistd.h>
39 #include <sys/time.h>
40
41 /* Application header files */
42 #include "io.h"
43
chomp(char * input)44 char *chomp( char *input )
45 {
46 if ( input != NULL )
47 {
48 int length = strlen( input );
49 if ( length && input[ length - 1 ] == '\n' )
50 input[ length - 1 ] = '\0';
51 if ( length > 1 && input[ length - 2 ] == '\r' )
52 input[ length - 2 ] = '\0';
53 }
54 return input;
55 }
56
trim(char * input)57 char *trim( char *input )
58 {
59 if ( input != NULL )
60 {
61 int length = strlen( input );
62 int first = 0;
63 while( first < length && isspace( input[ first ] ) )
64 first ++;
65 memmove( input, input + first, length - first + 1 );
66 length = length - first;
67 while ( length > 0 && isspace( input[ length - 1 ] ) )
68 input[ -- length ] = '\0';
69 }
70 return input;
71 }
72
strip_quotes(char * input)73 char *strip_quotes( char *input )
74 {
75 if ( input != NULL )
76 {
77 char *ptr = strrchr( input, '\"' );
78 if ( ptr != NULL )
79 *ptr = '\0';
80 if ( input[ 0 ] == '\"' )
81 strcpy( input, input + 1 );
82 }
83 return input;
84 }
85
get_int(int * output,int use)86 int *get_int( int *output, int use )
87 {
88 int *value = NULL;
89 char temp[ 132 ];
90 *output = use;
91 if ( trim( chomp( fgets( temp, 132, stdin ) ) ) != NULL )
92 {
93 if ( strcmp( temp, "" ) )
94 *output = atoi( temp );
95 value = output;
96 }
97 return value;
98 }
99
100 /** This stores the previous settings
101 */
102
103 #ifndef _WIN32
104 static struct termios oldtty;
105 #else
106 static DWORD oldtty;
107 #endif
108 static int mode = 0;
109
110 /** This is called automatically on application exit to restore the
111 previous tty settings.
112 */
113
term_exit(void)114 void term_exit(void)
115 {
116 if ( mode == 1 )
117 {
118 #ifndef _WIN32
119 tcsetattr( 0, TCSANOW, &oldtty );
120 #else
121 HANDLE h = GetStdHandle( STD_INPUT_HANDLE );
122 if (h) {
123 SetConsoleMode( h, oldtty );
124 }
125 #endif
126 mode = 0;
127 }
128 }
129
130 /** Init terminal so that we can grab keys without blocking.
131 */
132
term_init()133 void term_init( )
134 {
135 #ifndef _WIN32
136 struct termios tty;
137
138 tcgetattr( 0, &tty );
139 oldtty = tty;
140
141 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
142 tty.c_oflag |= OPOST;
143 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
144 tty.c_cflag &= ~(CSIZE|PARENB);
145 tty.c_cflag |= CS8;
146 tty.c_cc[ VMIN ] = 1;
147 tty.c_cc[ VTIME ] = 0;
148
149 tcsetattr( 0, TCSANOW, &tty );
150 #else
151 HANDLE h = GetStdHandle( STD_INPUT_HANDLE );
152 if (h) {
153 DWORD tty;
154 GetConsoleMode( h, &tty );
155 oldtty = tty;
156 SetConsoleMode( h, mode & ~( ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT ) );
157 }
158 #endif
159
160 mode = 1;
161
162 atexit( term_exit );
163 }
164
165 /** Check for a keypress without blocking infinitely.
166 Returns: ASCII value of keypress or -1 if no keypress detected.
167 */
168
term_read()169 int term_read( )
170 {
171 #ifndef _WIN32
172 int n = 1;
173 unsigned char ch;
174 struct timeval tv;
175 fd_set rfds;
176
177 FD_ZERO( &rfds );
178 FD_SET( 0, &rfds );
179 tv.tv_sec = 0;
180 tv.tv_usec = 40000;
181 n = select( 1, &rfds, NULL, NULL, &tv );
182 if (n > 0)
183 {
184 n = read( 0, &ch, 1 );
185 tcflush( 0, TCIFLUSH );
186 if (n == 1)
187 return ch;
188 return n;
189 }
190 #else
191 HANDLE h = GetStdHandle( STD_INPUT_HANDLE );
192 if ( h && WaitForSingleObject( h, 0 ) == WAIT_OBJECT_0 )
193 {
194 DWORD count;
195 TCHAR c = 0;
196 ReadConsole( h, &c, 1, &count, NULL );
197 return (int) c;
198 } else {
199 struct timespec tm = { 0, 40000000 };
200 nanosleep( &tm, NULL );
201 return 0;
202 }
203 #endif
204 return -1;
205 }
206
get_keypress()207 char get_keypress( )
208 {
209 char value = '\0';
210 int pressed = 0;
211
212 fflush( stdout );
213
214 term_init( );
215 while ( ( pressed = term_read( ) ) == -1 ) ;
216 term_exit( );
217
218 value = (char)pressed;
219
220 return value;
221 }
222
wait_for_any_key(char * message)223 void wait_for_any_key( char *message )
224 {
225 if ( message == NULL )
226 printf( "Press any key to continue: " );
227 else
228 printf( "%s", message );
229
230 get_keypress( );
231
232 printf( "\n\n" );
233 }
234
beep()235 void beep( )
236 {
237 printf( "%c", 7 );
238 fflush( stdout );
239 }
240