1 /* winstuff.c - windows interface routines for xlisp */
2 /* Written by Chris Tchou. */
3 /* This file contains the stuff that the other xlisp files call directly. */
4 
5 #include "windows.h"
6 #include <stdio.h>
7 //#include <QuickDraw.h>	/* for Random */
8 #include <memory.h>		/* for DisposPtr */
9 #include <string.h>
10 //#include <SegLoad.h>	/* for ExitToShell */
11 #include "xlisp.h"
12 #include "textio.h"
13 
14 #if OSC
15 #include "sliders.h" /* define sliders */
16 #include "sound.h" /* define nosc_enabled */
17 #endif
18 #include "falloc.h" /* define table_memory */
19 
20 const char os_pathchar = '\\';
21 const char os_sepchar = ',';
22 
23 
24 /* externals */
25 extern FILE *tfp;  /* transcript file pointer */
26 extern int cursorPos;
27 extern char *macgets (void);
28 
29 #define LBSIZE 200
30 
31 /* local variables */
32 static char lbuf[LBSIZE];
33 static int lpos[LBSIZE];
34 static int lindex;
35 static int lcount = 0;
36 static int lposition;
37 static int line_edit = TRUE;
38 
39 //int isascii (char c) { return 1; }  /* every char is an ascii char, isn't it? */
40 
osinit(const char * banner)41 void osinit(const char *banner) {
42 //	int i;
43     char version[] = "\nWindows console interface by Roger Dannenberg.\n";
44 //	InitMac ();  /* initialize the mac interface routines */
45 //	lposition = 0;  /* initialize the line editor */
46 //	for (i = 0; banner[i] != '\0'; i++) macputc (banner[i]);
47 //	for (i = 0; version[i] != '\0'; i++) macputc (version[i]);
48     nyquist_printf(banner);
49     nyquist_printf(version);
50 }
51 
52 
osaopen(const char * name,const char * mode)53 FILE *osaopen (const char *name, const char *mode) {
54     FILE *fp = NULL;
55     if (ok_to_open(name, mode))
56         fp = fopen (name, mode);
57     return fp;
58 }
59 
osbopen(const char * name,const char * mode)60 FILE *osbopen (const char *name, const char *mode) {
61     FILE *fp = NULL;
62     char nmode[4];
63     strcpy (nmode, mode); strcat (nmode, "b");
64     if (ok_to_open(name, mode))
65         fp = fopen (name, mode);
66     return fp;
67 }
68 
osclose(FILE * fp)69 int osclose (FILE *fp) { return (fclose (fp)); }
osaputc(int ch,FILE * fp)70 int osaputc (int ch, FILE *fp) { return (putc (ch, fp)); }
osbputc(int ch,FILE * fp)71 int osbputc (int ch, FILE *fp) { return (putc (ch, fp)); }
osoutflush(FILE * fp)72 void osoutflush(FILE *fp) { fflush(fp); }
73 
74 /* osagetc - get a character from an ascii file */
osagetc(fp)75 int osagetc(fp)
76   FILE *fp;
77 {
78     return (getc(fp));
79 }
80 
81 
82 extern int abort_flag;
83 
84 
85 #define OLDGETC
86 #ifdef OLDGETC
87 
ostgetc(void)88 int ostgetc (void) {
89 /*	int i;
90 
91     if (numChars <= 0) {  /* get some more */
92 /*		if (linebuf) DisposPtr (linebuf);
93         linebuf = macgets ();
94         i = 0;
95         while (linebuf[i] != '\0') i++;
96         numChars = i;
97         if (tfp) for (i = 0; i < numChars; i++) osaputc (linebuf[i], tfp);
98         lineptr = linebuf;
99     }
100     numChars--;
101     if (*lineptr == '\r') {
102         lineptr++;
103         return '\n';
104     } else return (*lineptr++);*/
105 
106     int ch = ggetchar();
107     oscheck(); /* in case user typed ^C */
108     if (ch == BREAK_CHAR && abort_flag == BREAK_LEVEL) {
109         abort_flag = 0;
110     }
111     return ch;
112 }
113 
114 #else
115 
end_of_line_edit()116 void end_of_line_edit()
117 {
118     line_edit = FALSE;
119     if (tfp) {
120     for (lindex = 0; lindex < lcount; ++lindex)
121         osaputc(lbuf[lindex], tfp);
122     }
123     lindex = 0;
124 }
125 
126 
127 
ostgetc()128 int ostgetc()
129 {
130 /*
131  * NOTE: lbuf[] accumulates characters as they are typed
132  *   lpos[] is the column position of the characters
133  *   lcount is the number of characters in lbuf
134  *   lposition is current position
135  *   lindex is index of next char to output
136  *   line_edit is true iff we're inputing characters
137  *
138  */
139     int ch;
140 
141     while (line_edit) {
142         ch = ggetchar();
143         oscheck(); /* in case user typed ^C */
144             if (ch == BREAK_CHAR && abort_flag == BREAK_LEVEL) {
145                 abort_flag = 0;
146             }
147         /* assume for now we should add the character */
148         lbuf[lcount] = ch;
149         lpos[lcount] = lposition;
150         lcount++;
151         lposition++;
152 
153         /* now do all the special character processing */
154         switch (ch) {
155           case '\n':
156             lposition = 0;
157             end_of_line_edit();
158             gputchar('\r');
159             gputchar(ch);
160             break;
161           /* delete key generates: 1b, 5b, 33, 7E
162                  which is: ESC, [, 3, ~ */
163           case '\010':	/* backspace */
164           case '\177':	/* delete */
165             lcount--; /* take out backspace or delete char */
166             lposition--;
167             if (lcount) {
168             lcount--;
169             while (lposition > lpos[lcount]) {
170                       gputchar('\010');
171                       gputchar(' ');
172                       gputchar('\010');
173                 lposition--;
174             }
175             }
176             break;
177           case '\025': /* control-u */
178             lcount--;
179             lposition--;
180             if (lcount) {
181                 while (lposition > lpos[0]) {
182                       gputchar('\010');
183                       gputchar(' ');
184                       gputchar('\010');
185                 lposition--;
186             }
187             lcount = 0;
188             }
189             break;
190 
191               /* note that control-z never reaches here */
192               case '\003':	/* control-c */
193             xltoplevel();
194             lcount = 0;
195             break;
196               case '\007':	/* control-g */
197             xlcleanup();
198             lcount = 0;
199             break;
200               case '\020':	/* control-p */
201             xlcontinue();
202             lcount = 0;
203             break;
204           case '\002':
205             ostputc('\n');	/* control-b */
206             xlbreak("BREAK",s_unbound);
207             break;
208           case '\024':	/* control-t */
209             xinfo();
210             lcount = 0;
211             break;
212           case '\t':	/* TAB */
213             lposition--; /* undo the increment above */
214             do {
215             lposition++;
216                     gputchar(' ');
217             } while (lposition & 7);
218             break;
219           default:
220             gputchar(ch);
221             break;
222         }
223     }
224     if (lindex + 1 >= lcount) {
225         lcount = 0;
226         line_edit = TRUE;
227     }
228     ch = lbuf[lindex++];
229     /* printf("[%c]", ch); */
230     fflush(stdout);
231     return ch;
232 }
233 #endif
234 
235 
ostputc(int ch)236 void ostputc (int ch) {
237 //	macputc (ch);
238     gputchar(ch);			// console
239 
240     if (tfp) osaputc (ch, tfp);
241 }
242 
ostoutflush()243 void ostoutflush()
244 {
245     if (tfp) fflush(tfp);
246     /* since ostputc calls gputchar which just calls putchar,
247        I'm going to flush stdout rather than extending the
248        "g" abstraction with a gflush() call. -RBD
249      */
250     fflush(stdout);
251 }
252 
osflush(void)253 void osflush (void) {
254     lindex = lcount = lposition = 0;
255     line_edit = TRUE;
256 }
257 
258 extern int abort_flag;
259 
oscheck(void)260 void oscheck (void)
261 {
262 
263 #if OSC
264     if (nosc_enabled) nosc_poll();
265 #endif
266 
267     check_aborted();
268     if (abort_flag == ABORT_LEVEL) {
269         abort_flag = 0;
270         osflush();
271         xltoplevel();
272     } else if (abort_flag == BREAK_LEVEL) {
273         abort_flag = 0;
274         osflush();
275         xlbreak("BREAK",s_unbound);
276     }
277     run_time++;
278     if (run_time % 30 == 0) {
279         // maybe we should call fflush here like in Unix; I'm not sure if this is
280 	// a bug or it is not necessary for Windows - RBD
281         if (run_time_limit > 0 && run_time > run_time_limit) {
282             xlfatal("Run time limit exceeded");
283         }
284 	if (memory_limit > 0 &&
285 	    npools * MAXPOOLSIZE + table_memory + total >
286 	    memory_limit * 1000000) {
287             xlfatal("Memory limit exceeded");
288 	}
289     }
290 }
291 
oserror(const char * msg)292 void oserror(const char *msg) {
293     char line[100], *p;
294     sprintf (line,"error: %s\n",msg);
295     for (p = line; *p != '\0'; ++p) ostputc (*p);
296 }
297 
osfinish(void)298 void osfinish(void) {
299     portaudio_exit();
300     /* dispose of everything... */
301 //	if (linebuf) DisposPtr (linebuf);
302 //	MacWrapUp ();
303 //	ExitToShell ();
304 }
305 
renamebackup(char * filename)306 int renamebackup (char *filename) { return 0; }
307 
308 
309 
310 static WIN32_FIND_DATA FindFileData;
311 static HANDLE hFind = INVALID_HANDLE_VALUE;
312 #define OSDIR_LIST_READY 0
313 #define OSDIR_LIST_STARTED 1
314 #define OSDIR_LIST_DONE 2
315 static osdir_list_status = OSDIR_LIST_READY;
316 #define OSDIR_MAX_PATH 256
317 static char osdir_path[OSDIR_MAX_PATH];
318 
319 // osdir_list_start -- prepare to list a directory
osdir_list_start(const char * path)320 int osdir_list_start(const char *path)
321 {
322     if (strlen(path) >= OSDIR_MAX_PATH - 2) {
323         xlcerror("LISTDIR path too big", "return nil", NULL);
324         return FALSE;
325     }
326     if (!ok_to_open(path, "r")) return FALSE;
327     strcpy(osdir_path, path);
328     strcat(osdir_path, "/*"); // make a pattern to match all files
329     if (osdir_list_status != OSDIR_LIST_READY) {
330         osdir_list_finish(); // close previously interrupted listing
331     }
332     hFind = FindFirstFile(osdir_path, &FindFileData); // get the "."
333     if (hFind == INVALID_HANDLE_VALUE) return FALSE;
334     if (FindNextFile(hFind, &FindFileData) == 0) return FALSE; // get the ".."
335     osdir_list_status = OSDIR_LIST_STARTED;
336     return TRUE;
337 }
338 
339 
osdir_list_next()340 const char *osdir_list_next()
341 {
342     if (FindNextFile(hFind, &FindFileData) == 0) {
343         osdir_list_status = OSDIR_LIST_DONE;
344         return NULL;
345     }
346     return FindFileData.cFileName;
347 }
348 
osdir_list_finish()349 void osdir_list_finish()
350 {
351     if (osdir_list_status != OSDIR_LIST_READY) {
352         FindClose(hFind);
353     }
354     osdir_list_status = OSDIR_LIST_READY;
355 }
356 
357 
358 /* xechoenabled -- set/clear echo_enabled flag (unix only) */
xechoenabled()359 LVAL xechoenabled()
360 {
361 	int flag = (xlgetarg() != NULL);
362     xllastarg();
363 	// echo_enabled = flag; -- do nothing in Windows
364 	return NULL;
365 }
366 
367