#include #include #include /* atariio.c */ #include "ztypes.h" #if defined(BSD) #include #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) #include #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) #include #endif /* defined(POSIX) */ #include #include #include /* needed by AIX */ #if defined(AIX) #include #endif /* new stuff for command editing */ int BUFFER_SIZE; char *commands; int space_avail; static int ptr1,ptr2=0; static int end_ptr=0; static int row,head_col; static int keypad_avail=1; /* done with editing global info */ static int ismint=0; static int current_row = 1; static int current_col = 1; static int saved_row; static int saved_col; static int cursor_saved = OFF; static char tcbuf[1024]; static char cmbuf[1024]; static char *cmbufp; volatile long volatile *_systicks=(long *)0x4baL; static char *CE, *CL, *CM, *CS, *DL, *MD, *ME, *MR, *SE, *SO, *TE, *TI, *UE, *US, *KD, *KL, *KR, *KU; #define GET_TC_STR(p1, p2) if ((p1 = tgetstr (p2, &cmbufp)) == NULL) p1 = "" #define BELL 7 static int Agetchar(void); static void outc (); static void display_string (); static int wait_for_char (); static int read_key (); static void set_cbreak_mode (); static void rundown (); extern int tgetent (); extern int tgetnum (); extern char *tgetstr (); extern char *tgoto (); extern void tputs (); static int colours=0; static void outc (c) int c; { putchar (c); }/* outc */ void set_colours(int foreground,int background) { /* Somewhere, we have a termcap entry, but we'll have to get a bit machine specific for this one */ static int cmap2b[]={0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}; static int cmap2f[]={1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}; static int cmap4b[]={0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3}; static int cmap4f[]={3,2,1,0,3,2,1,0,3,2,1,0,3,2,1,0}; static int cmap16f[]={0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}; static int cmap16b[]={15,13,11,9,7,5,3,1,14,12,10,8,6,4,2,0}; if(!colours) { int mode; putchar('\033'); putchar('w'); mode=Getrez(); switch(mode) { case 1: colours=4; break; case 6: case 2: colours=2; break; default: /* At least 16, and possibly 16 million */ colours=16; break; } } switch(colours) { case 2: foreground=cmap2f[foreground-1]; background=cmap2b[background-1]; putchar('\033'); putchar('b'); putchar(foreground); putchar('\033'); putchar('c'); putchar(foreground+1); break; case 4: foreground=cmap4f[foreground-1]; background=cmap4b[background-1]; putchar('\033'); putchar('b'); putchar(foreground); putchar('\033'); putchar('c'); putchar((foreground==background)?foreground+1:background); break; case 16: foreground=cmap16f[foreground-1]; background=cmap16b[background-1]; putchar('\033'); putchar('b'); putchar(foreground); putchar('\033'); putchar('c'); putchar((foreground==background)?foreground+1:background); break; default: fatal("Terminal error in colour handling."); } } void initialize_screen () { char *term; int row, col; ismint=Pgetpid()!=-32; if ((term = getenv ("TERM")) == NULL) { /* If there is no termcap entry available, then make the standard default */ fudge: term="vt52|dec-vt52|dec vt52:do=^J:le=^H:bs:cd=\\EJ:ce=\\EK: cl=\\EH\\EJ:cm=\\EY%+ %+ :co#80:li#24:nd=\\EC:pt:sr=\\EI:up=\\EA: ku=\\EA:kd=\\EB:kr=\\EC:kl=\\ED:kb=^H:so=\\Ep:se=\\Eq:al=\\EL:dl=\\EM:"; CE="\033K"; CL="\033H\033J"; CM="\033Y%+ %+ "; MR=MD=ME=CS=US=UE=""; KU="\033A"; KD="\033B"; KL="\033C"; KR="\033D"; DL="\033M"; SO="\033p"; SE="\033q"; TE="\033v";TI="\033w"; screen_cols=80; if(!Getrez()) screen_cols/=2; screen_rows=25; } else { if (tgetent (tcbuf, term) <= 0) { goto fudge; /* fatal ("No termcap entry for this terminal"); */ } cmbufp = cmbuf; GET_TC_STR (CE, "ce"); GET_TC_STR (CL, "cl"); GET_TC_STR (CM, "cm"); GET_TC_STR (CS, "cs"); GET_TC_STR (DL, "dl"); GET_TC_STR (MD, "md"); GET_TC_STR (ME, "me"); GET_TC_STR (MR, "mr"); GET_TC_STR (SE, "se"); GET_TC_STR (SO, "so"); GET_TC_STR (TE, "te"); GET_TC_STR (TI, "ti"); GET_TC_STR (UE, "ue"); GET_TC_STR (US, "us"); GET_TC_STR (KU, "ku"); GET_TC_STR (KD, "kd"); GET_TC_STR (KR, "kr"); GET_TC_STR (KL, "kl"); if(!KU||!*KU) { KU="\033A"; KD="\033B"; KL="\033C"; KR="\033D"; } if (screen_cols == 0 && (screen_cols = tgetnum ("co")) == -1) screen_cols = DEFAULT_COLS; if (screen_rows == 0 && (screen_rows = tgetnum ("li")) == -1) screen_rows = DEFAULT_ROWS; } if (*MD == '\0' || *ME == '\0' || *MR == '\0') { MD = SO; ME = SE; MR = SO; } if (*UE == '\0' || *US == '\0') { UE = SE; US = SO; } tputs (TI, 1, outc); clear_screen (); row = screen_rows / 2 - 1; col = (screen_cols - (sizeof (JZIPVER) - 1)) / 2; move_cursor (row, col); display_string (JZIPVER); row = screen_rows / 2; col = (screen_cols - (sizeof ("The story is loading...") - 1)) / 2; move_cursor (row, col); display_string ("The story is loading..."); h_interpreter = INTERP_ATARI_ST; commands=(char *) malloc(hist_buf_size*sizeof(char)); if (commands==NULL) fatal("Could not allocate history buffer!"); BUFFER_SIZE=hist_buf_size; space_avail=hist_buf_size-1; set_cbreak_mode (1); interp_initialized = 1; }/* initialize_screen */ void restart_screen () { cursor_saved = OFF; if (h_type < V4) set_byte (H_CONFIG, (get_byte (H_CONFIG) | CONFIG_WINDOWS)); else set_byte (H_CONFIG, (get_byte (H_CONFIG) | CONFIG_EMPHASIS | CONFIG_WINDOWS)); #if 0 /* Force graphics off as we can't do them */ set_word (H_FLAGS, (get_word (H_FLAGS) & (~GRAPHICS_FLAG))); #endif }/* restart_screen */ void reset_screen () { /* only do this stuff on exit when called AFTER initialize_screen */ if (interp_initialized) { delete_status_window (); select_text_window (); set_attribute (NORMAL); set_cbreak_mode (0); tputs (TE, 1, outc); } }/* reset_screen */ void clear_screen () { tputs (CL, 1, outc); current_row = 1; current_col = 1; }/* clear_screen */ void select_status_window () { save_cursor_position (); }/* select_status_window */ void select_text_window () { restore_cursor_position (); }/* select_text_window */ void create_status_window () { int row, col; if (*CS) { get_cursor_position (&row, &col); tputs (tgoto (CS, screen_rows - 1, status_size), 1, outc); move_cursor (row, col); } }/* create_status_window */ void delete_status_window () { int row, col; if (*CS) { get_cursor_position (&row, &col); tputs (tgoto (CS, screen_rows - 1, 0), 1, outc); move_cursor (row, col); } }/* delete_status_window */ void clear_line () { tputs (CE, 1, outc); }/* clear_line */ void clear_text_window () { int i, row, col; get_cursor_position (&row, &col); for (i = status_size + 1; i <= screen_rows; i++) { move_cursor (i, 1); clear_line (); } move_cursor (row, col); }/* clear_text_window */ void clear_status_window () { int i, row, col; get_cursor_position (&row, &col); for (i = status_size; i; i--) { move_cursor (i, 1); clear_line (); } move_cursor (row, col); }/* clear_status_window */ void move_cursor (row, col) int row; int col; { tputs (tgoto (CM, col - 1, row - 1), 1, outc); current_row = row; current_col = col; }/* move_cursor */ void get_cursor_position (row, col) int *row; int *col; { *row = current_row; *col = current_col; }/* get_cursor_position */ void save_cursor_position () { if (cursor_saved == OFF) { get_cursor_position (&saved_row, &saved_col); cursor_saved = ON; } }/* save_cursor_position */ void restore_cursor_position () { if (cursor_saved == ON) { move_cursor (saved_row, saved_col); cursor_saved = OFF; } }/* restore_cursor_position */ void set_attribute (attribute) int attribute; { if (attribute == NORMAL) { tputs (ME, 1, outc); tputs (UE, 1, outc); } if (attribute & REVERSE) tputs (MR, 1, outc); if (attribute & BOLD) tputs (MD, 1, outc); if (attribute & EMPHASIS) tputs (US, 1, outc); if (attribute & FIXED_FONT) ; }/* set_attribute */ static void display_string (s) char *s; { while (*s) display_char (*s++); }/* display_string */ void display_char (c) int c; { outc (c); if (++current_col > screen_cols) current_col = screen_cols; }/* display_char */ void scroll_line () { int row, col; get_cursor_position (&row, &col); if (*CS || row < screen_rows) { display_char ('\n'); } else { move_cursor (status_size + 1, 1); tputs (DL, 1, outc); move_cursor (row, 1); } current_col = 1; if (++current_row > screen_rows) current_row = screen_rows; }/* scroll_line */ int display_command(char *buffer) { int counter,loop; move_cursor(row,head_col); clear_line(); move_cursor(row,head_col); /* ptr1 == end_ptr when the player has selected beyond any previously saved command */ if(ptr1==end_ptr) return 0; else { counter=0; for(loop=ptr1;loop<=ptr2;loop++) { buffer[counter]=commands[loop]; display_char(buffer[counter++]); } return counter; } } void get_prev_command(void) { if(ptr1>0) { ptr2=ptr1-=2; if(ptr1<0) ptr1=0; if(ptr2<0) ptr2=0; if(ptr1>0) { do ptr1--; while ((commands[ptr1]!='\n')&&(ptr1>=0)); ptr1++; } } } void get_next_command(void) { if(ptr2=end_ptr) ptr1=ptr2=end_ptr; else { do ptr2++; while ((commands[ptr2]!='\n')&&(ptr2<=end_ptr)); ptr2--; } } } void get_first_command(void) { if(end_ptr>1) { ptr1=ptr2=0; do ptr2++; while ((commands[ptr2]!='\n')&&(ptr2<=end_ptr)); ptr2--; } } void delete_command(void) { int loop; do { for(loop=0;loop1000000) { tv.tv_sec++; tv.tv_usec-=1000000; } } */ for ( ; ; ) { get_cursor_position(&row,&col); keyfunc=0; /* Read a single keystroke */ fflush (stdout); if(timeout!=0) if(wait_for_char(timeout)) return (-1); c = read_key (); if(keypad_avail) { if(c==(char)*KU) { for(loop=0;loop<(strlen(KU)-1);loop++) do c=Agetchar(); while(c=='['); if(c==(unsigned char)KU[strlen(KU)-1]) { get_prev_command(); curr_char_pos=*read_size=display_command(buffer); tail_col=head_col+*read_size; keyfunc=1; } else if(c==(unsigned char)KD[strlen(KD)-1]) { get_next_command(); curr_char_pos=*read_size=display_command(buffer); tail_col=head_col+*read_size; keyfunc=1; } else if(c==(unsigned char)KL[strlen(KL)-1]) { get_cursor_position(&row,&col); if(col>head_col) { move_cursor(row,--col); curr_char_pos--; } keyfunc=1; } else if(c==(unsigned char)KR[strlen(KR)-1]) { get_cursor_position(&row,&col); if(colhead_col) { move_cursor(row,--col); for(loop=curr_char_pos;loop<*read_size;loop++) { buffer[loop-1]=buffer[loop]; display_char(buffer[loop-1]); } display_char(' '); curr_char_pos--; tail_col--; (*read_size)--; move_cursor(row,col); } } else { /* Normal key action */ if (*read_size == (buflen - 1)) { /* Ring bell if buffer is full */ outc (BELL); } else { /* Scroll line if return key pressed */ if (c == '\n'||c=='\r') { c='\n'; scroll_line (); } if(c=='\n') { if(*read_size>BUFFER_SIZE) return(c); while(*read_size>space_avail) { delete_command(); } if(*read_size>0) add_command(buffer,*read_size); return c; } else { get_cursor_position(&row,&col); if(col=curr_char_pos;loop--) buffer[loop+1]=buffer[loop]; buffer[curr_char_pos]=(char)c; (*read_size)++; tail_col++; #if 1 move_cursor(row,col); for(loop=curr_char_pos;loop<*read_size;loop++) display_char(buffer[loop]); move_cursor(row,++col); curr_char_pos++; #endif #if 0 move_cursor(row,head_col); for(loop=0;loop<*read_size;loop++) display_char(buffer[loop]); move_cursor(row,++col); #endif } else { buffer[curr_char_pos++]=(char)c; display_char(c); (*read_size)++; tail_col++; } } } } } } }/* input_line */ long Systicks(void) { long rval; long sssp; sssp=Super(0L); rval=*_systicks; Super(sssp); return rval; } static int wait_for_char (int timeout) { int nfds, status; fd_set readfds; struct timeval tv; struct timezone tz; printf("timeout %d/ticks %ld\n",timeout,Systicks()); if(!ismint) { /* if in TOS then the timeout value is just stored in tv.usec */ printf("timeout %d/ticks %ld\n",timeout,Systicks()); timeout=(timeout*20)+Systicks(); while(Systicks()<(long)timeout) if(Cconis()) return 0; return -1; } gettimeofday (&tv, &tz); /* if (tv.tv_sec >= timeout->tv_sec && tv.tv_usec >= timeout->tv_usec) return (-1); */ if(!timeout) return(-1); /* tv.tv_sec = timeout->tv_sec - tv.tv_sec; if (timeout->tv_usec < tv.tv_usec) { tv.tv_sec--; tv.tv_usec = (timeout->tv_usec + 1000000) - tv.tv_usec; } else tv.tv_usec = timeout->tv_usec - tv.tv_usec; */ tv.tv_sec=(timeout*100000)/1000000; tv.tv_usec=(timeout*100000)%1000000; /* used to be the following, but some boxen have no getdtablesize() */ /* nfds = getdtablesize (); */ nfds = FD_SETSIZE; FD_ZERO (&readfds); FD_SET (fileno (stdin), &readfds); status = select (nfds, &readfds, NULL, NULL, &tv); if (status < 0) { perror ("select"); return (-1); } if (status == 0) return (-1); else return (0); }/* wait_for_char */ static int Agetchar(void) { static int holdover=0; int c,c1; if(ismint) { c=getchar(); if(c==13) c=10; return c; } if(holdover) { c=holdover; holdover=0; return c; } reloop: c1 = Cnecin(); if(c1&0xff) return c1&0xff; c=((c1&0x00ff0000)>>16); switch(c) { case 0x48: holdover='A'; return 27; case 0x50: holdover='B'; return 27; case 0x4b: holdover='C'; return 27; case 0x4d: holdover='D'; return 27; default: goto reloop; } } static int read_key () { int c; c=Agetchar(); if (c == 127) c = '\b'; else if (c == 13) c = 10; return (c); }/* read_key */ static void set_cbreak_mode (mode) int mode; { int status; #if defined(BSD) struct sgttyb new_tty; static struct sgttyb old_tty; #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) struct termio new_termio; static struct termio old_termio; #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) struct termios new_termios; static struct termios old_termios; #endif /* defined(POSIX) */ #if defined(BSD) status = ioctl (fileno (stdin), (mode) ? TIOCGETP : TIOCSETP, &old_tty); #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) status = ioctl (fileno (stdin), (mode) ? TCGETA : TCSETA, &old_termio); #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) if (mode) status = tcgetattr (fileno (stdin), &old_termios); else status = tcsetattr (fileno (stdin), TCSANOW, &old_termios); #endif /* defined(POSIX) */ if (status&&ismint) { perror ("ioctl"); exit (1); } if (mode) { signal (SIGINT, rundown); signal (SIGTERM, rundown); } if (mode) { #if defined(BSD) status = ioctl (fileno (stdin), TIOCGETP, &new_tty); #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) status = ioctl (fileno (stdin), TCGETA, &new_termio); #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) status = tcgetattr (fileno (stdin), &new_termios); #endif /* defined(POSIX) */ if (status&&ismint) { perror ("ioctl"); exit (1); } #if defined(BSD) new_tty.sg_flags |= CBREAK; new_tty.sg_flags &= ~ECHO; #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) new_termio.c_lflag &= ~(ICANON | ECHO); #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) new_termios.c_lflag &= ~(ICANON | ECHO); /* the next two lines of code added by Mark Phillips. The patch */ /* was for sun and __hpux, active only if those were #defined, */ /* but most POSIX boxen (SunOS, HP-UX, Dec OSF, Irix for sure) */ /* can use this... It makes character input work. VMIN and */ /* VTIME are reused on some systems, so when the mode is switched*/ /* to RAW all character access is, by default, buffered wrong. */ /* For the curious: VMIN='\004' and VTIME='\005' octal on */ /* these systems. VMIN is usually EOF and VTIME is EOL. (JDH) */ new_termios.c_cc[VMIN]=1; new_termios.c_cc[VTIME]=2; #endif /* defined(POSIX) */ #if defined(BSD) status = ioctl (fileno (stdin), TIOCSETP, &new_tty); #endif /* defined(BSD) */ #if defined(SYSTEM_FIVE) status = ioctl (fileno (stdin), TCSETA, &new_termio); #endif /* defined(SYSTEM_FIVE) */ #if defined(POSIX) status = tcsetattr (fileno (stdin), TCSANOW, &new_termios); #endif /* defined(POSIX) */ if (status&&ismint) { perror ("ioctl"); exit (1); } } if (mode == 0) { signal (SIGINT, SIG_DFL); signal (SIGTERM, SIG_DFL); } }/* set_cbreak_mode */ static void rundown () { unload_cache (); close_story (); close_script (); reset_screen (); }/* rundown */