mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-07 23:51:14 +02:00
------------------------------------------------------------------------ r331 | rbd | 2020-10-13 12:40:12 -0500 (Tue, 13 Oct 2020) | 2 lines Also forgot to install NyquistWords.txt ------------------------------------------------------------------------ r330 | rbd | 2020-10-13 12:34:06 -0500 (Tue, 13 Oct 2020) | 2 lines Forgot to move nyquistman.pdf from docsrc/s2h to release ------------------------------------------------------------------------ r329 | rbd | 2020-10-13 11:32:33 -0500 (Tue, 13 Oct 2020) | 2 lines Updated some version numbers for 3.16. ------------------------------------------------------------------------ r328 | rbd | 2020-10-13 11:20:52 -0500 (Tue, 13 Oct 2020) | 2 lines Fixed NyquistIDE antialiasing for plot text, fix format of message. ------------------------------------------------------------------------ r327 | rbd | 2020-10-12 21:01:53 -0500 (Mon, 12 Oct 2020) | 2 lines Fixed a couple of format problems in manual. This version of Nyquist has been tested wtih macOS, Linux, 32&64-bit Windows. ------------------------------------------------------------------------ r326 | rbd | 2020-10-12 20:21:38 -0500 (Mon, 12 Oct 2020) | 1 line Modified WIN32 32-bit XLisp to use 64-bit FIXNUMs. This allows XLisp and Nyquist to handle big sounds even on 32-bit machines. Probably at some cost, but inner loops are mostly float and int32, and the Nyquist release is 64-bit anyway. Maybe we'll have to run some benchmarks on Audacity, which is still 32-bit on Windows. ------------------------------------------------------------------------ r325 | rbd | 2020-10-12 13:16:57 -0500 (Mon, 12 Oct 2020) | 1 line Win64 passes bigfiletest.lsp now. This version should work on all 64-bit systems now. These changes untested on Linux and macOS. ------------------------------------------------------------------------ r324 | rbd | 2020-10-11 21:31:53 -0500 (Sun, 11 Oct 2020) | 2 lines I couldn't free enough space on my linux box, so I adjusted the bigfiletest to write 8-bit ulaw. It's still >4GB and >4G samples. Works on Linux. ------------------------------------------------------------------------ r323 | rbd | 2020-10-11 19:41:25 -0500 (Sun, 11 Oct 2020) | 2 lines Missing file from last commit. ------------------------------------------------------------------------ r322 | rbd | 2020-10-11 19:36:08 -0500 (Sun, 11 Oct 2020) | 1 line Found another case where WIN64 needs int64_t instead of long for sample count. ------------------------------------------------------------------------ r321 | rbd | 2020-10-11 19:33:25 -0500 (Sun, 11 Oct 2020) | 3 lines Fixed s-save to handle optional and keyword parameters (which should never have been mixed in the first place). Documentation cleanup - should be final for this version. ------------------------------------------------------------------------ r320 | rbd | 2020-10-11 14:44:37 -0500 (Sun, 11 Oct 2020) | 2 lines Fixes to handle IRCAM sound format and tests for big file io working on macOS. ------------------------------------------------------------------------ r319 | rbd | 2020-10-10 21:31:58 -0500 (Sat, 10 Oct 2020) | 2 lines Changes for linux and to avoid compiler warnings on linux. ------------------------------------------------------------------------ r318 | rbd | 2020-10-10 20:50:23 -0500 (Sat, 10 Oct 2020) | 1 line This is the test used for Win64 version. ------------------------------------------------------------------------ r317 | rbd | 2020-10-10 20:34:34 -0500 (Sat, 10 Oct 2020) | 1 line This version works on Win64. Need to test changes on macOS and linux. ------------------------------------------------------------------------ r316 | rbd | 2020-10-10 19:59:15 -0500 (Sat, 10 Oct 2020) | 2 lines PWL changes to avoid compiler warning. ------------------------------------------------------------------------ r315 | rbd | 2020-10-10 19:34:04 -0500 (Sat, 10 Oct 2020) | 2 lines A few more changes for 64-bit sample counts on Win64 ------------------------------------------------------------------------ r314 | rbd | 2020-10-10 13:19:42 -0500 (Sat, 10 Oct 2020) | 2 lines Fixed int64_t declaration in gate.alg ------------------------------------------------------------------------ r313 | rbd | 2020-10-10 12:07:40 -0500 (Sat, 10 Oct 2020) | 2 lines Fixes to gate for long sounds ------------------------------------------------------------------------ r312 | rbd | 2020-10-10 11:47:29 -0500 (Sat, 10 Oct 2020) | 2 lines Fixed sound_save types for intgen ------------------------------------------------------------------------ r311 | rbd | 2020-10-10 11:09:01 -0500 (Sat, 10 Oct 2020) | 2 lines Fixed a 64-bit sample count problem in siosc.alg ------------------------------------------------------------------------ r310 | rbd | 2020-10-10 11:03:12 -0500 (Sat, 10 Oct 2020) | 2 lines Fixed sndmax to handle 64-bit sample counts. ------------------------------------------------------------------------ r309 | rbd | 2020-10-10 10:57:04 -0500 (Sat, 10 Oct 2020) | 2 lines Forgot to re-translate all tran/*.alg files with fix for int64 cast to int32. This version compiles on macOS and ready for test on Win64. ------------------------------------------------------------------------ r308 | rbd | 2020-10-10 10:16:05 -0500 (Sat, 10 Oct 2020) | 2 lines Everything seems to compile and run on macOS now. Moving changes to Windows for test. ------------------------------------------------------------------------ r307 | rbd | 2020-10-10 09:23:45 -0500 (Sat, 10 Oct 2020) | 1 line Added casts to avoid compiler warnings and to review changes to support 64-bit sample counts on Windows. Still not complete, and waiting to regenerate and compile tran directory code after updates to translation code that will insert more casts. ------------------------------------------------------------------------ r306 | rbd | 2020-10-09 21:55:15 -0500 (Fri, 09 Oct 2020) | 2 lines Rebuilt seqfnint.c from header files. ------------------------------------------------------------------------ r305 | rbd | 2020-10-09 21:53:33 -0500 (Fri, 09 Oct 2020) | 1 line Changed some FIXNUMS to LONG to avoid compiler warnings in seqfnint.c ------------------------------------------------------------------------ r304 | rbd | 2020-10-09 21:44:03 -0500 (Fri, 09 Oct 2020) | 2 lines I discovered forgotten regression-test.lsp and added test that requires 64-bit sample counts to pass. Fixed a few bugs revealed by running the type-checking regression tests. ------------------------------------------------------------------------ r303 | rbd | 2020-10-09 12:28:58 -0500 (Fri, 09 Oct 2020) | 2 lines Changes for 64-bit sample counts broke mult-channel s-save. Fixed in the commit for macOS. ------------------------------------------------------------------------ r302 | rbd | 2020-10-09 10:03:39 -0500 (Fri, 09 Oct 2020) | 2 lines Changed snd-play to return samples computed and used that to make a test for computing long sounds that would overflow 32-bit length counts. ------------------------------------------------------------------------ r301 | rbd | 2020-10-09 09:11:26 -0500 (Fri, 09 Oct 2020) | 2 lines corrected mistake in delaycv.alg and re-translated ------------------------------------------------------------------------ r300 | rbd | 2020-10-09 09:09:06 -0500 (Fri, 09 Oct 2020) | 2 lines Fix to delaycv.alg -- "s" changed to "input" to avoid matching "s" in "sample_type". ------------------------------------------------------------------------ r299 | rbd | 2020-10-09 09:03:33 -0500 (Fri, 09 Oct 2020) | 4 lines To avoid compiler warnings, XLisp interfaces to C int and long are now specified as LONG rather than FIXNUM, and the stubs that call the C functions cast FIXNUMs from XLisp into longs before calling C functions. ------------------------------------------------------------------------ r298 | rbd | 2020-10-08 22:20:26 -0500 (Thu, 08 Oct 2020) | 2 lines This commit has many more fixes to handle long (64-bit) sounds, including a lot of fixes for warnings by Visual Studio assigning int64_t to long (works on macOS, doesn't work on VS). This was compiled and tested on macOS, and even computed a 27.1-hour sound using OSC, LP, SUM and MULT (haven't tested I/O yet). ------------------------------------------------------------------------ r297 | rbd | 2020-10-07 13:04:02 -0500 (Wed, 07 Oct 2020) | 2 lines This is a major cleanup. It started with the goal of changing long to int64_t for sample counts so that on 64-bit windows, where long is only 32-bits, the sample counts would nevertheless be 64-bit allowing long sounds, which was a limitation for long recordings in Audacity. Since I was using compiler warnings to track possible loss-of-precision conversions from 64-bit sample counts, and there were *many* warnings, I started cleaning up *all* the warnings and ended up with a very large set of changes, including "modernizing" C declarations that date back to XLisp and CMU MIDI Toolkit code and were never changed. This version runs all the examples.sal code on macOS, but will surely have problems on Windows and Linux given the number of changes. ------------------------------------------------------------------------ r296 | rbd | 2020-10-06 13:34:20 -0500 (Tue, 06 Oct 2020) | 2 lines More changes from long to int64_t for sample counts. ------------------------------------------------------------------------ r295 | rbd | 2020-10-06 11:53:49 -0500 (Tue, 06 Oct 2020) | 2 lines More work on using 64-bit sample counts. Changed MAX_STOP from 32-bit to 64-bit limit. ------------------------------------------------------------------------ r294 | rbd | 2020-10-06 11:48:05 -0500 (Tue, 06 Oct 2020) | 2 lines Made some changes so that sample counts are int64_t (for windows) instead of long to support sample counts above 31 bits. ------------------------------------------------------------------------ r293 | rbd | 2020-10-04 21:30:55 -0500 (Sun, 04 Oct 2020) | 2 lines Fixed a few minor things for Linux and tested on Linux. ------------------------------------------------------------------------ r292 | rbd | 2020-10-04 21:00:28 -0500 (Sun, 04 Oct 2020) | 2 lines Update extensions: all are minor changes. ------------------------------------------------------------------------ r291 | rbd | 2020-09-24 13:59:31 -0500 (Thu, 24 Sep 2020) | 2 lines New implementation of seq and seqrep, added get-real-time, documented get-real-time, fixed examples.sal and examples.lsp which are now in lib rather than extensions (so they are now back in the basic installation), other cleanup. ------------------------------------------------------------------------ r290 | rbd | 2020-08-16 16:24:52 -0500 (Sun, 16 Aug 2020) | 2 lines Fixed bug in snd-gate, revised GATE and NOISE-GATE to handle multi-channel sound. RMS now handles multi-channel input. S-AVG added to take multichannel input (but not used, because RMS could not be written without making SND-SRATE convert multichannel sound to vector of floats. That seems to be going toward a fully vectorized model. Not going there for now. ------------------------------------------------------------------------ r289 | rbd | 2020-07-09 16:27:45 -0500 (Thu, 09 Jul 2020) | 2 lines Added GET-REAL-TIME function to XLISP. May not work yet on Windows. Various fixes for compiler warnings. I noticed FLAC doesn't work (I guess it never did) and I cannot figure out how this even links because flac_min seems to be undefined. Something to look at later.
1294 lines
36 KiB
C
1294 lines
36 KiB
C
/* userio.c -- handy user interface functions */
|
||
/* Copyright 1989 Carnegie Mellon University */
|
||
|
||
/*****************************************************************************
|
||
* Change Log
|
||
* Date | Change
|
||
*-----------+-----------------------------------------------------------------
|
||
* 21-May-86 | Created
|
||
* 11-Aug-87 | F.H: Added clear_abort(), stop()
|
||
* May-88 | JCD : AMIGA VERSION
|
||
* 11-Jun-88 | RBD: disable printing of GDEBUG messages
|
||
* 12-Oct-88 | JCD : EXCLUSIVE AMIGA VERSION
|
||
* 13-Apr-89 | JCD : New portable version.
|
||
* 5-Apr | JDW : Further changes
|
||
* 2-Mar-92 | GWL : Little changes to satisfy compiler
|
||
* 19-Nov-92 | JDZ : Mach tty io threads
|
||
* 28-Apr-03 | DM : portability changes. true->TRUE, false->FALSE
|
||
*****************************************************************************/
|
||
|
||
/* Notes on ascii input:
|
||
|
||
Input is complicated because different systems have varying input models,
|
||
especially with regard to handling ^C. The CMT model handles ^C and ^G as
|
||
special characters, and these do not cause software interrupts. Also, the
|
||
lowest level of the CMT model does not support line editing: Every character
|
||
is acted upon immediately. This has two implications:
|
||
(1) CMT must "read ahead" looking for ^C and ^G characters. This is handled
|
||
by the check_aborted() procedure, which reads characters into the
|
||
type_ahead[] array.
|
||
(2) CMT must do its own line editing. This is handled by the ggets() routine.
|
||
|
||
A number of functions support ascii input, only some of which are visible
|
||
to the application programmer. Let's start at the top-level and work down;
|
||
each of the following calls the routine below it:
|
||
|
||
ggets() - gets a string with line editing support. This function is fairly
|
||
machine independent, except for some backspace-and-erase control character
|
||
code sequences.
|
||
|
||
ggetchar() - gets a raw character. This function calls wait_ascii()
|
||
and echoes it. Note that it may return ABORT_CHAR or BREAK_CHAR.
|
||
|
||
wait_ascii() - gets a raw character without echo and without character
|
||
code translation. wait_ascii() either polls get_ascii() or uses some
|
||
kind of system-dependent event waiting. Returns ABORT_CHAR or BREAK_CHAR
|
||
immediately if abort_flag has been set, regardless of whether there is
|
||
new ascii input.
|
||
|
||
get_ascii() - checks to see if a character is available. (Using
|
||
check_aborted().)
|
||
The only dependency here is on the Amiga, we restart input when buffer goes
|
||
from full to non-full.
|
||
|
||
check_aborted() - looks for input by calling ascii_input. If found,
|
||
put the input into the type_ahead[] buffer. Returns abort_flag.
|
||
|
||
ascii_input() - lowest level of input; just gets a character if there is
|
||
one. Does conversion from RETURN (\r) to EOL (\n). The Amiga handles
|
||
this in-line directly in check_aborted().
|
||
|
||
Here's a quick summary:
|
||
|
||
ggets = ggetchar + line editing & string building
|
||
ggetchar = wait_ascii + character echo
|
||
wait_ascii = get_ascii + wait for character
|
||
get_ascii = check_aborted + pull char from buffer
|
||
check_aborted = ascii_input + test for ^C,^G + put in buffer
|
||
ascii_input = poll for char + CR->EOL conversion
|
||
|
||
*/
|
||
|
||
#include "switches.h"
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#if HAS_STDLIB_H
|
||
#include <stdlib.h> /* normal case */
|
||
#endif
|
||
|
||
|
||
#ifdef MACINTOSH
|
||
# include "StandardFile.h"
|
||
/* added for ThinkC 7 */
|
||
# ifdef THINK_C
|
||
# include <pascal.h>
|
||
# endif
|
||
#endif
|
||
|
||
#ifdef AMIGA
|
||
|
||
# ifdef AZTEC
|
||
# include "functions.h"
|
||
# else /* LATTICE */
|
||
# include "amiga.h"
|
||
# include "stdarg.h"
|
||
# endif
|
||
|
||
# include "intuition/intuition.h"
|
||
# include "devices/console.h"
|
||
#endif
|
||
|
||
#include "ctype.h"
|
||
#include "stdio.h"
|
||
#include "cext.h"
|
||
#include "userio.h"
|
||
|
||
#ifdef MICROSOFT
|
||
#include "signal.h"
|
||
#endif
|
||
|
||
#ifdef UNIX_MACH
|
||
#include <varargs.h>
|
||
#include <midistruct.h>
|
||
extern char a_in;
|
||
extern int a_in_flag;
|
||
extern int i_am_running;
|
||
#ifdef RTMach
|
||
extern itc_mutex_t a_mutex;
|
||
extern itc_condition_t a_cond, a_in_cond;
|
||
#define A_LOCK() itc_mutex_lock(&a_mutex)
|
||
#define A_UNLOCK() itc_mutex_unlock(&a_mutex)
|
||
#else /* RTMach */
|
||
extern struct mutex a_mutex;
|
||
extern struct condition a_cond, a_in_cond;
|
||
#define A_LOCK() mutex_lock(&a_mutex)
|
||
#define A_UNLOCK() mutex_unlock(&a_mutex)
|
||
#endif /* RTMach */
|
||
#endif
|
||
|
||
#ifdef DOTS_FOR_ARGS
|
||
#include <stdarg.h>
|
||
#endif
|
||
|
||
#ifdef UNIX
|
||
#include <sys/param.h>
|
||
#include <sys/resource.h>
|
||
#include "cmtio.h"
|
||
#ifdef _IBMR2
|
||
#define NBBY 8
|
||
#define OPEN_MAX 2000
|
||
#endif
|
||
#include <sys/select.h>
|
||
#endif
|
||
|
||
#ifdef linux
|
||
#include <sys/time.h> /* for FD_ZERO / FD_SET */
|
||
#endif
|
||
|
||
extern int debug;
|
||
|
||
#ifdef NYQUIST
|
||
/* get definitions for stdputstr, etc. */
|
||
#include "xlisp.h"
|
||
#endif
|
||
|
||
|
||
/****************************************************************************
|
||
*
|
||
* routines private to this module
|
||
*
|
||
****************************************************************************/
|
||
|
||
int GetReadFileName(void);
|
||
int GetWriteFileName(void);
|
||
|
||
#ifdef MACINTOSH
|
||
private void PtoC_StrCopy(char *p1, char *p2);
|
||
#endif
|
||
|
||
#ifdef AMIGA
|
||
char ConGetChar();
|
||
ConMayGetChar();
|
||
private void ConRead();
|
||
private void ConPutStr();
|
||
private void ConPutChar();
|
||
UBYTE ascii_signal();
|
||
UBYTE KeybSig();
|
||
#endif
|
||
|
||
|
||
/****************************************************************************
|
||
*
|
||
* variables shared with other modules
|
||
*
|
||
****************************************************************************/
|
||
|
||
public int abort_flag; /* control C or control G equivalent */
|
||
public int redirect_flag; /* check whether the I/O has been redirected--
|
||
Added by Ning Hu Apr.2001*/
|
||
/* extern void musicterm(); */ /*DMH: from macmidi.c, to allow abort_check*/
|
||
public boolean ascii_input(char *c);
|
||
|
||
/****************************************************************************
|
||
*
|
||
* variables private to this module
|
||
*
|
||
****************************************************************************/
|
||
|
||
#ifdef AMIGA
|
||
struct IntuitionBase *IntuitionBase;
|
||
private struct IOStdReq *ConOutReq;
|
||
private struct MsgPort *ConOutPort;
|
||
private struct IOStdReq *ConInReq;
|
||
private struct MsgPort *ConInPort;
|
||
private char KeyBuff[16];
|
||
private struct Window *Window;
|
||
private struct NewWindow NewWindow = {
|
||
0,11,640,189,
|
||
0,1,
|
||
NULL,
|
||
SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH |
|
||
WINDOWSIZING,
|
||
NULL,NULL,
|
||
(STRPTR) "Carnegie Mellon University MIDI Toolkit for Commodore AMIGA",
|
||
NULL,NULL,
|
||
100,25,640,200,
|
||
WBENCHSCREEN };
|
||
#endif
|
||
|
||
#ifdef MACINTOSH
|
||
private OSType io_file_type = 0x3F3F3F3F; /* '????' */
|
||
private OSType io_file_creator = 0x3F3F3F3F; /* '????' */
|
||
#endif
|
||
|
||
#define type_ahead_max 100
|
||
char type_ahead[100];
|
||
int type_ahead_head = 0;
|
||
int type_ahead_tail = 0;
|
||
int type_ahead_count = 0;
|
||
|
||
|
||
#ifdef DOS
|
||
#ifdef BORLAND
|
||
int c_break(void)
|
||
{
|
||
gprintf(TRANS, " BREAK ");
|
||
abort_flag = ABORT_LEVEL;
|
||
return 1; /* non-zero means do not exit program */
|
||
}
|
||
#endif
|
||
#ifdef MICROSOFT
|
||
void c_break(int sig)
|
||
{
|
||
abort_flag = ABORT_LEVEL;
|
||
/* The CTRL+C interrupt must be reset to our handler since
|
||
* by default it is reset to the system handler.
|
||
*/
|
||
signal(SIGINT, c_break); /* assume this succeeds */
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef MACINTOSH
|
||
#ifdef NYQUIST
|
||
void FlushOutput (void);
|
||
#endif
|
||
#endif
|
||
|
||
/* gflush -- flush output produced by gprintf, etc. */
|
||
/**/
|
||
void gflush(void)
|
||
{
|
||
#ifdef MACINTOSH
|
||
#ifdef NYQUIST
|
||
FlushOutput();
|
||
#else
|
||
fflush(stdout); /* make sure any prompts or errors have been output */
|
||
fflush(STDERR);
|
||
#endif /* NYQUIST */
|
||
#endif /* MACINTOSH */
|
||
#ifdef UNIX
|
||
fflush(stdout); /* make sure any prompts or errors have been output */
|
||
fflush(STDERR);
|
||
#endif
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* io_init
|
||
*
|
||
* I added this init function for the AMIGA version.
|
||
*
|
||
* io_init : opens a window
|
||
* and exits if initialisation can not be done properly.
|
||
* registers cleanup calls to carefully deallocate resources.
|
||
*
|
||
* io_init is not amiga specific : the simplest version
|
||
* of io_init could be a clear screen statement for example, and a
|
||
* printf("Good bye !\n") on exit.
|
||
*
|
||
* for the Mac, it seems that ascii_input doesn't work unless getchar() is
|
||
* called first. I assume this is because getchar() initializes the ability
|
||
* of the window to process type-in, so there is probably a way to set this
|
||
* directly. If you figure it out, let me know. -RBD
|
||
*
|
||
*****************************************************************************/
|
||
|
||
void
|
||
io_init()
|
||
{
|
||
|
||
#ifdef AMIGA
|
||
int error;
|
||
|
||
/* Window and console initialisation */
|
||
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",1L);
|
||
if (IntuitionBase == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) CloseLibrary, IntuitionBase);
|
||
|
||
ConOutPort = CreatePort("conoutport", 0L);
|
||
if (ConOutPort == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) DeletePort, ConOutPort);
|
||
|
||
ConOutReq = CreateStdIO(ConOutPort);
|
||
if (ConOutReq == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) DeleteStdIO, ConOutReq);
|
||
|
||
ConInPort = CreatePort("coninport", 0L);
|
||
if (ConInPort == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) DeletePort, ConInPort);
|
||
|
||
ConInReq = CreateStdIO(ConInPort);
|
||
if (ConInReq == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) DeleteStdIO, ConInReq);
|
||
|
||
Window = OpenWindow(&NewWindow);
|
||
if (Window == NULL) EXIT(1);
|
||
cu_register((cu_fn_type) CloseWindow, Window);
|
||
|
||
ConOutReq->io_Data = (APTR)Window;
|
||
ConOutReq->io_Length = sizeof(*Window);
|
||
error = OpenDevice("console.device", 0L, (struct IORequest *) ConOutReq, 0L);
|
||
ConInReq->io_Device = ConOutReq->io_Device;
|
||
ConInReq->io_Unit = ConOutReq->io_Unit;
|
||
if (error != NULL) EXIT(1);
|
||
cu_register((cu_fn_type) CloseDevice, ConOutReq);
|
||
|
||
ConInReq->io_Command = CMD_READ;
|
||
ConInReq->io_Data = (APTR)KeyBuff;
|
||
ConInReq->io_Length = 1;
|
||
SendIO((struct IORequest *) ConInReq);
|
||
#endif
|
||
|
||
#ifdef UNIX
|
||
#ifndef BUFFERED_SYNCHRONOUS_INPUT
|
||
IOsetup(0 /* standard input */);
|
||
cu_register((cu_fn_type) IOcleanup, NULL);
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef MACINTOSH
|
||
#ifndef NYQUIST /* don't need this if we're in Nyquist */
|
||
char s[100];
|
||
printf("Type <return> to start: ");
|
||
fgets(s, 100, stdin);
|
||
#endif /* NYQUIST */
|
||
#endif
|
||
|
||
#ifdef DOS
|
||
#ifdef MICROSOFT
|
||
if (signal(SIGINT, c_break) == SIG_ERR) {
|
||
gprintf(ERROR, "Couldn't set Ctrl C handler\n");
|
||
EXIT(1);
|
||
}
|
||
#else
|
||
#ifdef BORLAND
|
||
ctrlbrk(c_break);
|
||
#else
|
||
... we are in DOS, but neither MICROSOFT nor BORLAND,
|
||
please set up a control C handler here...
|
||
#endif
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
#ifdef MACINTOSH
|
||
|
||
/****************************************************************************
|
||
* abort_check
|
||
* Effect:
|
||
* exit nicely if the aborted flag is set
|
||
****************************************************************************/
|
||
|
||
public void abort_check()
|
||
{
|
||
if (abort_flag) clean_exit();
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* clean_exit
|
||
* Effect:
|
||
* clean up and exit
|
||
****************************************************************************/
|
||
|
||
public void clean_exit()
|
||
{
|
||
gprintf(TRANS, "Exiting...\n");
|
||
EXIT(1);
|
||
}
|
||
|
||
#ifdef MPW
|
||
/****************************************************************************
|
||
* cleanup_abort_handler
|
||
* Effect:
|
||
* shuts down abort watcher
|
||
****************************************************************************/
|
||
|
||
public void cleanup_abort_handler()
|
||
{
|
||
(void) sigset(SIGINT, SIG_DFL); /* deactivate abort watcher */
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* init_abort_handler
|
||
* Effect:
|
||
* starts abort watcher
|
||
* aborted flag is set to FALSE
|
||
****************************************************************************/
|
||
|
||
public void init_abort_handler()
|
||
{
|
||
abort_flag = FALSE;
|
||
(void) sigset(SIGINT, abort_watcher); /* activate abort watcher */
|
||
}
|
||
#endif
|
||
|
||
#endif
|
||
|
||
|
||
/****************************************************************************
|
||
* askbool
|
||
* Inputs:
|
||
* char *prompt: string to prompt for user input
|
||
* int deflt: TRUE or FALSE default
|
||
* Returns:
|
||
* boolean: TRUE or FALSE as entered by user
|
||
* Effect:
|
||
* prompts user for yes or no input, returns result
|
||
****************************************************************************/
|
||
|
||
int askbool(prompt, deflt)
|
||
char *prompt;
|
||
int deflt;
|
||
{
|
||
#define undefined -1
|
||
char defchar; /* the default answer */
|
||
char c; /* user input */
|
||
char in_string[100];
|
||
int result = -1; /* the result: -1 = undefined, 0 = FALSE, 1 = TRUE */
|
||
if (deflt) defchar = 'y';
|
||
else defchar = 'n';
|
||
while (result == undefined) {
|
||
gprintf(TRANS, "%s? [%c]: ", prompt, defchar);
|
||
ggets(in_string);
|
||
c = in_string[0];
|
||
if (islower(c)) c = toupper(c);
|
||
if (c == 'Y') result = TRUE;
|
||
else if (c == 'N') result = FALSE;
|
||
else if (c == EOS) result = deflt;
|
||
else if (abort_flag) result = deflt;
|
||
/* space before Please to separate from user's type-in: */
|
||
else gprintf(TRANS, " Please type Y or N.\n");
|
||
}
|
||
if (abort_flag == BREAK_LEVEL) {
|
||
abort_flag = 0;
|
||
result = deflt;
|
||
gprintf(TRANS, "\n");
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* fileopen
|
||
* Inputs:
|
||
* char *deflt: the default file name (e.g. from command line)
|
||
* char *extension: default extension
|
||
* char *mode: read ("r") or write ("w")
|
||
* char *prompt: prompt for user
|
||
* Returns:
|
||
* opened file pointer
|
||
* Effect:
|
||
* opens file, prompts for user input if necessary and warns about
|
||
* possible confusion. If deflt is a null string or NULL, the user will
|
||
* be prompted for a name. The routine loops until a file is opened.
|
||
* If the mode is "r", a check is made to see if the file exists
|
||
* with and without the extension. If both exist a warning is given.
|
||
* For mode "w", a check is made to see if the file will be overwritten.
|
||
* The extension is automatically added if the default or user-typed
|
||
* file has no "." At the bottom of the loop body, if no file has
|
||
* been opened, the user is prompted for another file name.
|
||
****************************************************************************/
|
||
|
||
char fileopen_name[100]; /* name of the opened file */
|
||
|
||
FILE *fileopen(deflt, extension, mode, prompt)
|
||
char *deflt;
|
||
char *extension; /* default extension */
|
||
char *mode; /* read "r" or write "w" */
|
||
char *prompt; /* prompt for user */
|
||
{
|
||
char extname[100]; /* trial name with extension added */
|
||
FILE *fp = NULL; /* file corresponding to filename */
|
||
FILE *fpext; /* file corresponding to extname */
|
||
char *problem = NULL; /* tells user why he has to try again */
|
||
|
||
if (!deflt) deflt = ""; /* treat NULL as the empty string */
|
||
strcpy(fileopen_name, deflt);
|
||
/* keep trying until a good file is found: */
|
||
while (fp == NULL) {
|
||
/* avoid null file names: */
|
||
while (strlen(fileopen_name) == 0) {
|
||
#ifndef MACINTOSH
|
||
gprintf(TRANS, "%s : ", prompt);
|
||
ggets(fileopen_name);
|
||
if (abort_flag) {
|
||
if (abort_flag == BREAK_LEVEL) {
|
||
abort_flag = 0;
|
||
/* type return since user didn't... */
|
||
gprintf(TRANS, "\n");
|
||
}
|
||
return NULL;
|
||
}
|
||
#else /* use Macintosh file dialog */
|
||
if (mode[0] == 'r') {
|
||
if (!GetReadFileName(fileopen_name)) return NULL;
|
||
} else if (mode[0] == 'w') {
|
||
if (!(GetWriteFileName(fileopen_name, prompt))) return NULL;
|
||
} else {
|
||
gprintf(ERROR, "(fileopen) internal error: bad mode\n");
|
||
}
|
||
#endif /* MACINTOSH */
|
||
}
|
||
if (mode[0] == 'r') {
|
||
strcpy(extname, fileopen_name);
|
||
strcat(extname, ".");
|
||
strcat(extname, extension);
|
||
fp = NULL;
|
||
fpext = NULL;
|
||
if (ok_to_open(fileopen_name, mode)) {
|
||
fp = fopen(fileopen_name, mode);
|
||
}
|
||
if (ok_to_open(extname, mode)) {
|
||
fpext = fopen(extname, mode);
|
||
}
|
||
if (fp != NULL && fpext != NULL) {
|
||
gprintf(TRANS,
|
||
"warning: both %s and %s exist. %s will be used.\n",
|
||
fileopen_name, extname, fileopen_name);
|
||
fclose(fpext);
|
||
} else if (fpext != NULL) {
|
||
fp = fpext;
|
||
strcpy(fileopen_name, extname); /* remember what was opened */
|
||
}
|
||
if (fp == NULL) problem = "Couldn't find %s.\n";
|
||
} else if (mode[0] == 'w') {
|
||
boolean added_extension = FALSE;
|
||
|
||
/* add the extension if there is no '.' in the file name */
|
||
if (!strchr(fileopen_name, '.')) {
|
||
strcat(fileopen_name, ".");
|
||
strcat(fileopen_name, extension);
|
||
added_extension = TRUE;
|
||
}
|
||
if (TRUE
|
||
#ifdef MACINTOSH
|
||
/* file open dialog already asked user to confirm unless we're
|
||
* adding an extension
|
||
*/
|
||
&& added_extension
|
||
#endif
|
||
) {
|
||
fp = NULL;
|
||
if (ok_to_open(fileopen_name, "r"))
|
||
fp = fopen(fileopen_name, "r");
|
||
if (fp != NULL) {
|
||
char question[100];
|
||
fclose(fp);
|
||
strcpy(question, "OK to overwrite ");
|
||
strcat(question, fileopen_name);
|
||
if (!askbool(question, FALSE)) {
|
||
fp = NULL;
|
||
problem = "\n";
|
||
goto tryagain;
|
||
}
|
||
}
|
||
}
|
||
fp = NULL;
|
||
if (ok_to_open(fileopen_name, mode))
|
||
fp = fopen(fileopen_name, mode);
|
||
if (fp == NULL) problem = "Couldn't create %s.\n";
|
||
}
|
||
tryagain:
|
||
if (fp == NULL) {
|
||
gprintf(TRANS, problem, fileopen_name);
|
||
gprintf(TRANS,"Try again.\n");
|
||
fileopen_name[0] = EOS;
|
||
}
|
||
}
|
||
return fp;
|
||
}
|
||
|
||
#ifdef MACINTOSH
|
||
|
||
static int GetReadFileName(name)
|
||
char *name;
|
||
{
|
||
static Point p = {100,100};
|
||
SFReply loadfile;
|
||
SFTypeList mytypes;
|
||
|
||
mytypes[0] = 0x54455854; /* 'TEXT' */
|
||
mytypes[1] = 0x4D696469; /* 'Midi' */
|
||
mytypes[2] = 0x3F3F3F3F; /* '????' */
|
||
/* could put any filter here (i.e. giofilefileter) */
|
||
SFGetFile(p, "\p", NULL, 3, mytypes, 0L, &loadfile);
|
||
if (loadfile.good) {
|
||
SetVol(0L,loadfile.vRefNum);
|
||
PtoC_StrCopy((char *) &loadfile.fName, name);
|
||
return(true);
|
||
} else return(false);
|
||
}
|
||
|
||
|
||
static int GetWriteFileName(fn, str)
|
||
char *fn, *str;
|
||
{
|
||
static Point SFPwhere = { 106, 104 };
|
||
unsigned char Pstr[100], Pfn[100];
|
||
SFReply reply;
|
||
|
||
strcpy((char *)Pstr, str);
|
||
CtoPstr((char *)Pstr);
|
||
strcpy((char *)Pfn, fn);
|
||
CtoPstr((char *)Pfn);
|
||
|
||
SFPutFile(SFPwhere, (ConstStr255Param) Pstr, (ConstStr255Param) Pfn,
|
||
0L, &reply);
|
||
if (reply.good) {
|
||
SetVol (0L,reply.vRefNum);
|
||
PtoC_StrCopy((char *) &reply.fName, fn);
|
||
return(true);
|
||
}
|
||
else return(false);
|
||
}
|
||
|
||
|
||
void PtoC_StrCopy(p1, p2)
|
||
register char *p1, *p2;
|
||
/* copies a pascal string from p1 to p2 */
|
||
{
|
||
register int len;
|
||
|
||
len = *p1++;
|
||
while (--len>=0) *p2++=*p1++;
|
||
*p2 = '\0';
|
||
}
|
||
|
||
|
||
boolean get_file_info(char *filename, OSType *file_type, OSType *file_creator)
|
||
{
|
||
short rc; /* toolbox return code */
|
||
FInfo fi; /* toolbox file info */
|
||
char fn[101]; /* temporary file name */
|
||
|
||
strcpy(fn, filename);
|
||
CtoPstr(fn);
|
||
if (rc = GetFInfo((byte*)fn, 0, &fi)) {
|
||
gprintf(ERROR, "rc from GetFInfo=%d\n", rc);
|
||
gprintf(ERROR, "unable to get file type\n");
|
||
*file_type = 0x3F3F3F3F; /* '????' */
|
||
*file_creator = 0x3F3F3F3F; /* '????' */
|
||
return FALSE;
|
||
} else /* set file type & creator */ {
|
||
if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n",
|
||
&fi.fdType, &fi.fdCreator );
|
||
*file_type = fi.fdType;
|
||
*file_creator = fi.fdCreator;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
boolean put_file_info(char *filename, OSType file_type, OSType file_creator)
|
||
{
|
||
short rc; /* toolbox return code */
|
||
FInfo fi; /* toolbox file info */
|
||
char fn[101]; /* temporary file name */
|
||
|
||
if (debug) gprintf(TRANS,"set file %s to become type '%.4s'\n", filename, &file_type);
|
||
strcpy(fn, filename);
|
||
CtoPstr(fn);
|
||
if (rc = GetFInfo((byte*)fn, 0, &fi)) {
|
||
gprintf(TRANS, "rc from GetFInfo=%d\n", rc);
|
||
gprintf(TRANS, "unable to set file type\n");
|
||
} else /* set file type & creator */ {
|
||
if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n",
|
||
&fi.fdType, &fi.fdCreator );
|
||
fi.fdType = file_type;
|
||
fi.fdCreator = file_creator;
|
||
if (rc=SetFInfo((byte*)fn, 0, &fi)) {
|
||
gprintf(TRANS, "rc from SetFInfo=%d\n", rc);
|
||
gprintf(TRANS, "unable to set file type\n");
|
||
} else if (rc=GetFInfo((byte*)fn, 0, &fi)) {
|
||
gprintf(TRANS, "rc from GetFInfo=%d\n", rc);
|
||
gprintf(TRANS, "unable to verify file type\n");
|
||
} else {
|
||
if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n",
|
||
&fi.fdType, &fi.fdCreator );
|
||
}
|
||
}
|
||
}
|
||
#endif /* MACINTOSH */
|
||
|
||
|
||
|
||
#ifdef AMIGA
|
||
/***************************************************************
|
||
* ascii_signal
|
||
*
|
||
* Input : none
|
||
* Ouput : none
|
||
* Return: the signal that will be raised on ascii input
|
||
* Effect: none
|
||
***************************************************************/
|
||
|
||
UBYTE ascii_signal()
|
||
{
|
||
return ConInPort->mp_SigBit;
|
||
}
|
||
#endif
|
||
|
||
/* check_aborted -- see if any characters are available, check for ctrl C */
|
||
|
||
int check_aborted()
|
||
{
|
||
char in_c;
|
||
#ifdef AMIGA
|
||
if (GetMsg(ConInPort)) {
|
||
in_c = KeyBuff[0];
|
||
if (in_c == '\r') in_c = '\n';
|
||
#endif
|
||
#ifndef AMIGA /* DOS or MACINTOSH or UNIX */
|
||
if (type_ahead_count < type_ahead_max && ascii_input(&in_c)) {
|
||
#endif
|
||
type_ahead[type_ahead_tail] = in_c;
|
||
if (in_c == ABORT_CHAR) abort_flag = ABORT_LEVEL;
|
||
else if (!abort_flag && in_c == BREAK_CHAR)
|
||
abort_flag = BREAK_LEVEL;
|
||
|
||
/* go ahead and insert anything into buffer, including ^C, ^G: */
|
||
type_ahead_count++;
|
||
type_ahead_tail++;
|
||
if (type_ahead_tail == type_ahead_max) type_ahead_tail = 0;
|
||
|
||
#ifdef AMIGA
|
||
if (type_ahead_count < type_ahead_max) ConRead();
|
||
#endif
|
||
}
|
||
return abort_flag;
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* readln
|
||
* Inputs:
|
||
* FILE * fp: File to read from
|
||
* Effect:
|
||
* Reads and discards characters until a newline is seen
|
||
****************************************************************************/
|
||
|
||
void readln(fp)
|
||
register FILE *fp;
|
||
{
|
||
register int c;
|
||
while (((c = getc(fp)) != '\n') && (c != EOF)) ;
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* gprintf
|
||
* Inputs:
|
||
* int * handler: pointer to output handler (say, a window)
|
||
* or one of {TRANS, ERROR, FATAL, GDEBUG} from userio.h
|
||
* char * format: a null-terminated printf style format string
|
||
* int arg0 through arg14: a variable number of arguments for printf
|
||
* Effect:
|
||
* formats and outputs the specified information to an output handler.
|
||
* this is a system-independent approach to output. On
|
||
* a simple machine, it is like printf. on a more complex machine,
|
||
* output is directed to the appropriate window.
|
||
* Implementation
|
||
* Note that to handle the variable argument list, a number of different
|
||
* approaches are implemented. The first part of the implementation selects
|
||
* one of 4 ways to build temp1, a formatted string. The 4 ways arise from
|
||
* use or non-use of vsnprintf, and use or non-use of ... in the arg list.
|
||
* After building temp1, non-Amiga systems write to stdout or stderr,
|
||
* whereas AMIGA writes to a special console. Why? Because the Amiga
|
||
* needs a new console so we can set up a signal upon character typein.
|
||
****************************************************************************/
|
||
|
||
#ifndef gprintf
|
||
#define GPRINTF_MESSAGE_LEN 512
|
||
#ifdef HAVE_VSNPRINTF
|
||
#ifdef DOTS_FOR_ARGS
|
||
|
||
/* define with ... in arg list and use vsnprintf to get temp1 */
|
||
public void gprintf(long where, const char *format, ...)
|
||
{
|
||
char temp1[GPRINTF_MESSAGE_LEN];
|
||
#ifdef AMIGA
|
||
char temp2[GPRINTF_MESSAGE_LEN];
|
||
#endif
|
||
va_list ap;
|
||
|
||
va_start(ap, format);
|
||
vsnprintf(temp1, GPRINTF_MESSAGE_LEN, format, ap);
|
||
va_end(ap);
|
||
|
||
#else /* !DOTS_FOR_ARGS */
|
||
|
||
/* define with va_alist and use vsnprintf to get temp1 */
|
||
public void gprintf(where, format, va_alist)
|
||
long where;
|
||
char *format;
|
||
va_dcl
|
||
{
|
||
char temp1[GPRINTF_MESSAGE_LEN];
|
||
va_list pvar;
|
||
/* this is a syntax error - if you don't have to remove this, */
|
||
/* then this whole section of code is unnecessary. */
|
||
va_start(pvar);
|
||
vsnprintf(temp1, GPRINTF_MESSAGE_LEN, format, pvar);
|
||
va_end(pvar);
|
||
|
||
#endif /* DOTS_FOR_ARGS */
|
||
|
||
#else /* !HAVE_VSNPRINTF */
|
||
#define MAX_GPRINTF_ARGS 10
|
||
typedef struct gp_args_struct {
|
||
long arg[MAX_GPRINTF_ARGS];
|
||
} gp_args_node;
|
||
|
||
#ifdef DOTS_FOR_ARGS
|
||
/* use ... but not vsnprintf */
|
||
public void gprintf(long where, char *format, ...)
|
||
{
|
||
char temp1[GPRINTF_MESSAGE_LEN];
|
||
#ifdef AMIGA
|
||
char temp2[GPRINTF_MESSAGE_LEN];
|
||
#endif
|
||
va_list ap;
|
||
gp_args_node args;
|
||
va_start(ap, format);
|
||
args = va_arg(ap, gp_args_node);
|
||
va_end(ap);
|
||
#else /* !DOTS_FOR_ARGS */
|
||
/* don't use ... and don't use vsnprintf */
|
||
public void gprintf(where, format, args)
|
||
long where;
|
||
char *format;
|
||
gp_args_node args;
|
||
{
|
||
char temp1[GPRINTF_MESSAGE_LEN];
|
||
#ifdef AMIGA
|
||
char temp2[GPRINTF_MESSAGE_LEN];
|
||
#endif /* AMIGA*/
|
||
#endif /* DOTS_FOR_ARGS */
|
||
|
||
snprintf(temp1, GPRINTF_MESSAGE_LEN, format, args);
|
||
|
||
#endif /* HAVE_VSNPRINTF */
|
||
|
||
/*
|
||
* Now we've got formatted output in temp1. Write it out.
|
||
*/
|
||
#ifdef NYQUIST
|
||
switch ((long) where) {
|
||
case TRANS:
|
||
stdputstr(temp1);
|
||
break;
|
||
case ERROR:
|
||
errputstr(temp1);
|
||
break;
|
||
case FATAL:
|
||
errputstr("FATAL: ");
|
||
errputstr(temp1);
|
||
break;
|
||
case GDEBUG:
|
||
errputstr("DEBUG: ");
|
||
errputstr(temp1);
|
||
break;
|
||
default:
|
||
errputstr("UNKNOWN: ");
|
||
errputstr(temp1);
|
||
break;
|
||
}
|
||
gflush();
|
||
#else /* not NYQUIST */
|
||
#ifdef AMIGA
|
||
|
||
switch((long) where) {
|
||
case TRANS:
|
||
strcpy(temp2, temp1);
|
||
break;
|
||
case ERROR:
|
||
strcpy(temp2, temp1);
|
||
break;
|
||
case FATAL:
|
||
strcpy(temp2, "FATAL: ");
|
||
strcat(temp2, temp1);
|
||
break;
|
||
case GDEBUG:
|
||
strcpy(temp2,"DEBUG: ");
|
||
strcat(temp2, temp1);
|
||
break;
|
||
default:
|
||
strcpy(temp2, "UNKNOWN: ");
|
||
strcat(temp2, temp1);
|
||
break;
|
||
}
|
||
ConOutReq->io_Command = CMD_WRITE;
|
||
ConOutReq->io_Data = (APTR)temp2;
|
||
ConOutReq->io_Length = -1; /* NULL terminated string */
|
||
DoIO((struct IORequest *) ConOutReq);
|
||
#else /* not NYQUIST or AMIGA */
|
||
switch(where) {
|
||
case TRANS:
|
||
printf("%s", temp1);
|
||
break;
|
||
case ERROR:
|
||
fprintf(STDERR, "%s", temp1);
|
||
break;
|
||
case GDEBUG:
|
||
fprintf(STDERR, "DEBUG %s", temp1);
|
||
break;
|
||
case FATAL:
|
||
fprintf(STDERR, "FATAL %s", temp1);
|
||
break;
|
||
default:
|
||
fprintf(STDERR, "UNKNOWN %s", temp1);
|
||
break;
|
||
}
|
||
#endif /* AMIGA */
|
||
#endif /* NYQUIST */
|
||
}
|
||
|
||
#endif /* ifndef gprintf */
|
||
|
||
|
||
/**************************************************************************
|
||
* gputchar
|
||
* General putchar
|
||
**************************************************************************/
|
||
|
||
#ifndef gputchar
|
||
|
||
#ifdef AMIGA
|
||
public int gputchar(c)
|
||
int c;
|
||
{
|
||
ConPutChar((char)c);
|
||
return(c);
|
||
}
|
||
#else
|
||
public int gputchar(c)
|
||
int c;
|
||
{
|
||
putchar((char)c);
|
||
return(c);
|
||
}
|
||
#endif
|
||
|
||
#endif /* ifndef gputchar */
|
||
|
||
/**************************************************************************
|
||
* ggetchar
|
||
* General getchar
|
||
**************************************************************************/
|
||
|
||
public int ggetchar()
|
||
{
|
||
#ifdef BUFFERED_SYNCHRONOUS_INPUT
|
||
return getchar();
|
||
#else
|
||
int key = wait_ascii();
|
||
if (key != ABORT_CHAR && key != '\b') gputchar((char)key);
|
||
return(key);
|
||
#endif
|
||
}
|
||
|
||
|
||
/**************************************************************************
|
||
* ggets
|
||
* General gets
|
||
**************************************************************************/
|
||
|
||
|
||
#ifndef ggets
|
||
|
||
public char *ggets(str)
|
||
char *str;
|
||
{
|
||
char *s = str;
|
||
int c;
|
||
|
||
do {
|
||
c = ggetchar();
|
||
if (c == '\b' /* backspace */) {
|
||
if (s != str) {
|
||
gputchar('\b');
|
||
gputchar((int)' ');
|
||
gputchar('\b');
|
||
s--;
|
||
} else {
|
||
#ifdef AMIGA
|
||
gputchar((int)0x9b);
|
||
gputchar((int)0x43);
|
||
#else
|
||
/* gputchar((int)' '); */
|
||
#endif
|
||
gputchar((int)0x07);
|
||
}
|
||
} else *s++ = (char) c;
|
||
} while (c != (int) '\n' && !abort_flag);
|
||
|
||
*(s-1) = EOS;
|
||
if (abort_flag) *str = EOS;
|
||
return str;
|
||
}
|
||
|
||
#endif /* ifndef ggets */
|
||
|
||
|
||
/****************************************************************************
|
||
* get_ascii
|
||
* Returns:
|
||
* boolean: TRUE if a character was found
|
||
* int * c: pointer to int into which to store the character, if any
|
||
* Effect:
|
||
* polls (doesn't wait) for an ascii character and says if it got one
|
||
* the character is returned in *c.
|
||
****************************************************************************/
|
||
|
||
public boolean get_ascii(c)
|
||
char *c;
|
||
{
|
||
check_aborted(); /* input buffer check */
|
||
if (type_ahead_count == 0) return FALSE;
|
||
#ifdef AMIGA
|
||
/* if the buffer is full, then there is no outstanding read, restart it: */
|
||
if (type_ahead_count == type_ahead_max) ConRead();
|
||
#endif
|
||
type_ahead_count--;
|
||
*c = type_ahead[type_ahead_head++];
|
||
if (type_ahead_head == type_ahead_max) type_ahead_head = 0;
|
||
return TRUE;
|
||
}
|
||
|
||
#ifdef MACINTOSH /** Macintosh direct ascii input**/
|
||
public boolean ascii_input(c)
|
||
char *c;
|
||
{
|
||
EventRecord theEvent;
|
||
|
||
(void) GetNextEvent((keyDownMask | autoKeyMask), &theEvent);
|
||
if ((theEvent.what == keyDown) || (theEvent.what == autoKey)) {
|
||
*c = theEvent.message & charCodeMask;
|
||
if (*c == '\r') *c = '\n';
|
||
return(true);
|
||
}
|
||
else {
|
||
return(false);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef WINDOWS
|
||
#include "conio.h"
|
||
#define kbhit _kbhit
|
||
#define getch _getch
|
||
#endif
|
||
|
||
#ifdef DOS
|
||
public boolean ascii_input(c)
|
||
char *c;
|
||
{
|
||
if (abort_flag == ABORT_LEVEL) {
|
||
*c=ABORT_CHAR;
|
||
return((boolean)TRUE);
|
||
}
|
||
if (kbhit()) { /* If the keyboard was hit */
|
||
*c = getch(); /* Don't echo it */
|
||
// printf("now break");
|
||
if (*c == '\r') *c = '\n';
|
||
return((boolean)TRUE);
|
||
}
|
||
return((boolean)FALSE); /* Keeps Lattice compiler happy */
|
||
}
|
||
#endif
|
||
|
||
#ifdef UNIX
|
||
public boolean ascii_input(char *c)
|
||
{
|
||
#ifdef UNIX_MACH
|
||
/*
|
||
* we can't read from stdin directly, because the ascii
|
||
* input thread is already doing so, so instead we'll
|
||
* wait for that thread to read a character and then take
|
||
* it
|
||
*/
|
||
boolean ret = FALSE;
|
||
|
||
A_LOCK();
|
||
if (a_in_flag) {
|
||
(*c) = a_in;
|
||
a_in_flag = 0;
|
||
ret = TRUE;
|
||
}
|
||
A_UNLOCK();
|
||
if (ret) {
|
||
#ifdef RTMach
|
||
itc_condition_signal(&a_cond);
|
||
#else /* RTMach */
|
||
condition_signal(&a_cond);
|
||
#endif /* RTMach */
|
||
}
|
||
if ((*c) == '\r')
|
||
(*c) = '\n';
|
||
return(ret);
|
||
#else /* __APPLE__ */
|
||
#ifndef BUFFERED_SYNCHRONOUS_INPUT
|
||
int input = IOgetchar();
|
||
if (input != IOnochar) {
|
||
*c = input;
|
||
if (*c == '\r') *c = '\n';
|
||
return TRUE;
|
||
}
|
||
#endif /* BUFFERED_SYNCHRONOUS_INPUT */
|
||
return FALSE;
|
||
#endif /* __APPLE__ */
|
||
}
|
||
#endif
|
||
|
||
#ifndef AMIGA /*DOS and MAC and UNIX */
|
||
public void unget_ascii(char c)
|
||
{
|
||
if (type_ahead_head == 0) type_ahead_head = type_ahead_max;
|
||
type_ahead_head--;
|
||
type_ahead[type_ahead_head] = c;
|
||
type_ahead_count++;
|
||
}
|
||
|
||
|
||
public boolean check_ascii(void)
|
||
{
|
||
char c;
|
||
|
||
if(get_ascii(&c)) {
|
||
unget_ascii(c);
|
||
return TRUE;
|
||
}
|
||
else return FALSE;
|
||
}
|
||
#endif
|
||
|
||
|
||
/****************************************************************************
|
||
* wait_ascii
|
||
* Returns:
|
||
* int: character for key pressed
|
||
* Effect:
|
||
* waits for the user to type a key on the terminal keyboard
|
||
* (versus the synthesizer keyboard) and returns the key typed
|
||
****************************************************************************/
|
||
|
||
#ifdef MACINTOSH
|
||
public int wait_ascii()
|
||
{
|
||
char key ; /* key typed */
|
||
|
||
if (abort_flag == ABORT_LEVEL) return ABORT_CHAR;
|
||
if (abort_flag == BREAK_LEVEL) return BREAK_CHAR;
|
||
gflush();
|
||
while (!get_ascii(&key)) ;
|
||
return(key);
|
||
}
|
||
#endif
|
||
|
||
#ifdef DOS
|
||
public int wait_ascii()
|
||
{
|
||
char key ; /* key typed */
|
||
|
||
if (abort_flag == ABORT_LEVEL) return ABORT_CHAR;
|
||
if (abort_flag == BREAK_LEVEL) return BREAK_CHAR;
|
||
if (!get_ascii(&key)) {
|
||
key = _getch(); // block until we get an input
|
||
}
|
||
/* GWL - check for abort on previos line */
|
||
return (int)key;
|
||
}
|
||
#endif
|
||
|
||
#ifndef MACINTOSH
|
||
#ifndef DOS
|
||
public int wait_ascii()
|
||
{
|
||
#ifdef UNIX /* was defined (UNIX) || defined(ITC) */
|
||
#ifndef UNIX_MACH
|
||
fd_set readfds;
|
||
#endif /* !UNIX_MACH */
|
||
#endif
|
||
char c;
|
||
struct rlimit file_limit;
|
||
|
||
if (abort_flag == ABORT_LEVEL) return ABORT_CHAR;
|
||
if (abort_flag == BREAK_LEVEL) return BREAK_CHAR;
|
||
while (!get_ascii(&c)) {
|
||
#ifdef AMIGA
|
||
WaitPort(ConInPort);
|
||
#endif
|
||
#ifdef UNIX
|
||
fflush(stdout);
|
||
#ifdef UNIX_MACH
|
||
/*
|
||
* we can't select, since another thread is reading
|
||
* from stdin, and we don't want to have an input war
|
||
* so instead, the ascii input thread will signal
|
||
* a_in_cond when it gets input, so we just wait
|
||
* for that to happen
|
||
*/
|
||
A_LOCK();
|
||
#ifdef RTMach
|
||
itc_condition_wait(&a_in_cond, &a_mutex);
|
||
#else /* RTMach */
|
||
condition_wait(&a_in_cond, &a_mutex);
|
||
#endif /* RTMach */
|
||
A_UNLOCK();
|
||
#else /* UNIX_MACH */
|
||
FD_ZERO(&readfds);
|
||
FD_SET(IOinputfd, &readfds);
|
||
gflush();
|
||
getrlimit(RLIMIT_NOFILE, &file_limit);
|
||
select((int) (file_limit.rlim_max+1), &readfds, 0, 0, NULL);
|
||
#endif /* !__APPLE__ */
|
||
#endif /* ifdef UNIX */
|
||
}
|
||
return (int) c;
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef AMIGA
|
||
/******************************************************************
|
||
AMIGA 2000.
|
||
Console IO Functions
|
||
JCD 25-Apr-88
|
||
*******************************************************************/
|
||
|
||
UBYTE KeybSig()
|
||
{
|
||
return ConInPort->mp_SigBit;
|
||
}
|
||
|
||
private void ConPutChar(c)
|
||
char c;
|
||
{
|
||
ConOutReq->io_Command = CMD_WRITE;
|
||
ConOutReq->io_Data = (APTR)&c;
|
||
ConOutReq->io_Length = 1;
|
||
DoIO((struct IORequest *) ConOutReq);
|
||
}
|
||
|
||
private void ConPutStr(str)
|
||
char *str;
|
||
{
|
||
ConOutReq->io_Command = CMD_WRITE;
|
||
ConOutReq->io_Data = (APTR)str;
|
||
ConOutReq->io_Length = -1;
|
||
DoIO((struct IORequest *) ConOutReq);
|
||
}
|
||
|
||
private void ConRead()
|
||
{
|
||
ConInReq->io_Command = CMD_READ;
|
||
ConInReq->io_Data = (APTR)KeyBuff;
|
||
ConInReq->io_Length = 1;
|
||
SendIO((struct IORequest *) ConInReq);
|
||
}
|
||
#endif
|