1 /*
2 Copyright (C) 2004-2017,2018 John E. Davis
3
4 This file is part of the S-Lang Library.
5
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The S-Lang Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 */
21
22 #include "slinclud.h"
23
24 #include "slang.h"
25 #include "_slang.h"
26
27 #define INCL_BASE
28 #define INCL_NOPM
29 #define INCL_VIO
30 #define INCL_KBD
31 #define INCL_DOS
32 #if 0
33 # define INCL_DOSSEMAPHORES
34 #endif
35 #ifdef LONG
36 #undef LONG
37 #endif
38 #ifdef VOID
39 #undef VOID
40 #endif
41 #include <os2.h>
42
43 #include <signal.h>
44 #include <process.h>
45
46 static TID SLos2_threadID = (TID) 0;
47
48 KBDINFO initialKbdInfo; /* keyboard info */
49
50 /* Code to read keystrokes in a separate thread */
51
52 typedef struct kbdcodes {
53 UCHAR ascii;
54 UCHAR scan;
55 /* USHORT shift; */
56 } KBDCODES;
57
58 #define BUFFER_LEN 4096
59 static KBDCODES threadKeys[BUFFER_LEN];
60 static int atEnd = 0;
61 static int startBuf;
62 static int endBuf;
63
64 /* Original code used semaphores to control access to threadKeys.
65 * It is expected that the semaphore code will be deleted after 0.97.
66 */
67 #if 0
68
69 #ifdef __os2_16__
70
71 typedef USHORT APIRET;
72 static HSEM Hmtx;
73
74 #define DosRequestMutexSem(hmtx,timeout) DosSemRequest(hmtx,timeout)
75 #define DosReleaseMutexSem(hmtx) DosSemClear(hmtx)
76 #define DosCloseMutexSem(hmtx) DosCloseSem(hmtx)
77
78 #else /* !defined(__os2_16__) */
79
80 static HMTX Hmtx; /* Mutex Semaphore */
81
82 #endif
83
84 static APIRET CreateSem(void)
85 {
86 #ifdef __os2_16__
87 char SemName[32];
88 sprintf(SemName, "\\SEM\\jed\\%u", getpid());
89 return ( DosCreateSem (0, &Hmtx, SemName) );
90 #else
91 return ( DosCreateMutexSem (NULL, &Hmtx, 0, 0) );
92 #endif
93 }
94
95 static APIRET RequestSem(void)
96 {
97 return ( DosRequestMutexSem (Hmtx, -1) );
98 }
99
100 static APIRET ReleaseSem(void)
101 {
102 return ( DosReleaseMutexSem (Hmtx) );
103 }
104
105 static APIRET CloseSem(void)
106 {
107 return( DosCloseMutexSem (Hmtx) );
108 }
109
110 #else
111
112 #define CreateSem()
113 #define RequestSem()
114 #define ReleaseSem()
115 #define CloseSem()
116
117 #endif
118
set_kbd(void)119 static void set_kbd(void)
120 {
121 KBDINFO kbdInfo;
122
123 kbdInfo = initialKbdInfo;
124 kbdInfo.fsMask &= ~0x0001; /* not echo on */
125 kbdInfo.fsMask |= 0x0002; /* echo off */
126 kbdInfo.fsMask &= ~0x0008; /* cooked mode off */
127 kbdInfo.fsMask |= 0x0004; /* raw mode */
128 kbdInfo.fsMask &= ~0x0100; /* shift report off */
129 KbdSetStatus(&kbdInfo, 0);
130 }
131
thread_getkey()132 static void thread_getkey ()
133 {
134 KBDKEYINFO keyInfo;
135 int n;
136
137 while (!atEnd) { /* at end is a flag */
138 set_kbd();
139 KbdCharIn(&keyInfo, IO_NOWAIT, 0); /* get a character */
140 if (keyInfo.fbStatus & 0x040) { /* found a char process it */
141 if (keyInfo.chChar == SLang_Abort_Char) {
142 if (SLang_Ignore_User_Abort == 0) SLang_set_error (SL_USER_BREAK);
143 SLKeyBoard_Quit = 1;
144 }
145 n = (endBuf + 1) % BUFFER_LEN;
146 if (n == startBuf) {
147 DosBeep (500, 20);
148 KbdFlushBuffer(0);
149 continue;
150 }
151 RequestSem();
152 threadKeys [n].ascii = keyInfo.chChar;
153 threadKeys [n].scan = keyInfo.chScan;
154 /* threadKeys [n].shift = keyInfo.fsState; */
155 endBuf = n;
156 ReleaseSem();
157 } else /* no char available*/
158 DosSleep (20);
159 }
160 }
161
thread_code(void * Args)162 static void thread_code (void *Args)
163 {
164 (void) Args;
165 startBuf = -1; /* initialize the buffer pointers */
166 endBuf = -1;
167 thread_getkey ();
168 atEnd = 0; /* reset the flag */
169 _endthread();
170 }
171
172 /* The code below is in the main thread */
173
SLang_init_tty(int abort_char,int dum2,int dum3)174 int SLang_init_tty(int abort_char, int dum2, int dum3)
175 {
176 VIOCURSORINFO cursorInfo, OldcursorInfo;
177
178 (void) dum2; (void) dum3;
179 if (abort_char == -1) abort_char = 3; /* ^C */
180 SLang_Abort_Char = abort_char;
181 SLKeyBoard_Quit = 0;
182
183 /* set ^C off */
184 signal (SIGINT, SIG_IGN);
185 signal (SIGBREAK, SIG_IGN);
186
187 /* set up the keyboard */
188
189 initialKbdInfo.cb = sizeof(initialKbdInfo);
190 KbdGetStatus(&initialKbdInfo, 0);
191 set_kbd();
192
193 /* open a semaphore */
194 CreateSem();
195
196 /* start a separate thread to read the keyboard */
197 #if defined(__BORLANDC__)
198 SLos2_threadID = _beginthread (thread_code, 8096, NULL);
199 #else
200 SLos2_threadID = _beginthread (thread_code, NULL, 8096, NULL);
201 #endif
202
203 if ((int)SLos2_threadID == -1)
204 {
205 SLang_exit_error ("init_tty: Error starting keyboard thread.");
206 }
207
208 VioGetCurType (&OldcursorInfo, 0);
209 cursorInfo.yStart = 1;
210 cursorInfo.cEnd = 15;
211 cursorInfo.cx = 1;
212 cursorInfo.attr = 1;
213 if (VioSetCurType (&cursorInfo, 0))
214 VioSetCurType (&OldcursorInfo, 0); /* reset to previous value */
215
216 return 0;
217 }
218
SLang_reset_tty(void)219 void SLang_reset_tty (void)
220 {
221 if (0 == SLos2_threadID) return;
222 atEnd = 1; /* set flag and wait until thread ends */
223 while (atEnd) {DosSleep (0);}
224
225 CloseSem();
226
227 /* close the keyboard */
228 KbdSetStatus(&initialKbdInfo, 0); /* restore original state */
229 SLos2_threadID = 0;
230 }
231
232 #define keyWaiting() (endBuf != startBuf)
233
234 /* sleep for *tsecs tenths of a sec waiting for input */
235
_pSLsys_input_pending(int tsecs)236 int _pSLsys_input_pending(int tsecs)
237 {
238 if (keyWaiting()) return 1;
239
240 /* Convert tsecs to units of 20 ms */
241 tsecs = tsecs * 5;
242
243 /* If tsecs is less than 0, it represents millisecs */
244 if (tsecs < 0)
245 tsecs = -tsecs / 100;
246
247 while (tsecs > 0)
248 {
249 DosSleep(20); /* 20 ms or 1/50 sec */
250 if (keyWaiting()) break;
251 tsecs--;
252 }
253 return (tsecs);
254 }
255
_pSLsys_getkey()256 unsigned int _pSLsys_getkey ()
257 {
258 unsigned int c;
259 unsigned char scan;
260
261
262 if (!keyWaiting())
263 {
264 int tsecs = 300;
265 while (!_pSLsys_input_pending(tsecs))
266 ;
267 }
268
269 /* read codes from buffer */
270 RequestSem();
271 startBuf = (startBuf + 1) % BUFFER_LEN;
272 c = threadKeys [startBuf].ascii;
273 scan = threadKeys [startBuf].scan;
274 ReleaseSem();
275
276 switch (c)
277 {
278 case 8:
279 if (scan == 0x0E) c = 127;
280 break;
281
282 case 0xE0:
283 case 0:
284 c = _pSLpc_convert_scancode (scan, 0, 1);
285 break;
286
287 default:
288 break;
289 }
290 return (c);
291 }
292
SLang_set_abort_signal(void (* dum)(int))293 int SLang_set_abort_signal (void (*dum)(int))
294 {
295 (void) dum;
296 return 0;
297 }
298
SLtt_set_mouse_mode(int mode,int force)299 int SLtt_set_mouse_mode (int mode, int force)
300 {
301 /* FIXME: Priority=low */
302 (void) mode;
303 (void) force;
304
305 return -1;
306 }
307