File: atariio.c - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

0001: 
0002: /* $Id: atariio.c,v 1.1.1.1 2000/05/10 14:20:50 jholder Exp $  
0003:  * --------------------------------------------------------------------
0004:  * see doc/License.txt for License Information  
0005:  * --------------------------------------------------------------------
0006:  *
0007:  * File name: $Id: atariio.c,v 1.1.1.1 2000/05/10 14:20:50 jholder Exp $  
0008:  *  
0009:  * Description:    
0010:  *    
0011:  * Modification history:      
0012:  * $Log: atariio.c,v $
0013:  * Revision 1.1.1.1  2000/05/10 14:20:50  jholder
0014:  *
0015:  * imported
0016:  *
0017:  *
0018:  * --------------------------------------------------------------------
0019:  */
0020: 
0021: 
0022: #include <stdio.h>
0023: #include <osbind.h>
0024: #include <mintbind.h>
0025: 
0026: #include <ncurses/termcap.h>
0027: 
0028: /* atariio.c */
0029: 
0030: #include "ztypes.h"
0031: 
0032: #if defined(BSD)
0033: #include <sgtty.h>
0034: #endif /* defined(BSD) */
0035: #if defined(SYSTEM_FIVE)
0036: #include <termio.h>
0037: #endif /* defined(SYSTEM_FIVE) */
0038: #if defined(POSIX)
0039: #include <termios.h>
0040: #endif /* defined(POSIX) */
0041: 
0042: #include <signal.h>
0043: #include <sys/types.h>
0044: #include <sys/time.h>
0045: 
0046: /* needed by AIX */
0047: #if defined(AIX)
0048: #include <sys/select.h>
0049: #endif
0050: 
0051: /* new stuff for command editing */
0052: int BUFFER_SIZE;
0053: char *commands;
0054: int space_avail;
0055: static int ptr1, ptr2 = 0;
0056: static int end_ptr = 0;
0057: static int row, head_col;
0058: static int keypad_avail = 1;
0059: 
0060: /* done with editing global info */
0061: 
0062: static int ismint = 0;
0063: static int current_row = 1;
0064: static int current_col = 1;
0065: 
0066: static int saved_row;
0067: static int saved_col;
0068: 
0069: static int cursor_saved = OFF;
0070: 
0071: static char tcbuf[1024];
0072: static char cmbuf[1024];
0073: static char *cmbufp;
0074: 
0075: volatile long volatile *_systicks = ( long * ) 0x4baL;
0076: static char *CE, *CL, *CM, *CS, *DL, *MD, *ME, *MR, *SE, *SO, *TE, *TI, *UE, *US, *KD, *KL, *KR,
0077: 
0078:       *KU;
0079: 
0080: #define GET_TC_STR(p1, p2) if ((p1 = tgetstr (p2, &cmbufp)) == NULL) p1 = ""
0081: 
0082: #define BELL 7
0083: static int Agetchar( void );
0084: static int outc(  );
0085: static void display_string(  );
0086: static int wait_for_char(  );
0087: static int read_key(  );
0088: static void set_cbreak_mode(  );
0089: static void rundown(  );
0090: 
0091: /*extern int tgetent(  );
0092: extern int tgetnum(  );
0093: extern char *tgetstr(  );
0094: extern char *tgoto(  );
0095: extern void tputs(  );*/ // already declared in termcap
0096: 
0097: static int colours = 0;
0098: static int outc( c )
0099:    int c;
0100: {
0101:    putchar( c ); return 0;
0102: }                               /* outc */
0103: 
0104: void set_colours( int foreground, int background )
0105: {
0106:    /* Somewhere, we have a termcap entry, but we'll have to get a
0107:     * bit machine specific for this one */
0108:    static int cmap2b[] = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
0109:    static int cmap2f[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
0110:    static int cmap4b[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
0111:    static int cmap4f[] = { 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0 };
0112:    static int cmap16f[] = { 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
0113:    static int cmap16b[] = { 15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0 };
0114: 
0115:    if ( !colours )
0116:    {
0117:       int mode;
0118: 
0119:       putchar( '\033' );
0120:       putchar( 'w' );
0121:       mode = Getrez(  );
0122:       switch ( mode )
0123:       {
0124:          case 1:
0125:             colours = 4;
0126:             break;
0127:          case 6:
0128:          case 2:
0129:             colours = 2;
0130:             break;
0131:          default:
0132:             /* At least 16, and possibly 16 million */
0133:             colours = 16;
0134:             break;
0135:       }
0136:    }
0137: 
0138:    switch ( colours )
0139:    {
0140:       case 2:
0141:          foreground = cmap2f[foreground - 1];
0142:          background = cmap2b[background - 1];
0143:          putchar( '\033' );
0144:          putchar( 'b' );
0145:          putchar( foreground );
0146:          putchar( '\033' );
0147:          putchar( 'c' );
0148:          putchar( foreground + 1 );
0149:          break;
0150:       case 4:
0151:          foreground = cmap4f[foreground - 1];
0152:          background = cmap4b[background - 1];
0153:          putchar( '\033' );
0154:          putchar( 'b' );
0155:          putchar( foreground );
0156:          putchar( '\033' );
0157:          putchar( 'c' );
0158:          putchar( ( foreground == background ) ? foreground + 1 : background );
0159:          break;
0160:       case 16:
0161:          foreground = cmap16f[foreground - 1];
0162:          background = cmap16b[background - 1];
0163:          putchar( '\033' );
0164:          putchar( 'b' );
0165:          putchar( foreground );
0166:          putchar( '\033' );
0167:          putchar( 'c' );
0168:          putchar( ( foreground == background ) ? foreground + 1 : background );
0169:          break;
0170:       default:
0171:          fatal( "set_colours(): Terminal error in colour handling." );
0172:    }
0173: }
0174: 
0175: void initialize_screen(  )
0176: {
0177:    char *term;
0178:    int row, col;
0179: 
0180:    ismint = Pgetpid(  ) != -32;
0181: 
0182:    if ( ( term = getenv( "TERM" ) ) == NULL )
0183:    {
0184:       /* If there is no termcap entry available, then make the standard default */
0185:     fudge:
0186:       term =
0187:             "vt52|dec-vt52|dec vt52:do=^J:le=^H:bs:cd=\\EJ:ce=\\EK:"
0188:             "cl=\\EH\\EJ:cm=\\EY%+ %+ :co#80:li#24:nd=\\EC:pt:sr=\\EI:up=\\EA:"
0189:             "ku=\\EA:kd=\\EB:kr=\\EC:kl=\\ED:kb=^H:so=\\Ep:se=\\Eq:al=\\EL:dl=\\EM:";
0190:       CE = "\033K";
0191:       CL = "\033H\033J";
0192:       CM = "\033Y%+ %+ ";
0193:       MR = MD = ME = CS = US = UE = "";
0194:       KU = "\033A";
0195:       KD = "\033B";
0196:       KL = "\033C";
0197:       KR = "\033D";
0198:       DL = "\033M";
0199:       SO = "\033p";
0200:       SE = "\033q";
0201:       TE = "\033v";
0202:       TI = "\033w";
0203:       screen_cols = 80;
0204:       if ( !Getrez(  ) )
0205:          screen_cols /= 2;
0206:       screen_rows = 25;
0207:    }
0208:    else
0209:    {
0210:       if ( tgetent( tcbuf, term ) <= 0 )
0211:       {
0212:          goto fudge;
0213:          /* fatal ("No termcap entry for this terminal"); */
0214:       }
0215: 
0216:       cmbufp = cmbuf;
0217: 
0218:       GET_TC_STR( CE, "ce" );
0219:       GET_TC_STR( CL, "cl" );
0220:       GET_TC_STR( CM, "cm" );
0221:       GET_TC_STR( CS, "cs" );
0222:       GET_TC_STR( DL, "dl" );
0223:       GET_TC_STR( MD, "md" );
0224:       GET_TC_STR( ME, "me" );
0225:       GET_TC_STR( MR, "mr" );
0226:       GET_TC_STR( SE, "se" );
0227:       GET_TC_STR( SO, "so" );
0228:       GET_TC_STR( TE, "te" );
0229:       GET_TC_STR( TI, "ti" );
0230:       GET_TC_STR( UE, "ue" );
0231:       GET_TC_STR( US, "us" );
0232:       GET_TC_STR( KU, "ku" );
0233:       GET_TC_STR( KD, "kd" );
0234:       GET_TC_STR( KR, "kr" );
0235:       GET_TC_STR( KL, "kl" );
0236: 
0237:       if ( !KU || !*KU )
0238:       {
0239:          KU = "\033A";
0240:          KD = "\033B";
0241:          KL = "\033C";
0242:          KR = "\033D";
0243:       }
0244:       if ( screen_cols == 0 && ( screen_cols = tgetnum( "co" ) ) == -1 )
0245:          screen_cols = DEFAULT_COLS;
0246: 
0247:       if ( screen_rows == 0 && ( screen_rows = tgetnum( "li" ) ) == -1 )
0248:          screen_rows = DEFAULT_ROWS;
0249: 
0250:    }
0251:    if ( *MD == '\0' || *ME == '\0' || *MR == '\0' )
0252:    {
0253:       MD = SO;
0254:       ME = SE;
0255:       MR = SO;
0256:    }
0257:    if ( *UE == '\0' || *US == '\0' )
0258:    {
0259:       UE = SE;
0260:       US = SO;
0261:    }
0262: 
0263:    tputs( TI, 1, outc );
0264: 
0265:    clear_screen(  );
0266: 
0267:    row = screen_rows / 2 - 1;
0268:    col = ( screen_cols - ( sizeof ( JZIPVER ) - 1 ) ) / 2;
0269:    move_cursor( row, col );
0270:    display_string( JZIPVER );
0271:    row = screen_rows / 2;
0272:    col = ( screen_cols - ( sizeof ( "The story is loading..." ) - 1 ) ) / 2;
0273:    move_cursor( row, col );
0274:    display_string( "The story is loading..." );
0275: 
0276:    h_interpreter = INTERP_ATARI_ST;
0277: 
0278:    commands = ( char * ) malloc( hist_buf_size * sizeof ( char ) );
0279: 
0280:    if ( commands == NULL )
0281:       fatal( "initialize_screen(): Could not allocate history buffer!" );
0282:    BUFFER_SIZE = hist_buf_size;
0283:    space_avail = hist_buf_size - 1;
0284: 
0285:    set_cbreak_mode( 1 );
0286:    interp_initialized = 1;
0287: 
0288: }                               /* initialize_screen */
0289: 
0290: void restart_screen(  )
0291: {
0292:    zbyte_t high = 1, low = 0;
0293: 
0294:    cursor_saved = OFF;
0295: 
0296:    set_byte( H_STANDARD_HIGH, high );
0297:    set_byte( H_STANDARD_LOW, low );
0298:    if ( h_type < V4 )
0299:       set_byte( H_CONFIG, ( get_byte( H_CONFIG ) | CONFIG_WINDOWS ) );
0300:    else
0301:    {
0302:       /* turn stuff on */
0303:       set_byte( H_CONFIG,
0304:                 ( get_byte( H_CONFIG ) | CONFIG_BOLDFACE | CONFIG_EMPHASIS | CONFIG_FIXED |
0305:                   CONFIG_TIMEDINPUT ) );
0306: #if defined HARD_COLORS
0307:       set_byte( H_CONFIG, ( get_byte( H_CONFIG ) | CONFIG_COLOUR ) );
0308: #endif
0309:       /* turn stuff off */
0310:       set_byte( H_CONFIG, ( get_byte( H_CONFIG ) & ~CONFIG_PICTURES & ~CONFIG_SFX ) );
0311:    }
0312: 
0313:    /* Force graphics off as we can't do them */
0314:    set_word( H_FLAGS, ( get_word( H_FLAGS ) & ( ~GRAPHICS_FLAG ) ) );
0315: 
0316: }                               /* restart_screen */
0317: 
0318: void reset_screen(  )
0319: {
0320:    /* only do this stuff on exit when called AFTER initialize_screen */
0321:    if ( interp_initialized )
0322:    {
0323:       delete_status_window(  );
0324:       select_text_window(  );
0325:       set_attribute( NORMAL );
0326: 
0327:       set_cbreak_mode( 0 );
0328: 
0329:       tputs( TE, 1, outc );
0330:    }
0331: 
0332: }                               /* reset_screen */
0333: 
0334: void clear_screen(  )
0335: {
0336: 
0337:    tputs( CL, 1, outc );
0338:    current_row = 1;
0339:    current_col = 1;
0340: 
0341: }                               /* clear_screen */
0342: 
0343: void select_status_window(  )
0344: {
0345: 
0346:    save_cursor_position(  );
0347: 
0348: }                               /* select_status_window */
0349: 
0350: void select_text_window(  )
0351: {
0352: 
0353:    restore_cursor_position(  );
0354: 
0355: }                               /* select_text_window */
0356: 
0357: void create_status_window(  )
0358: {
0359:    int row, col;
0360: 
0361:    if ( *CS )
0362:    {
0363:       get_cursor_position( &row, &col );
0364: 
0365:       tputs( tgoto( CS, screen_rows - 1, status_size ), 1, outc );
0366: 
0367:       move_cursor( row, col );
0368:    }
0369: 
0370: }                               /* create_status_window */
0371: 
0372: void delete_status_window(  )
0373: {
0374:    int row, col;
0375: 
0376:    if ( *CS )
0377:    {
0378:       get_cursor_position( &row, &col );
0379: 
0380:       tputs( tgoto( CS, screen_rows - 1, 0 ), 1, outc );
0381: 
0382:       move_cursor( row, col );
0383:    }
0384: 
0385: }                               /* delete_status_window */
0386: 
0387: void clear_line(  )
0388: {
0389: 
0390:    tputs( CE, 1, outc );
0391: 
0392: }                               /* clear_line */
0393: 
0394: void clear_text_window(  )
0395: {
0396:    int i, row, col;
0397: 
0398:    get_cursor_position( &row, &col );
0399: 
0400:    for ( i = status_size + 1; i <= screen_rows; i++ )
0401:    {
0402:       move_cursor( i, 1 );
0403:       clear_line(  );
0404:    }
0405: 
0406:    move_cursor( row, col );
0407: 
0408: }                               /* clear_text_window */
0409: 
0410: void clear_status_window(  )
0411: {
0412:    int i, row, col;
0413: 
0414:    get_cursor_position( &row, &col );
0415: 
0416:    for ( i = status_size; i; i-- )
0417:    {
0418:       move_cursor( i, 1 );
0419:       clear_line(  );
0420:    }
0421: 
0422:    move_cursor( row, col );
0423: 
0424: }                               /* clear_status_window */
0425: 
0426: void move_cursor( row, col )
0427:    int row;
0428:    int col;
0429: {
0430: 
0431:    tputs( tgoto( CM, col - 1, row - 1 ), 1, outc );
0432:    current_row = row;
0433:    current_col = col;
0434: 
0435: }                               /* move_cursor */
0436: 
0437: void get_cursor_position( row, col )
0438:    int *row;
0439:    int *col;
0440: {
0441: 
0442:    *row = current_row;
0443:    *col = current_col;
0444: 
0445: }                               /* get_cursor_position */
0446: 
0447: void save_cursor_position(  )
0448: {
0449: 
0450:    if ( cursor_saved == OFF )
0451:    {
0452:       get_cursor_position( &saved_row, &saved_col );
0453:       cursor_saved = ON;
0454:    }
0455: 
0456: }                               /* save_cursor_position */
0457: 
0458: void restore_cursor_position(  )
0459: {
0460: 
0461:    if ( cursor_saved == ON )
0462:    {
0463:       move_cursor( saved_row, saved_col );
0464:       cursor_saved = OFF;
0465:    }
0466: 
0467: }                               /* restore_cursor_position */
0468: 
0469: void set_attribute( attribute )
0470:    int attribute;
0471: {
0472: 
0473:    if ( attribute == NORMAL )
0474:    {
0475:       tputs( ME, 1, outc );
0476:       tputs( UE, 1, outc );
0477:    }
0478: 
0479:    if ( attribute & REVERSE )
0480:       tputs( MR, 1, outc );
0481: 
0482:    if ( attribute & BOLD )
0483:       tputs( MD, 1, outc );
0484: 
0485:    if ( attribute & EMPHASIS )
0486:       tputs( US, 1, outc );
0487: 
0488:    if ( attribute & FIXED_FONT )
0489:       ;
0490: 
0491: }                               /* set_attribute */
0492: 
0493: static void display_string( s )
0494:    char *s;
0495: {
0496: 
0497:    while ( *s )
0498:       display_char( *s++ );
0499: 
0500: }                               /* display_string */
0501: 
0502: void display_char( c )
0503:    int c;
0504: {
0505: 
0506:    outc( c );
0507: 
0508:    if ( ++current_col > screen_cols )
0509:       current_col = screen_cols;
0510: 
0511: }                               /* display_char */
0512: 
0513: void scroll_line(  )
0514: {
0515:    int row, col;
0516: 
0517:    get_cursor_position( &row, &col );
0518: 
0519:    if ( *CS || row < screen_rows )
0520:    {
0521:       display_char( '\n' );
0522:    }
0523:    else
0524:    {
0525:       move_cursor( status_size + 1, 1 );
0526:       tputs( DL, 1, outc );
0527:       move_cursor( row, 1 );
0528:    }
0529: 
0530:    current_col = 1;
0531:    if ( ++current_row > screen_rows )
0532:       current_row = screen_rows;
0533: 
0534: }                               /* scroll_line */
0535: 
0536: int display_command( char *buffer )
0537: {
0538:    int counter, loop;
0539: 
0540:    move_cursor( row, head_col );
0541:    clear_line(  );
0542:    move_cursor( row, head_col );
0543:    /* ptr1 == end_ptr when the player has selected beyond any previously
0544:     * saved command */
0545:    if ( ptr1 == end_ptr )
0546:       return 0;
0547:    else
0548:    {
0549:       counter = 0;
0550:       for ( loop = ptr1; loop <= ptr2; loop++ )
0551:       {
0552:          buffer[counter] = commands[loop];
0553:          display_char( buffer[counter++] );
0554:       }
0555:       return counter;
0556:    }
0557: }
0558: 
0559: void get_prev_command( void )
0560: {
0561:    if ( ptr1 > 0 )
0562:    {
0563:       ptr2 = ptr1 -= 2;
0564:       if ( ptr1 < 0 )
0565:          ptr1 = 0;
0566:       if ( ptr2 < 0 )
0567:          ptr2 = 0;
0568:       if ( ptr1 > 0 )
0569:       {
0570:          do
0571:             ptr1--;
0572:          while ( ( commands[ptr1] != '\n' ) && ( ptr1 >= 0 ) );
0573:          ptr1++;
0574:       }
0575:    }
0576: }
0577: 
0578: void get_next_command( void )
0579: {
0580:    if ( ptr2 < end_ptr )
0581:    {
0582:       ptr1 = ptr2 += 2;
0583:       if ( ptr2 >= end_ptr )
0584:          ptr1 = ptr2 = end_ptr;
0585:       else
0586:       {
0587:          do
0588:             ptr2++;
0589:          while ( ( commands[ptr2] != '\n' ) && ( ptr2 <= end_ptr ) );
0590:          ptr2--;
0591:       }
0592:    }
0593: }
0594: 
0595: void get_first_command( void )
0596: {
0597:    if ( end_ptr > 1 )
0598:    {
0599:       ptr1 = ptr2 = 0;
0600:       do
0601:          ptr2++;
0602:       while ( ( commands[ptr2] != '\n' ) && ( ptr2 <= end_ptr ) );
0603:       ptr2--;
0604:    }
0605: 
0606: }
0607: 
0608: void delete_command( void )
0609: {
0610:    int loop;
0611: 
0612:    do
0613:    {
0614:       for ( loop = 0; loop < end_ptr; loop++ )
0615:       {
0616:          commands[loop] = commands[loop + 1];
0617:       }
0618:       end_ptr--;
0619:       space_avail++;
0620:    }
0621:    while ( commands[0] != '\n' );
0622:    for ( loop = 0; loop < end_ptr; loop++ )
0623:    {
0624:       commands[loop] = commands[loop + 1];
0625:    }
0626:    end_ptr--;
0627:    space_avail++;
0628:    ptr1 = ptr2 = end_ptr;
0629: }
0630: 
0631: void add_command( char *buffer, int size )
0632: {
0633:    int loop, counter;
0634: 
0635:    counter = 0;
0636:    for ( loop = end_ptr; loop < ( end_ptr + size ); loop++ )
0637:    {
0638:       commands[loop] = buffer[counter++];
0639:    }
0640:    end_ptr += size + 1;
0641:    ptr1 = ptr2 = end_ptr;
0642:    commands[end_ptr - 1] = '\n';
0643:    space_avail -= size + 1;
0644: }
0645: 
0646: 
0647: 
0648: 
0649: 
0650: 
0651: /*
0652:  * Patched 28-June-1995: Changed this routine's expectation of a \n to
0653:  *                       a \r so the form in Bureaucracy works.  Patch
0654:  *                       applied by John Holder.
0655:  */
0656: int input_character( int timeout )
0657: {
0658:    struct timeval tv;
0659:    struct timezone tz;
0660:    int c;
0661: 
0662:    /* gettimeofday (&tv, &tz);
0663:     *
0664:     * tv.tv_sec += timeout; */
0665: 
0666:    fflush( stdout );
0667: 
0668:    if ( timeout != 0 )
0669:    {
0670:       if ( wait_for_char( timeout ) )
0671:          return ( -1 );
0672:    }
0673: 
0674:    c = read_key(  );
0675: 
0676:    if ( c == '\n' )
0677:       c = '\r';
0678: 
0679:    return ( c );
0680: 
0681: }                               /* input_character */
0682: 
0683: int input_line( int buflen, char *buffer, int timeout, int *read_size )
0684: {
0685:    struct timeval tv;
0686:    struct timezone tz;
0687:    int c, col;
0688:    int init_char_pos, curr_char_pos, loop, tail_col, keyfunc = 0;
0689: 
0690:    get_cursor_position( &row, &col );
0691:    head_col = tail_col = col;
0692:    init_char_pos = curr_char_pos = *read_size;
0693:    ptr1 = ptr2 = end_ptr;
0694: 
0695: /*
0696:     if(timeout!=0)
0697:         {
0698:         gettimeofday (&tv, &tz);
0699:         tv.tv_usec+=timeout*100000;
0700:         while(tv.tv_usec>1000000)
0701:             {
0702:             tv.tv_sec++;
0703:             tv.tv_usec-=1000000;
0704:             }
0705:         }
0706: */
0707: 
0708:    for ( ;; )
0709:    {
0710: 
0711:       get_cursor_position( &row, &col );
0712:       keyfunc = 0;
0713:       /* Read a single keystroke */
0714:       fflush( stdout );
0715: 
0716:       if ( timeout != 0 )
0717:          if ( wait_for_char( timeout ) )
0718:             return ( -1 );
0719:       c = read_key(  );
0720: 
0721:       if ( keypad_avail )
0722:       {
0723:          if ( c == ( char ) *KU )
0724:          {
0725:             for ( loop = 0; loop < ( strlen( KU ) - 1 ); loop++ )
0726:                do
0727:                   c = Agetchar(  );
0728:                while ( c == '[' );
0729:             if ( c == ( unsigned char ) KU[strlen( KU ) - 1] )
0730:             {
0731:                get_prev_command(  );
0732:                curr_char_pos = *read_size = display_command( buffer );
0733:                tail_col = head_col + *read_size;
0734:                keyfunc = 1;
0735:             }
0736:             else if ( c == ( unsigned char ) KD[strlen( KD ) - 1] )
0737:             {
0738:                get_next_command(  );
0739:                curr_char_pos = *read_size = display_command( buffer );
0740:                tail_col = head_col + *read_size;
0741:                keyfunc = 1;
0742:             }
0743:             else if ( c == ( unsigned char ) KL[strlen( KL ) - 1] )
0744:             {
0745:                get_cursor_position( &row, &col );
0746:                if ( col > head_col )
0747:                {
0748:                   move_cursor( row, --col );
0749:                   curr_char_pos--;
0750:                }
0751:                keyfunc = 1;
0752:             }
0753:             else if ( c == ( unsigned char ) KR[strlen( KR ) - 1] )
0754:             {
0755:                get_cursor_position( &row, &col );
0756:                if ( col < tail_col )
0757:                {
0758:                   move_cursor( row, ++col );
0759:                   curr_char_pos++;
0760:                }
0761:                keyfunc = 1;
0762:             }
0763:          }
0764:       }
0765:       if ( keyfunc )
0766:          continue;
0767: 
0768:       if ( !keyfunc )
0769:       {
0770:          if ( c == '\b' )
0771:          {
0772:             /* Backspace */
0773:             get_cursor_position( &row, &col );
0774:             if ( col > head_col )
0775:             {
0776:                move_cursor( row, --col );
0777:                for ( loop = curr_char_pos; loop < *read_size; loop++ )
0778:                {
0779:                   buffer[loop - 1] = buffer[loop];
0780:                   display_char( buffer[loop - 1] );
0781:                }
0782:                display_char( ' ' );
0783:                curr_char_pos--;
0784:                tail_col--;
0785:                ( *read_size )--;
0786:                move_cursor( row, col );
0787:             }
0788:          }
0789:          else
0790:          {
0791:             /* Normal key action */
0792:             if ( *read_size == ( buflen - 1 ) )
0793:             {
0794:                /* Ring bell if buffer is full */
0795:                outc( BELL );
0796:             }
0797:             else
0798:             {
0799:                /* Scroll line if return key pressed */
0800:                if ( c == '\n' || c == '\r' )
0801:                {
0802:                   c = '\n';
0803:                   scroll_line(  );
0804:                }
0805:                if ( c == '\n' )
0806:                {
0807:                   if ( *read_size > BUFFER_SIZE )
0808:                      return ( c );
0809:                   while ( *read_size > space_avail )
0810:                   {
0811:                      delete_command(  );
0812:                   }
0813:                   if ( *read_size > 0 )
0814:                      add_command( buffer, *read_size );
0815:                   return c;
0816:                }
0817:                else
0818:                {
0819:                   get_cursor_position( &row, &col );
0820:                   if ( col < tail_col )
0821:                   {
0822:                      for ( loop = *read_size; loop >= curr_char_pos; loop-- )
0823:                         buffer[loop + 1] = buffer[loop];
0824:                      buffer[curr_char_pos] = ( char ) c;
0825:                      ( *read_size )++;
0826:                      tail_col++;
0827: #if 1
0828:                      move_cursor( row, col );
0829:                      for ( loop = curr_char_pos; loop < *read_size; loop++ )
0830:                         display_char( buffer[loop] );
0831:                      move_cursor( row, ++col );
0832:                      curr_char_pos++;
0833: #endif
0834: #if 0
0835:                      move_cursor( row, head_col );
0836:                      for ( loop = 0; loop < *read_size; loop++ )
0837:                         display_char( buffer[loop] );
0838:                      move_cursor( row, ++col );
0839: #endif
0840:                   }
0841:                   else
0842:                   {
0843:                      buffer[curr_char_pos++] = ( char ) c;
0844:                      display_char( c );
0845:                      ( *read_size )++;
0846:                      tail_col++;
0847:                   }
0848:                }
0849:             }
0850:          }
0851:       }
0852:    }
0853: }                               /* input_line */
0854: 
0855: long Systicks( void )
0856: {
0857:    long rval;
0858:    long sssp;
0859: 
0860:    sssp = Super( 0L );
0861:    rval = *_systicks;
0862:    Super( sssp );
0863:    return rval;
0864: }
0865: 
0866: static int wait_for_char( int timeout )
0867: {
0868:    int nfds, status;
0869:    fd_set readfds;
0870:    struct timeval tv;
0871:    struct timezone tz;
0872: 
0873:    printf( "timeout %d/ticks %ld\n", timeout, Systicks(  ) );
0874:    if ( !ismint )
0875:    {
0876:       /* if in TOS then the timeout value is just stored in tv.usec */
0877:       printf( "timeout %d/ticks %ld\n", timeout, Systicks(  ) );
0878:       timeout = ( timeout * 20 ) + Systicks(  );
0879:       while ( Systicks(  ) < ( long ) timeout )
0880:          if ( Cconis(  ) )
0881:             return 0;
0882:       return -1;
0883:    }
0884: 
0885:    gettimeofday( &tv, &tz );
0886: 
0887:    /*
0888:     * if (tv.tv_sec >= timeout->tv_sec && tv.tv_usec >= timeout->tv_usec)
0889:     * return (-1);
0890:     */
0891:    if ( !timeout )
0892:       return ( -1 );
0893: 
0894: /*
0895:     tv.tv_sec = timeout->tv_sec - tv.tv_sec;
0896:     if (timeout->tv_usec < tv.tv_usec) {
0897:     tv.tv_sec--;
0898:     tv.tv_usec = (timeout->tv_usec + 1000000) - tv.tv_usec;
0899:     } else
0900:     tv.tv_usec = timeout->tv_usec - tv.tv_usec;
0901: */
0902:    tv.tv_sec = ( timeout * 100000 ) / 1000000;
0903:    tv.tv_usec = ( timeout * 100000 ) % 1000000;
0904: 
0905:    /* used to be the following, but some boxen have no getdtablesize() */
0906:    /* nfds = getdtablesize (); */
0907:    nfds = FD_SETSIZE;
0908: 
0909:    FD_ZERO( &readfds );
0910:    FD_SET( fileno( stdin ), &readfds );
0911: 
0912:    status = select( nfds, &readfds, NULL, NULL, &tv );
0913:    if ( status < 0 )
0914:    {
0915:       perror( "select" );
0916:       return ( -1 );
0917:    }
0918: 
0919:    if ( status == 0 )
0920:       return ( -1 );
0921:    else
0922:       return ( 0 );
0923: 
0924: }                               /* wait_for_char */
0925: 
0926: static int Agetchar( void )
0927: {
0928:    static int holdover = 0;
0929:    int c, c1;
0930: 
0931:    if ( ismint )
0932:    {
0933:       c = getchar(  );
0934:       if ( c == 13 )
0935:          c = 10;
0936:       return c;
0937:    }
0938:    if ( holdover )
0939:    {
0940:       c = holdover;
0941:       holdover = 0;
0942:       return c;
0943:    }
0944:  reloop:
0945:    c1 = Cnecin(  );
0946:    if ( c1 & 0xff )
0947:       return c1 & 0xff;
0948:    c = ( ( c1 & 0x00ff0000 ) >> 16 );
0949:    switch ( c )
0950:    {
0951:       case 0x48:
0952:          holdover = 'A';
0953:          return 27;
0954:       case 0x50:
0955:          holdover = 'B';
0956:          return 27;
0957:       case 0x4b:
0958:          holdover = 'C';
0959:          return 27;
0960:       case 0x4d:
0961:          holdover = 'D';
0962:          return 27;
0963:       default:
0964:          goto reloop;
0965:    }
0966: }
0967: 
0968: 
0969: static int read_key(  )
0970: {
0971:    int c;
0972: 
0973:    c = Agetchar(  );
0974: 
0975: 
0976:    if ( c == 127 )
0977:       c = '\b';
0978:    else if ( c == 13 )
0979:       c = 10;
0980: 
0981:    return ( c );
0982: 
0983: }                               /* read_key */
0984: 
0985: static void set_cbreak_mode( mode )
0986:    int mode;
0987: {
0988:    int status;
0989: 
0990: #if defined(BSD)
0991:    struct sgttyb new_tty;
0992:    static struct sgttyb old_tty;
0993: #endif /* defined(BSD) */
0994: #if defined(SYSTEM_FIVE)
0995:    struct termio new_termio;
0996:    static struct termio old_termio;
0997: #endif /* defined(SYSTEM_FIVE) */
0998: #if defined(POSIX)
0999:    struct termios new_termios;
1000:    static struct termios old_termios;
1001: #endif /* defined(POSIX) */
1002: 
1003: #if defined(BSD)
1004:    status = ioctl( fileno( stdin ), ( mode ) ? TIOCGETP : TIOCSETP, &old_tty );
1005: #endif /* defined(BSD) */
1006: #if defined(SYSTEM_FIVE)
1007:    status = ioctl( fileno( stdin ), ( mode ) ? TCGETA : TCSETA, &old_termio );
1008: #endif /* defined(SYSTEM_FIVE) */
1009: #if defined(POSIX)
1010:    if ( mode )
1011:       status = tcgetattr( fileno( stdin ), &old_termios );
1012:    else
1013:       status = tcsetattr( fileno( stdin ), TCSANOW, &old_termios );
1014: #endif /* defined(POSIX) */
1015:    if ( status && ismint )
1016:    {
1017:       perror( "ioctl" );
1018:       exit( 1 );
1019:    }
1020: 
1021:    if ( mode )
1022:    {
1023:       signal( SIGINT, rundown );
1024:       signal( SIGTERM, rundown );
1025:    }
1026: 
1027:    if ( mode )
1028:    {
1029: #if defined(BSD)
1030:       status = ioctl( fileno( stdin ), TIOCGETP, &new_tty );
1031: #endif /* defined(BSD) */
1032: #if defined(SYSTEM_FIVE)
1033:       status = ioctl( fileno( stdin ), TCGETA, &new_termio );
1034: #endif /* defined(SYSTEM_FIVE) */
1035: #if defined(POSIX)
1036:       status = tcgetattr( fileno( stdin ), &new_termios );
1037: #endif /* defined(POSIX) */
1038:       if ( status && ismint )
1039:       {
1040:          perror( "ioctl" );
1041:          exit( 1 );
1042:       }
1043: 
1044: #if defined(BSD)
1045:       new_tty.sg_flags |= CBREAK;
1046:       new_tty.sg_flags &= ~ECHO;
1047: #endif /* defined(BSD) */
1048: #if defined(SYSTEM_FIVE)
1049:       new_termio.c_lflag &= ~( ICANON | ECHO );
1050: #endif /* defined(SYSTEM_FIVE) */
1051: #if defined(POSIX)
1052:       new_termios.c_lflag &= ~( ICANON | ECHO );
1053: 
1054:       /* the next two lines of code added by Mark Phillips.  The patch */
1055:       /* was for sun and __hpux, active only if those were #defined,   */
1056:       /* but most POSIX boxen (SunOS, HP-UX, Dec OSF, Irix for sure)   */
1057:       /* can use this... It makes character input work.  VMIN and      */
1058:       /* VTIME are reused on some systems, so when the mode is switched */
1059:       /* to RAW all character access is, by default, buffered wrong.   */
1060:       /* For the curious: VMIN='\004' and VTIME='\005' octal on        */
1061:       /* these systems.  VMIN is usually EOF and VTIME is EOL. (JDH)   */
1062:       new_termios.c_cc[VMIN] = 1;
1063:       new_termios.c_cc[VTIME] = 2;
1064: #endif /* defined(POSIX) */
1065: 
1066: #if defined(BSD)
1067:       status = ioctl( fileno( stdin ), TIOCSETP, &new_tty );
1068: #endif /* defined(BSD) */
1069: #if defined(SYSTEM_FIVE)
1070:       status = ioctl( fileno( stdin ), TCSETA, &new_termio );
1071: #endif /* defined(SYSTEM_FIVE) */
1072: #if defined(POSIX)
1073:       status = tcsetattr( fileno( stdin ), TCSANOW, &new_termios );
1074: #endif /* defined(POSIX) */
1075:       if ( status && ismint )
1076:       {
1077:          perror( "ioctl" );
1078:          exit( 1 );
1079:       }
1080:    }
1081: 
1082:    if ( mode == 0 )
1083:    {
1084:       signal( SIGINT, SIG_DFL );
1085:       signal( SIGTERM, SIG_DFL );
1086:    }
1087: 
1088: }                               /* set_cbreak_mode */
1089: 
1090: static void rundown(  )
1091: {
1092:    unload_cache(  );
1093:    close_story(  );
1094:    close_script(  );
1095:    reset_screen(  );
1096: }                               /* rundown */
1097: 
1098: 
1099: 
1100: 
1101: 
1102: 
1103: 
1104: 
1105: 
1106: 
1107: /*
1108:  * codes_to_text
1109:  *
1110:  * Translate Z-code characters to machine specific characters. These characters
1111:  * include line drawing characters and international characters.
1112:  *
1113:  * The routine takes one of the Z-code characters from the following table and
1114:  * writes the machine specific text replacement. The target replacement buffer
1115:  * is defined by MAX_TEXT_SIZE in ztypes.h. The replacement text should be in a
1116:  * normal C, zero terminated, string.
1117:  *
1118:  * Return 0 if a translation was available, otherwise 1.
1119:  *
1120:  *  Arrow characters (0x18 - 0x1b):
1121:  *
1122:  *  0x18 Up arrow
1123:  *  0x19 Down arrow
1124:  *  0x1a Right arrow
1125:  *  0x1b Left arrow
1126:  *
1127:  *  International characters (0x9b - 0xa3):
1128:  *
1129:  *  0x9b a umlaut (ae)
1130:  *  0x9c o umlaut (oe)
1131:  *  0x9d u umlaut (ue)
1132:  *  0x9e A umlaut (Ae)
1133:  *  0x9f O umlaut (Oe)
1134:  *  0xa0 U umlaut (Ue)
1135:  *  0xa1 sz (ss)
1136:  *  0xa2 open quote (>>)
1137:  *  0xa3 close quota (<<)
1138:  *
1139:  *  Line drawing characters (0xb3 - 0xda):
1140:  *
1141:  *  0xb3 vertical line (|)
1142:  *  0xba double vertical line (#)
1143:  *  0xc4 horizontal line (-)
1144:  *  0xcd double horizontal line (=)
1145:  *  all other are corner pieces (+)
1146:  *
1147:  */
1148: 
1149: int codes_to_text( int c, char *s )
1150: {
1151:    return 1;
1152: }                               /* codes_to_text */