📄 userio.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 asspecial characters, and these do not cause software interrupts. Also, thelowest level of the CMT model does not support line editing: Every characteris acted upon immediately. This has two implications:(1) CMT must "read ahead" looking for ^C and ^G characters. This is handledby 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 visibleto 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 fairlymachine independent, except for some backspace-and-erase control charactercode 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 charactercode translation. wait_ascii() either polls get_ascii() or uses somekind of system-dependent event waiting. Returns ABORT_CHAR or BREAK_CHARimmediately if abort_flag has been set, regardless of whether there isnew ascii input.get_ascii() - checks to see if a character is available. (Usingcheck_aborted().)The only dependency here is on the Amiga, we restart input when buffer goesfrom 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 isone. Does conversion from RETURN (\r) to EOL (\n). The Amiga handlesthis in-line directly in check_aborted().Here's a quick summary:ggets = ggetchar + line editing & string buildingggetchar = wait_ascii + character echowait_ascii = get_ascii + wait for characterget_ascii = check_aborted + pull char from buffercheck_aborted = ascii_input + test for ^C,^G + put in bufferascii_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 RTMachextern 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 "cmtio.h"#ifdef _IBMR2#define NBBY 8#define OPEN_MAX 2000#include <sys/select.h>#endif#endif#ifdef linux#include <sys/time.h> /* for FD_ZERO / FD_SET */#endifextern int debug;#ifdef NYQUIST/* get definitions for stdputstr, etc. */#include "xlisp.h"#endif/****************************************************************************** routines private to this module*****************************************************************************/int GetReadFileName();int GetWriteFileName();#ifdef MACINTOSHprivate 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();/****************************************************************************** variables private to this module*****************************************************************************/#ifdef AMIGAstruct 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 MACINTOSHprivate OSType io_file_type = 0x3F3F3F3F; /* '????' */private OSType io_file_creator = 0x3F3F3F3F; /* '????' */#endif#define type_ahead_max 100char type_ahead[100];int type_ahead_head = 0;int type_ahead_tail = 0;int type_ahead_count = 0;#ifdef DOS#ifdef BORLANDint c_break(void){ gprintf(TRANS, " BREAK "); abort_flag = ABORT_LEVEL; return 1; /* non-zero means do not exit program */}#endif#ifdef MICROSOFTvoid 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 NYQUISTvoid 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******************************************************************************/voidio_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -