1 /*	SCCS Id: @(#)tos.c	3.1	90/14/08
2 /* NetHack may be freely redistributed.  See license for details. */
3 
4 /*
5  *  TOS system functions.
6  */
7 
8 #define NEED_VARARGS
9 #include "hack.h"
10 
11 #ifdef TTY_GRAPHICS
12 # include "tcap.h"
13 #else
14 /* To avoid error for tos.c; will be removed later */
15 static char *nh_HE="\033q";
16 #endif
17 
18 #ifdef TOS
19 
20 # include <osbind.h>
21 # ifndef WORD
22 #  define WORD short		/* 16 bits -- redefine if necessary */
23 # endif
24 
25 #include <ctype.h>
26 
27 static char NDECL(DOSgetch);
28 static char NDECL(BIOSgetch);
29 static void NDECL(init_aline);
30 char *_a_line;			/* for Line A variables */
31 # ifdef TEXTCOLOR
32 boolean colors_changed = FALSE;
33 # endif
34 
35 int
tgetch()36 tgetch()
37 {
38 	char ch;
39 
40 	/* BIOSgetch can use the numeric key pad on IBM compatibles. */
41 	if (iflags.BIOS)
42 		ch = BIOSgetch();
43 	else
44 		ch = DOSgetch();
45 	return ((ch == '\r') ? '\n' : ch);
46 }
47 
48 /*
49  *  Keyboard translation tables.
50  */
51 #define KEYPADLO	0x61
52 #define KEYPADHI	0x71
53 
54 #define PADKEYS 	(KEYPADHI - KEYPADLO + 1)
55 #define iskeypad(x)	(KEYPADLO <= (x) && (x) <= KEYPADHI)
56 
57 /*
58  * Keypad keys are translated to the normal values below.
59  * When iflags.BIOS is active, shifted keypad keys are translated to the
60  *    shift values below.
61  */
62 static const struct pad {
63 	char normal, shift, cntrl;
64 } keypad[PADKEYS] = {
65 			{C('['), 'Q', C('[')},		/* UNDO */
66 			{'?', '/', '?'},		/* HELP */
67 			{'(', 'a', '('},		/* ( */
68 			{')', 'w', ')'},		/* ) */
69 			{'/', '/', '/'},		/* / */
70 			{C('p'), '$', C('p')},		/* * */
71 			{'y', 'Y', C('y')},		/* 7 */
72 			{'k', 'K', C('k')},		/* 8 */
73 			{'u', 'U', C('u')},		/* 9 */
74 			{'h', 'H', C('h')},		/* 4 */
75 			{'.', '.', '.'},
76 			{'l', 'L', C('l')},		/* 6 */
77 			{'b', 'B', C('b')},		/* 1 */
78 			{'j', 'J', C('j')},		/* 2 */
79 			{'n', 'N', C('n')},		/* 3 */
80 			{'i', 'I', C('i')},		/* Ins */
81 			{'.', ':', ':'}			/* Del */
82 }, numpad[PADKEYS] = {
83 			{C('['), 'Q', C('[')}	,	/* UNDO */
84 			{'?', '/', '?'},		/* HELP */
85 			{'(', 'a', '('},		/* ( */
86 			{')', 'w', ')'},		/* ) */
87 			{'/', '/', '/'},		/* / */
88 			{C('p'), '$', C('p')},		/* * */
89 			{'7', M('7'), '7'},		/* 7 */
90 			{'8', M('8'), '8'},		/* 8 */
91 			{'9', M('9'), '9'},		/* 9 */
92 			{'4', M('4'), '4'},		/* 4 */
93 			{'.', '.', '.'},		/* 5 */
94 			{'6', M('6'), '6'},		/* 6 */
95 			{'1', M('1'), '1'},		/* 1 */
96 			{'2', M('2'), '2'},		/* 2 */
97 			{'3', M('3'), '3'},		/* 3 */
98 			{'i', 'I', C('i')},		/* Ins */
99 			{'.', ':', ':'}			/* Del */
100 };
101 
102 /*
103  * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
104  * meaning unless assigned one by a keyboard conversion table, so the
105  * keyboard BIOS normally does not return a character code when Alt-letter
106  * is pressed.	So, to interpret unassigned Alt-letters, we must use a
107  * scan code table to translate the scan code into a letter, then set the
108  * "meta" bit for it.  -3.
109  */
110 #define SCANLO		0x10
111 
112 static const char scanmap[] = { 	/* ... */
113 	'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
114 	0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
115 	0, '\\', 'z','x','c','v','b','N','m',',','.','?' 	/* ... */
116 };
117 
118 #define inmap(x)	(SCANLO <= (x) && (x) < SCANLO + SIZE(scanmap))
119 
120 /*
121  * BIOSgetch gets keys directly with a BIOS call.
122  */
123 #define SHIFT		(0x1 | 0x2)
124 #define CTRL		0x4
125 #define ALT		0x8
126 
127 static char
BIOSgetch()128 BIOSgetch()
129 {
130 	unsigned char scan, shift, ch;
131 	const struct pad *kpad;
132 
133 	long  x;
134 
135 	/* Get scan code.
136 	 */
137 	x = Crawcin();
138 	ch = x & 0x0ff;
139 	scan = (x & 0x00ff0000L) >> 16;
140 	/* Get shift status.
141 	 */
142 	shift = Kbshift(-1);
143 
144 	/* Translate keypad keys */
145 	if (iskeypad(scan)) {
146 		kpad = iflags.num_pad ? numpad : keypad;
147 		if (shift & SHIFT)
148 			ch = kpad[scan - KEYPADLO].shift;
149 		else if (shift & CTRL)
150 			ch = kpad[scan - KEYPADLO].cntrl;
151 		else
152 			ch = kpad[scan - KEYPADLO].normal;
153 	}
154 	/* Translate unassigned Alt-letters */
155 	if ((shift & ALT) && !ch) {
156 		if (inmap(scan))
157 			ch = scanmap[scan - SCANLO];
158 		return (isprint(ch) ? M(ch) : ch);
159 	}
160 	return ch;
161 }
162 
163 static char
DOSgetch()164 DOSgetch()
165 {
166 	return (Crawcin() & 0x007f);
167 }
168 
169 
170 long
freediskspace(path)171 freediskspace(path)
172 char *path;
173 {
174 	int drive = 0;
175 	struct {
176 		long freal; /*free allocation units*/
177 		long total; /*total number of allocation units*/
178 		long bps;   /*bytes per sector*/
179 		long pspal; /*physical sectors per allocation unit*/
180 	} freespace;
181 	if (path[0] && path[1] == ':')
182 		drive = (toupper(path[0]) - 'A') + 1;
183 	if (Dfree(&freespace,drive)<0) return -1;
184 	return freespace.freal*freespace.bps*freespace.pspal;
185 }
186 
187 /*
188  * Functions to get filenames using wildcards
189  */
190 int
findfirst(path)191 findfirst(path)
192 char *path;
193 {
194 	return (Fsfirst(path, 0) == 0);
195 }
196 
197 int
findnext()198 findnext()
199 {
200 	return (Fsnext() == 0);
201 }
202 
203 char *
foundfile_buffer()204 foundfile_buffer()
205 {
206 	return (char *)Fgetdta() + 30;
207 }
208 
209 long
filesize(file)210 filesize(file)
211 char *file;
212 {
213 	if (findfirst(file))
214 		return  (* (long *) ((char *)Fgetdta() + 26));
215 	else
216 		return -1L;
217 }
218 
219 /*
220  * Chdrive() changes the default drive.
221  */
222 void
chdrive(str)223 chdrive(str)
224 char *str;
225 {
226 	char *ptr;
227 	char drive;
228 
229 	if ((ptr = index(str, ':')) != (char *)0) {
230 		drive = toupper(*(ptr - 1));
231 		(void)Dsetdrv(drive - 'A');
232 	}
233 	return;
234 }
235 
236 
237 void
get_scr_size()238 get_scr_size()
239 {
240 # ifdef MINT
241 #  include <ioctl.h>
242 	struct winsize win;
243 	char *tmp;
244 
245 	if((tmp=nh_getenv("LINES")))
246 		LI = atoi(tmp);
247 	else if((tmp=nh_getenv("ROWS")))
248 		LI = atoi(tmp);
249 	if(tmp && (tmp=nh_getenv("COLUMNS")))
250 		CO = atoi(tmp);
251 	else {
252 	    ioctl(0,TIOCGWINSZ, &win);
253 	    LI = win.ws_row;
254 	    CO = win.ws_col;
255 	}
256 # else
257 	init_aline();
258 	LI = (*((WORD  *)(_a_line + -42L))) + 1;
259 	CO = (*((WORD  *)(_a_line + -44L))) + 1;
260 # endif
261 }
262 
263 # define BIGBUF  8192
264 
265 int
_copyfile(from,to)266 _copyfile(from, to)
267 char *from, *to;
268 {
269 	int fromfd, tofd, r;
270 	char *buf;
271 
272 	if ((fromfd = open(from, O_RDONLY|O_BINARY, 0)) < 0)
273 		return -1;
274 	if ((tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, FCMASK)) < 0)
275 		return -1;
276 	buf = (char *)alloc((size_t)BIGBUF);
277 	while ( (r = read(fromfd, buf, BIGBUF)) > 0)
278 		write(tofd, buf, r);
279 	close(fromfd);
280 	close(tofd);
281 	free(buf);
282 	return 0;	/* successful */
283 }
284 
kbhit()285 int kbhit()
286 {
287 	return Cconis();
288 }
289 
290 static void
init_aline()291 init_aline()
292 {
293 # ifdef __GNUC__
294 /* line A calls nuke registers d0-d2,a0-a2; not all compilers regard these
295    as scratch registers, though, so we save them
296  */
297 	asm(" moveml d0-d2/a0-a2, sp@-");
298 	asm(" .word 0xa000; movel d0, __a_line");
299 	asm(" moveml sp@+, d0-d2/a0-a2");
300 # else
301 	asm(" movem.l d0-d2/a0-a2, -(sp)");
302 	asm(" .dc.w 0xa000");	/* tweak as necessary for your compiler */
303 	asm(" move.l d0, __a_line");
304 	asm(" movem.l (sp)+, d0-d2/a0-a2");
305 # endif
306 }
307 
308 # ifdef TEXTCOLOR
309 /* used in termcap.c to decide how to set up the hilites */
310 unsigned long tos_numcolors = 2;
311 
312 void
set_colors()313 set_colors()
314 {
315 	static char colorHE[] = "\033q\033b0";
316 
317 	if (!iflags.BIOS)
318 		return;
319 	init_aline();
320 	tos_numcolors = 1 << (((unsigned char *) _a_line)[1]);
321 	if (tos_numcolors <= 2) {			/* mono */
322 		iflags.use_color = FALSE;
323 		return;
324 	} else {
325 		colors_changed = TRUE;
326 		nh_HE = colorHE;
327 	}
328 }
329 
330 void
restore_colors()331 restore_colors()
332 {
333 	static char plainHE[] = "\033q";
334 
335 	if (colors_changed)
336 		nh_HE = plainHE;
337 	colors_changed = FALSE;
338 }
339 # endif /* TEXTCOLOR */
340 
341 # ifdef SUSPEND
342 
343 #include	<signal.h>
344 
345 #   ifdef MINT
346 extern int __mint;
347 #   endif
348 
349 int
dosuspend()350 dosuspend() {
351 #   ifdef MINT
352 	extern int kill();
353 	if (__mint == 0) {
354 #   endif
355 		pline("Sorry, it seems we have no SIGTSTP here.  Try ! or S.");
356 #   ifdef MINT
357 	}
358 	else if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) {
359 		suspend_nhwindows((char *)0);
360 		(void) signal(SIGTSTP, SIG_DFL);
361 		(void) kill(0, SIGTSTP);
362 		get_scr_size();
363 		resume_nhwindows();
364 	} else {
365 		pline("I don't think your shell has job control.");
366 	}
367 #   endif /* MINT */
368 	return(0);
369 }
370 # endif /* SUSPEND */
371 
372 #endif /* TOS */
373