/* * RTERM.C * * Terminal emulator for iRMX Version 1.0 * * HISTORY: * * - Version X.01 to X.10: * * Prototype software, many features added * and many bug fixes. Nam Ly 02/29/90 * * - Version 1.0: * First version checked into the source data base, many features * added and many bug fixes. Nam Ly 09/15/90 * */ #include #include #include #include #include #include "rterm.h" /* * -- External declaration */ extern int kb_char(void); extern void set_dos_flag(void); extern unsigned pascal RQLookupObject(unsigned, unsigned char far *, unsigned, unsigned far *); extern void pascal RQSendMessage(unsigned, unsigned, unsigned, unsigned far *); extern unsigned pascal RQGetTaskTokens(unsigned char, unsigned far *); #define VERSION "V1.0" char version[] = "program_version_number=V1.0program_name=RTERM"; static char cpyrt[] = {0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,}; static char name[] = " 1989 Intel Corporation"; #define EOK 0 #define rootjob 3 #define callingtask 0 static unsigned roottoken; static unsigned vm86j; static unsigned Kb_Mux; static unsigned except; static unsigned response; static unsigned segment; static unsigned rootjobtoken; unsigned char vm86[12] ={10,'R','?','V','M','8','6','_','J','O','B',0}; unsigned char kb_mb[14] ={12,'R','?','K','B','_' ,'M','A','I','L','B','O','X',0}; union REGS ireg; /* * Standard way of doing things */ static void set_cursor(unsigned char, unsigned char); static unsigned int get_key(void); static void set_page(unsigned int); static void get_mode(void); static void set_mode(unsigned char); static unsigned char get_cols(void); static void str_copy(int *, int *, unsigned int); static void update_screen(void); static void restore(void); static void set_screen_attrib(void); static void set_forg_col(void); static void set_back_col(void); static void send_data(unsigned int); static unsigned int restore_r_screen(void); static unsigned int save_r_screen(void); OUT_BUFFER far *out_buf= MK_FP (0x0040, 0xE0); IN_BUFFER far *in_buf = MK_FP (0x0040, 0xE2); /* * ----------------------- Main Program ------------------------------------ */ main() { printf("\niRMX Terminal emulator, "); printf(VERSION); printf("\n%s%s\n",cpyrt,name); /* * The following copyright message is printed ONLY because of the * licensing agreement associated with the Microsoft C compiler. * It must be removed if this utility is ever generated with a * different compiler. */ printf("%s (c) Microsoft Corp 1984, 1985, 1986, 1987.",cpyrt); printf(" All rights reserved.\n\n"); /* * initialize save buffer ptr */ save_buff = (int far *)save_buffer; /* * Set up the screen attribute */ forground = (WHITE | HI_INTENS); background = BLUE; r_term.row = CRTROWS; /* Set number of rows */ get_mode(); r_term.column = get_cols(); /* Get columns */ r_term.crtlen = r_term.row * r_term.column; r_term.console_state = 0; /* ???? */ r_term.output_state = 0; /* ???? */ r_term.routine_index = 0; /* default */ r_term.displayw = ((background << 4) + forground) << 8; /* Set colors */ /* * Find base address of display memory */ FP_SEG(video_p) = (r_term.mode == 7) ? 0xb000 : 0xb800; FP_OFF(video_p) = 0; /* * save stuff on the DOS screen */ movedata (FP_SEG(video_p), FP_OFF(video_p), /* source seg. off. */ FP_SEG(save_buff), FP_OFF(save_buff), /* destin seg. off. */ 4000); /* count */ if ( !restore_r_screen() ) { /* * blank the screen */ temp_ptr =(int far *) video_p; for(tmp=0; tmp < r_term.crtlen; tmp++) { (*temp_ptr++) = r_term.displayw; } /* * put the cursor to top of screen */ r_term.row = 0; r_term.column = 0; set_cursor(r_term.row, r_term.column); } Stop_output = FALSE; /* * initialize input/output buffer @ iRMX comm. area */ if( in_buf->count > 29 ) in_buf->count = 0; Num_chars = 0; out_buf->flag_byte = 0; out_buf->data_byte = 0; roottoken = RQGetTaskTokens(rootjob,&except); if (except != EOK) { printf("RQGetTaskTokens fail, error: %X\n", except); exit(0); } vm86j = RQLookupObject(roottoken,&vm86[0],0,&except); if (except != EOK) { printf("RQLookupObject fail, error: %X\n", except); exit(0); } Kb_Mux = RQLookupObject(vm86j,&kb_mb[0],0,&except); if (except != EOK) { printf("RQLookupObject fail, error: %X\n", except); exit(0); } response = 0; segment = Kb_Mux; for (;;) /* forever loop */ { if( kb_char() ) /* keyboard data is available */ { if(Stop_output) /* output is stopped */ { Stop_output = FALSE; /* then enable screen output */ temp = get_key(); /* and flush the kb buffer */ } else { switch (temp = get_key()) { case 0x0E08: /* Backspace key */ temp = 0x7f; send_data(temp); break; case 0x1011: /* Control-Q */ Stop_output = FALSE; break; case 0x1117: /* Control-W */ temp = 0x17; send_data(temp); break; case 0x1312: /* Control-R */ temp = 0x12; send_data(temp); break; case 0x1910: /* Control-P */ temp = 0x10; send_data(temp); break; case 0x1F13: /* Control-S */ Stop_output = TRUE; break; case 0x2C1A: /* Control-Z */ temp = 0x1A; send_data(temp); break; case 0x2D18: /* Control-X */ temp = 0x18; send_data(temp); break; case 0x8200: /* ALT (minus) */ set_back_col(); break; case 0x8300: /* ALT (plus) */ set_forg_col(); break; case 0x2d00: /* ALT-X exit program */ save_r_screen(); restore(); /* restore the screen */ exit(0); case 0x2300: /* ALT-H key */ break; case 0x2E03: /* Control-C key */ break; case 0x4700: /* Home key */ temp = 0x1d; send_data(temp); break; case 0x4900: /* Page-up key */ break; case 0x4F00: /* End key */ break; case 0x5100: /* Page down */ break; case 0x4800: /* Up arrow */ temp = 0x1e; send_data(temp); break; case 0x4B00: /* Left arrow */ temp = 0x1f; send_data(temp); break; case 0x4D00: /* Right arrow */ temp = 0x19; send_data(temp); break; case 0x5000: /* Down arrow */ temp = 0x1c; send_data(temp); break; case 0x7500: /* Ctrl-End */ *bflag_ptr = 0x1234; /* skip the mem. test */ outp(0x64, 0xFC); /* do warm reset */ break; case 0x7700: /* Ctrl-Home */ temp = 0xEE; /* Break to SDM mon */ send_data(temp); break; case 0x7200: /* Ctrl-SysRq */ case 0x7600: /* Ctrl-Pgdn */ temp = 0xEF; /* reload DOS frm. RMX */ send_data(temp); break; default: /* send characters to the comm area for iRMX */ send_data(temp); break; } } } /* * check the comm. area and process characters from iRMX driver * and display them. */ if (((in_buf->count) > 0) && (Num_chars == 0)) { /* * copy data from iRMX to local buffer */ for(tmp=0; tmp < in_buf->count; tmp++) Temp_str[tmp] = in_buf->data_byte[tmp]; Num_chars = in_buf->count; /* save count for update_screen */ in_buf->count = 0; /* tell RMX we read the data */ } update_screen(); /* write data to screen */ } /* end forever!!!??? */ restore(); /* restore the DOS screen */ exit(0); } /* --------------------- end of main code section ------------------------ */ /* * ----------------------- Local procedures ------------------------------- * * Title : update_screen * Process characters from the input data segment and update screen */ void update_screen() { if ( ( Stop_output ) || ( Num_chars == 0) ) return; for (index = 0; index <= Num_chars - 1; index++) { /* * Get one character from buffer */ X_char = Temp_str[index]; switch (r_term.routine_index) { case 0 : /* routine$index = 0 - ordinary character */ { if (X_char < DISPLAYABLECHAR && (r_term.console_state & LITERALMODE) == 0) switch (X_char) { case 0 : { /* CASE 0 - */ } break; case 1 : /* CASE 1 - erase rest of screen */ { temp_w = r_term.displayw + BLANKCHARACTER; t_count = (CRTCOLS * (CRTROWS - r_term.row - 1) + CRTCOLS - r_term.column); des_ptr =(int far *) video_p+(r_term.row * CRTCOLS + r_term.column); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } break; case 2 : /* CASE 2 - erase line */ { temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS; des_ptr =(int far *) video_p+(r_term.row * CRTCOLS); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } break; case 3 : /* CASE 3 - erase rest of line */ { temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS - r_term.column; des_ptr =(int far *) video_p+(r_term.row * CRTCOLS + r_term.column); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } break; case 4 : /* CASE 4 - cursor absolute */ { r_term.routine_index = 1; } break; case 5 : /* CASE 5 - line delete */ { t_count = (LASTROW - r_term.row) * CRTCOLS * 2; src_ptr =(int far *) video_p+((r_term.row + 1) * CRTCOLS); des_ptr =(int far *) video_p+(r_term.row * CRTCOLS); movedata (FP_SEG(src_ptr), FP_OFF(src_ptr), /* source seg. off. */ FP_SEG(des_ptr), FP_OFF(des_ptr), /* destin seg. off. */ t_count); /* count */ temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS; des_ptr =(int far *) video_p+(LASTROW * CRTCOLS); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } break; case 6 : /* CASE 6 - line insert */ { t_count = (LASTROW - r_term.row) * CRTCOLS; src_ptr =(int far *) video_p+(r_term.row * CRTCOLS) + t_count; des_ptr =(int far *) video_p+((r_term.row + 1) * CRTCOLS) + t_count; for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr--) = (*src_ptr--); } temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS; des_ptr =(int far *) video_p+(r_term.row * CRTCOLS); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } break; case 7 : /* CASE 7 - bell */ { } break; case 8 : /* CASE 8 - backspace */ { if (r_term.column == 0) { if (r_term.row > 0) { --r_term.row; r_term.column = LASTCOL; } } else --r_term.column; } break; case 9 : /* CASE 9 - tab */ { /* CASE 9 - tab */ } break; case 10 : /* CASE 0A - linefeed */ { if (r_term.row >= LASTROW) { t_count = CRTCOLS * LASTROW * 2; src_ptr =(int far *) video_p + CRTCOLS; des_ptr =(int far *) video_p; movedata (FP_SEG(src_ptr), FP_OFF(src_ptr), /* source seg. off. */ FP_SEG(des_ptr), FP_OFF(des_ptr), /* destin seg. off. */ t_count); /* count */ temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS; des_ptr =(int far *) video_p+(CRTCOLS * LASTROW); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } else ++r_term.row; } break; case 11 : /* CASE 0B - set color */ { r_term.routine_index = 3; } break; case 12 : /* CASE 0C - erase screen */ { temp_w = r_term.displayw + BLANKCHARACTER; des_ptr =(int far *) video_p; for(tmp=0; tmp < r_term.crtlen; ++tmp) { (*des_ptr++) = temp_w; } r_term.row = 0; r_term.column = 0; } break; case 13 : /* CASE 0D - CR */ { r_term.column = 0; } break; case 14 : /* CASE 0E - literal */ { r_term.console_state = r_term.console_state | LITERALMODE; } break; case 15 : /* CASE 0F - set raw mode */ { r_term.console_state = r_term.console_state | RAWMODE; } break; case 16 : /* CASE 10 - set cooked mode */ { r_term.console_state = r_term.console_state & ~RAWMODE; } break; case 17 : /* CASE 11 - X-ON */ { /* CASE 11 - X-ON */ } break; case 18 : /* CASE 12 */ { /* CASE 12 */ } break; case 19 : /* CASE 13 - X-OFF */ { /* CASE 13 - X-OFF */ } break; case 20 : /* CASE 14 */ { /* CASE 14 */ } break; case 21 : /* CASE 15 */ { /* CASE 15 */ } break; case 22 : /* CASE 16 */ { /* CASE 16 */ } break; case 23 : /* CASE 17 */ { /* CASE 17 */ } break; case 24 : /* CASE 18 */ { /* CASE 18 */ } break; case 25 : /* CASE 19 - cursor right */ { if (r_term.column >= LASTCOL) { if (r_term.row < LASTROW) { ++r_term.row; r_term.column = 0; } } else { ++r_term.column; } } break; case 26 : /* CASE 1A */ { /* CASE 1A */ } break; case 27 : /* CASE 1B */ { /* CASE 1B */ } break; case 28 : /* CASE 1C - cursor down */ { if (r_term.row != LASTROW) ++r_term.row; } break; case 29 : /* CASE 1D - cursor home */ { r_term.row = 0; r_term.column = 0; } break; case 30 : /* CASE 1E - cursor up */ { if (r_term.row != 0) --r_term.row; } break; case 31 : /* CASE 1F - cursor left */ { if (r_term.column == 0) { if (r_term.row > 0) { --r_term.row; r_term.column = LASTCOL; } } else --r_term.column; } break; } /* CASE char */ else /* process normal character */ { r_term.console_state = r_term.console_state & ~LITERALMODE; /* write the characrer to display ram at current cursor pos. */ (*video_p)[r_term.row * CRTCOLS + r_term.column] = r_term.displayw + X_char; /* update cursor position */ ++r_term.column; if (r_term.column > LASTCOL) { r_term.column = 0; if (r_term.row >= LASTROW) { /* scroll the display up one line */ t_count = CRTCOLS * LASTROW * 2; src_ptr =(int far *) video_p + CRTCOLS; des_ptr =(int far *) video_p; movedata (FP_SEG(src_ptr), FP_OFF(src_ptr), /* source seg. off. */ FP_SEG(des_ptr), FP_OFF(des_ptr), /* destin seg. off. */ t_count); /* count */ /* erase the last line on the screen */ temp_w = r_term.displayw + BLANKCHARACTER; t_count = CRTCOLS; des_ptr =(int far *) video_p+(CRTCOLS * LASTROW); for(tmp=0; tmp < t_count; ++tmp) { (*des_ptr++) = temp_w; } } else ++r_term.row; } } } /* of case 0 => routine$index = 0 */ break; case 1 : /* routine$index = 1 - second byte of absolute cursor position */ { r_term.routine_index = 2; temp = X_char - 0x20; if (temp < CRTROWS) r_term.row = temp; else r_term.row = 0; } break; case 2 : /* routine$index = 2 - third byte of absolute cursor position */ { r_term.routine_index = 0; temp = X_char - 0x20; if (temp <= CRTCOLS) r_term.column = temp; else r_term.column = 0; } /* routine$index = 3 - second byte of set foreground color */ break; case 3 : { r_term.routine_index = 0; r_term.displayw = X_char * 256; } break; } /* CASE routine$index */ } /* of DO index */ End_of_output: Num_chars = 0; set_cursor(r_term.row, r_term.column); } /* End update_screen */ /* * Title: get_mode * Determine the display mode. * * Return: r_term.mode * r_term.page * r_term.column */ void get_mode(void) { ireg.h.ah = 0x0f; int86(0x10, &ireg, &ireg); r_term.mode = (ireg.h.al); r_term.page = (ireg.h.bh); r_term.column = (ireg.h.ah); } /* * Title: set_mode * Set the display mode for the video device. */ void set_mode(unsigned char mode) { ireg.h.ah = 0x00; /* Function 0 */ ireg.h.al = mode; int86(0x10, &ireg, &ireg); } /* * Title: get_cols() * Determine the number of columns being used by the video display * via interrupt 0x10, function 0x0f. * Return: number of columns (40 or 80). */ unsigned char get_cols(void) { ireg.h.ah = 0x0f; int86(0x10, &ireg, &ireg); /* mode is returned in ireg.h.al */ if (ireg.h.al < 2) return 40; /* 40-column mode */ if (ireg.h.al > 3 && ireg.h.al != 7) return 0; /* Return 0 for any graphics mode */ else return 80; /* 80-column mode */ } /* * Title: set_page * Set the currently-active video page. */ #define MAXPAGE 8 void set_page(unsigned int page) { ireg.h.ah = 0x05; /* Function */ ireg.h.al = (page % MAXPAGE); int86(0x10, &ireg, &ireg); } /* * Title: read_cursor() * Read the current row and column position of the cursor. * Input: int *row and int *col */ void read_cursor(int *row, int *col) { ireg.h.ah = 0x03; /* Function */ ireg.h.bh = r_term.page; /* Current page */ int86(0x10, &ireg, &ireg); *row = (int) ireg.h.dh; *col = (int) ireg.h.dl; } /* * Title: set_cursor */ void set_cursor(unsigned char row, unsigned char col) { ireg.h.ah = 0x02; /* Function */ ireg.h.bh = r_term.page; /* Current page */ ireg.h.dh = row; ireg.h.dl = col; int86(0x10, &ireg, &ireg); } /* * Title: send_data * Copy a byte of data to iRMX buffer */ void send_data(unsigned int data_byte) { if (!(out_buf->flag_byte)) { out_buf->data_byte = (unsigned char) (data_byte & 0x00ff); out_buf->flag_byte = TRUE; RQSendMessage(Kb_Mux, segment, response, &except); if (except != EOK) { printf("RQSendMessage fail, error: %X\n", except); exit(0); } } } /* * Title: get_key */ unsigned int get_key() { ireg.h.ah = 0; /* Get next key from keyboard */ int86(0x16, &ireg, &ireg); return(ireg.x.ax); } /* * Title restore * Restore the screen */ void restore() { movedata (FP_SEG(save_buff), FP_OFF(save_buff), /* source seg. off. */ FP_SEG(video_p), FP_OFF(video_p), /* destin seg. off. */ 4000); /* count */ r_term.row = 25; r_term.column = 0; set_cursor(r_term.row, r_term.column); } /* * Title: str_copy() */ void str_copy(int *source, int *target, unsigned int count) { while (count !=0) { *target++ = *source++; --count; } } /* * Change forground color */ void set_forg_col() { if( ((++forground) && 0x1f) > 0x0f ) forground = 0; if (forground == background) { if( ((++forground) && 0x1f) > 0x0f ) forground = 0; } r_term.displayw = ((((background << 4) + forground) << 8) & 0x7f00 ); set_screen_attrib(); } /* * Change background color */ void set_back_col() { if( ((++background) && 0x0f) > 0x07 ) background = 0; if (forground == background) { if( ((++background) && 0x0f) > 0x07 ) background = 0; } r_term.displayw = ((((background << 4) + forground) << 8) & 0x7f00 ); set_screen_attrib(); } /* * Title: set_screen_attrib * Set attribute for the whole screen */ void set_screen_attrib() { unsigned char far *tmp_ptr; unsigned int temp_b; unsigned char x; unsigned int y; temp_b = (r_term.displayw >> 8); x = (char) temp_b; x &= NO_BLINK; tmp_ptr =(char far *) video_p +1; for(y=1; y <= 2000; ++y) { (*tmp_ptr) = (char) x; tmp_ptr += 2; } } /* * Title: save_r_screen * Save iRMX screen in file RMX$$$.SCR */ unsigned int save_r_screen() { int *buff_ptr, *last_b_ptr; int far *screen_ptr; int fd_out, bytes; if ((fd_out = open("\\RMX$$$.SCR", O_WRONLY|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) < 0) { return(FALSE); /* error open file */ } /* Copy the screen into a near buffer. */ last_b_ptr = &Temp_Buff[SCREENLENGTH]; buff_ptr = Temp_Buff; screen_ptr = (int far *) video_p; for (; buff_ptr < last_b_ptr; ++buff_ptr, ++screen_ptr) *buff_ptr = *screen_ptr; /* Write it to file. */ bytes = write(fd_out, Temp_Buff, SCREENLENGTH * 2); if (bytes != SCREENLENGTH * 2) { close(fd_out) ; return(FALSE); /* error writing file */ } /* * Save screen cursor location to file */ Temp_Buff[0] = ( (r_term.row << 8) + r_term.column ); bytes = write(fd_out, Temp_Buff, 2); /* * Save screen attribute */ Temp_Buff[0] = r_term.displayw; bytes = write(fd_out, Temp_Buff, 2); close(fd_out) ; return(TRUE); } /* * Title: restore_r_screen * Restore iRMX screen from file RMX$$$.SCR */ unsigned int restore_r_screen() { int *buff_ptr, *last_b_ptr; int far *screen_ptr; int fd_in, bytes, Temp_W; if ((fd_in = open("\\RMX$$$.SCR", O_RDONLY | O_BINARY)) < 0) { return(FALSE); /* error open file */ } /* Read the file into buffer. */ bytes = read(fd_in, Temp_Buff, SCREENLENGTH * 2); if (bytes <= 0) { close(fd_in) ; return(FALSE); /* error reading file */ } /* Copy the buffer to screen memory. */ last_b_ptr = &Temp_Buff[bytes / 2]; buff_ptr = Temp_Buff; screen_ptr = (int far *) video_p; for (; buff_ptr < last_b_ptr; ++buff_ptr, ++screen_ptr) *screen_ptr = *buff_ptr; /* * read the screen cursor location from file */ bytes = read(fd_in, Temp_Buff, 2); Temp_W = Temp_Buff[0]; r_term.row = (unsigned char) (Temp_W >> 8); Temp_W = Temp_Buff[0]; r_term.column = (unsigned char) (Temp_W); /* * read screen attribute */ bytes = read(fd_in, Temp_Buff, 2); r_term.displayw = Temp_Buff[0]; close(fd_in) ; set_cursor(r_term.row, r_term.column); return(TRUE); }