/* =====> ZCIO.C */ /* TIPC Scheme Runtime Support - Window Input/Output Support (C) Copyright 1985 by Texas Instruments Incorporated. All rights reserved. Author: John C. Jensen Installation: Texas Instruments Incorporated, Dallas, Texas Division: Central Research Laboratories Cost Center: Computer Science Laboratory Project: Computer Architecture Branch Date Written: 1 February 1985 Last Modification: 11 Feb 86 - Fixed READ-CHAR for "read from string". - added a call to "force-reset" after an error was encountered in routine "takechar". - modified routine "takechar" to correctly report an error when an invalid status is returned from a write. Added the message "Write error: DOS error code X". April 86 - Most codes are moved to Assembly language. The modules left are: clear_window, gc_on, gc_off */ #include "scheme.h" #include "sport.h" extern unsigned GC_ING; /* Garbage collecting indicator */ /********************** Following Code commented out #include "slist.h" int prn_handle = 0; /* current printer handle */ static int handle = 0; /* current port file's handle */ static int port_disp = 0; /* current port displacement */ static int port_page = 0; /* current port page number */ static int port_reg[2] = {0,0}; /* current port pointer */ static int window_p = FALSE; /* flag indicating if port is a window */ static int string_p = FALSE; /* flag indicating string I/O */ #define NUM_FIELDS 12 static int defaults[NUM_FIELDS] = {0, /* cursor line number */ 0, /* cursor column number */ 0, /* upper left corner line number */ 0, /* upper left corner column number */ 25, /* number of lines */ 80, /* number of columns */ -1, /* no border */ 15, /* text high intensity, enable */ 1, /* wrap enabled */ 0, /* current buffer position */ 0, /* current buffer end */ TRANSCRIPT+BINARY+WINDOW+OPEN+READ_WRITE}; /* port attributes */ static int map_attr[NUM_FIELDS] = {10,12,14,16,18,20,22,24,26,28,30,6}; /* Extended Character Definitions */ #define F3 0x003d #define F5 0x003f #define LEFT_ARROW 0x004b #define RIGHT_ARROW 0x004d #define ENTER_KEY 0x000d #define INSERT 0x0052 #define DELETE 0x0053 char *getmem(); /* Lattice C's memory allocation support */ /************************************************************************/ /* Allocate a Window */ /************************************************************************/ make_window(reg) int reg[2]; /* register to receive pointer to window object */ { int disp; /* displacement component of a pointer */ int i; /* index variable */ int page; /* page number component of a pointer */ int retstat = 0; /* the return status */ ENTER(make_window); page = CORRPAGE(reg[C_PAGE]); if (ptype[page] == STRTYPE*2 || (!page)) { /* allocate window object (port data type) */ mov_reg(tmp_reg, reg); /* save pointer to window label */ alloc_block(reg, PORTTYPE, WINDSIZE+BUFFSIZE); page = CORRPAGE(reg[C_PAGE]); disp = reg[C_DISP]; zero_blk(page,disp); /* initialize fields of window object */ for (i = 0; i < NUM_FIELDS; i++) put_word(page, disp+map_attr[i], defaults[i]); /* store window label pointer into window object */ put_ptr(page, disp+STR_PTR, tmp_page, tmp_disp); } else { set_src_err("MAKE-WINDOW", 1, reg); retstat = -1; } return(retstat); } /* end of function: make_window(reg) */ ************************************************/ /************************************************************************/ /* Clear Window */ /************************************************************************/ clear_window(reg) int reg[2]; /* register containing port pointer */ { int b_attrib; /* border attributes */ int disp; /* displacement component of a pointer */ /*%%int i; /* index variable */*/ /*%%int len; /* label length (in characters) */*/ int n_cols; /* number of columns in the window */ int n_lines; /* number of lines in the window */ int page; /* page number component of a pointer */ int retstat = 0; /* the return status */ char *string; /* buffer pointer for label's text */ int t_attrib; /* text attributes */ int ul_col; /* upper left corner's column number */ int ul_line; /* upper left corner's line number */ char *string_asciz(); /* fetches characters of a string */ ENTER(clear_window); get_port(reg,0); page = CORRPAGE(tmp_page); disp = tmp_disp; if (ptype[page] == PORTTYPE*2 && get_byte(page, disp+P_FLAGS) & WINDOW) { pt_flds4(tmp_reg, &ul_line, &ul_col, &n_lines, &n_cols); t_attrib = get_word(page, disp+T_ATTRIB); b_attrib = get_word(page, disp+B_ATTRIB); zclear(ul_line, ul_col, n_lines, n_cols, t_attrib); if (b_attrib != -1) { tmp_page = get_byte(page, disp+STR_PTR); tmp_disp = get_word(page, disp+STR_PTR+1); string = string_asciz(tmp_reg); zborder(ul_line, ul_col, n_lines, n_cols, b_attrib, string); rlsstr(string); } /* put the cursor in the "home" position (upper left hand corner) */ put_word(page, disp+CUR_LINE, 0); put_word(page, disp+CUR_COL, 0); } else { set_src_err("WINDOW-CLEAR", 1, reg); retstat = -1; } return(retstat); } /* end of function: clear_window(reg) */ /************ /************************************************************************/ /* Get Window Attribute */ /************************************************************************/ get_window_attribute(reg, attr) int reg[2]; /* register containing port pointer */ int attr[2]; /* attribute number */ { int attribute; /* index of the attribute desired */ int disp; /* displacement component of a pointer */ int page; /* page number component of a pointer */ int retstat = 0; /* the return status */ ENTER(get_window_attribute); get_port(reg, 1); page = CORRPAGE(tmp_page); disp = tmp_disp; if (ptype[page] == PORTTYPE*2 && attr[C_PAGE] == SPECFIX*2 && (attribute = get_fix(CORRPAGE(attr[C_PAGE]),attr[C_DISP])) >= 0 && attribute < NUM_FIELDS) { reg[C_PAGE] = SPECFIX*2; reg[C_DISP] = get_word(page, disp+map_attr[attribute]) & 0x7fff; } else { set_src_err("%REIFY-PORT", 2, reg, attr); retstat = -1; } return(retstat); } /* end of function: get_window_attribute(reg, attr) */ /************************************************************************/ /* Set Window Attribute */ /************************************************************************/ set_window_attribute(reg, attr, value) int reg[2]; /* register containing port pointer */ int attr[2]; /* attribute number */ int value[2]; /* new value for attribute */ { int attribute; /* index of the attribute desired */ int disp; /* displacement component of a pointer */ int page; /* page number component of a pointer */ int retstat = 0; /* the return status */ int v; /* the new attribute value */ int fld; /* offset of lines/columns field */ int maxnum; /* maximum possible number of lines/columns */ ENTER(set_window_attribute); get_port(reg, 1); page = CORRPAGE(tmp_page); disp = tmp_disp; if (ptype[page] == PORTTYPE*2 && attr[C_PAGE] == SPECFIX*2 && (attribute = get_fix(CORRPAGE(attr[C_PAGE]),attr[C_DISP])) >= 0 && attribute < NUM_FIELDS && value[C_PAGE] == SPECFIX*2) { v = get_fix(CORRPAGE(value[C_PAGE]), value[C_DISP]); switch (attribute) { case 0: /* cursor line */ case 1: /* cursor column */ if (v < 0) goto src_err; break; case 2: /* upper left corner line */ fld = N_LINES; maxnum = MAX_LINES; goto FIT; /* v = fit_in_range(v, 0, MAX_LINES-1); if (get_word(page, disp+N_LINES) > MAX_LINES - v) put_word(page, disp+N_LINES, MAX_LINES - v); break; */ case 3: /* upper left corner column */ fld = N_COLS; maxnum = MAX_COLUMNS; FIT: v = fit_in_range(v, 0, maxnum-1); if (get_word(page, disp+fld) > maxnum-v) put_word(page, disp+fld, maxnum-v); break; /* v = fit_in_range(v, 0, MAX_COLUMNS-1); if (get_word(page, disp+N_COLS) > MAX_COLUMNS - v) put_word(page, disp+N_COLS, MAX_COLUMNS - v); break; */ case 4: /* number of lines */ v = fit_in_range(v, 1, MAX_LINES-get_word(page,disp+UL_LINE)); break; case 5: /* number of columns */ if (!(get_word(page,disp+P_FLAGS) & WINDOW)) break; v = fit_in_range(v, 1, MAX_COLUMNS-get_word(page,disp+UL_COL)); break; default: goto src_err; case 6: /* border color/attributes */ case 7: /* text color/attributes */ case 8: /* flags */ case 9: /* buffer position */ case 10: /* buffer end */ case 11: /* port flags */ } put_word(page, disp+map_attr[attribute], v); /* make the change */ } else { src_err: set_src_err("%REIFY-PORT!", 3, reg, attr, value); retstat = -1; } return(retstat); } /* end of function: set_window_attribute(reg, attr, value) */ /************************************************************************/ /* Save Window Contents */ /************************************************************************/ save_window(reg) int reg[2]; /* pointer to window object */ { int page,disp; /* pointer components */ int n_cols; /* number of columns in the window */ int n_lines; /* number of lines in the window */ int retstat = 0; /* the return status */ int ul_col; /* upper left hand corner's column number */ int ul_line; /* upper left hand corner's line number */ ENTER(save_window); get_port(reg,0); page = CORRPAGE(tmp_page); disp = tmp_disp; if (ptype[page] == PORTTYPE*2 && get_word(page, disp+P_FLAGS) & WINDOW) { pt_flds4(tmp_reg, &ul_line, &ul_col, &n_lines, &n_cols); if (/* bordered? */ get_word(page, disp+B_ATTRIB) != -1) { adj4bord(&ul_line, &n_lines, &ul_col, &n_cols); /* if (ul_line) { ul_line--; n_lines++; } if (ul_col) { ul_col--; n_cols++; } if (ul_line + n_lines < MAX_LINES) n_lines++; if (ul_col + n_cols < MAX_COLUMNS) n_cols++; */ } alloc_block(reg, STRTYPE, ((n_lines * n_cols) * 2) + 2); save_scr(reg, ul_line, ul_col, n_lines, n_cols); } else { set_src_err("WINDOW-SAVE-CONTENTS", 1, reg); retstat = -1; } return(retstat); } /* end of function: save_window(reg) */ /************************************************************************/ /* Restore Window Contents */ /************************************************************************/ rest_window(reg,data) int reg[2]; /* pointer to window object */ int data[2]; /* data to be restored */ { int page,disp; /* pointer components */ int n_cols; /* number of columns in the window */ int n_lines; /* number of lines in the window */ int retstat = 0; /* the return status */ int ul_col; /* upper left hand corner's column number */ int ul_line; /* upper left hand corner's line number */ ENTER(rest_window); get_port(reg,0); page = CORRPAGE(tmp_page); disp = tmp_disp; if (ptype[CORRPAGE(data[C_PAGE])] == STRTYPE*2 && ptype[page] == PORTTYPE*2 && get_word(page, disp+P_FLAGS) & WINDOW) { pt_flds4(tmp_reg, &ul_line, &ul_col, &n_lines, &n_cols); if (/* bordered? */ get_word(page, disp+B_ATTRIB) != -1) { adj4bord(&ul_line, &n_lines, &ul_col, &n_cols); /* if (ul_line) { ul_line--; n_lines++; } if (ul_col) { ul_col--; n_cols++; } if (ul_line + n_lines < MAX_LINES) n_lines++; if (ul_col + n_cols < MAX_COLUMNS) n_cols++; */ } rest_scr(data, ul_line, ul_col, n_lines, n_cols); } else { set_src_err("WINDOW-RESTORE-CONTENTS", 2, reg, data); retstat = -1; } return(retstat); } /* end of function: rest_window(reg, data) */ /************************************************************************/ /* Output Character to Window */ /* */ /* Description: This routine writes a character to the current cursor */ /* position, then increments the cursor location. */ /* If the current cursor position is now within the bounds */ /* of the window, the character is output in the first */ /* column of the next line, scrolling the window, if */ /* necessary. The current text attributes are used to */ /* write the character. */ /************************************************************************/ putc_window(window, ch) int window[2]; /* register containing the window pointer */ int ch; /* the character to be written to the window */ { int cur_col; /* current cursor position column number */ int cur_line; /* current cursor position line number */ int n_cols; /* number of columns in the window */ int n_lines; /* number of lines in the window */ int page, disp; /* page/displacement components of window pointer */ int t_attrib; /* window's text character attributes */ int ul_col; /* upper left hand corner column number */ int ul_line; /* upper left hand corner line number */ page = CORRPAGE(window[C_PAGE]); disp = window[C_DISP]; if (ptype[page] == PORTTYPE*2) { if (get_byte(page, disp+P_FLAGS) & OPEN) { pt_flds6(window, &cur_line, &cur_col, &ul_line, &ul_col, &n_lines, &n_cols); t_attrib = get_word(page, disp+T_ATTRIB); switch(ch) { case '\b': /* process backspace character */ cur_col--; if (cur_col < 0) cur_col = 0; case '\0': /* null character-- do nothing */ break; case '\007': /* bell character-- sound the alarm */ zbell(); break; case '\t': /* process tab character */ cur_col += (8 - (cur_col % 8)); break; case '\r': /* process carriage return */ cur_col = 0; break; case '\n': /* process newline */ cur_col = 0; cur_line++; if (cur_line >= n_lines) { zscroll(ul_line, ul_col, n_lines, n_cols, t_attrib); cur_line = n_lines-1; } break; default: if (cur_col >= n_cols) { if (get_word(page, disp+W_FLAGS) & WRAP) { cur_line++; cur_col=0; } else { cur_col++; break; } } if (cur_line >= n_lines) { zscroll(ul_line, ul_col, n_lines, n_cols, t_attrib); cur_line = n_lines-1; cur_col = 0; } zputc(cur_line+ul_line, cur_col+ul_col, ch, t_attrib); cur_col++; } /* end: switch(ch) */ /* record new cursor position (next character position) */ put_word(page, disp+CUR_LINE, cur_line); put_word(page, disp+CUR_COL, cur_col); } } else { printf("[VM INTERNAL ERROR] Bad port for window output\n"); force_debug(); } } /************************************************************************/ /* Read a "record" from Window */ /************************************************************************/ static int *column; /* column coordinate vector */ static int cur_col; /* current cursor position- column number */ static int cur_line; /* current cursor position- line number */ static int i; /* index into character buffer */ static int insert_mode; /* insert mode flag */ static int len; /* local copy of ln */ static int n_cols; /* number of columns in the window */ static int n_lines; /* number of lines in the window */ static int page, disp; /* page/displacement components of window pointer */ static int *row; /* row coordinate vector */ static int sh_ptr; /* shadow buffer pointer */ static int t_attrib; /* window's text character attributes */ static int ul_col; /* upper left hand corner column number */ static int ul_line; /* upper left hand corner line number */ static char *string; /* input buffer pointer */ static int sh_length = 0; /* number of characters in the shadow buffer */ static char *sh_buffer; /* shadow buffer */ read_window(window, str, ln) int window[2]; /* register containing window pointer */ char *str; /* character buffer in which to return data read */ int *ln; /* maximum number of characters to read */ { int ch; /* character just read */ int j; /* index variable */ int len2; /* length of input buffer times two (2) */ ENTER(read_window); string = str; sh_ptr = i = 0; insert_mode = FALSE; len2 = (*ln) + (*ln); len = (*ln) - 3; if (!(row = (int *) getmem(len2)) || !(column = (int *) getmem(len2))) getmem_error(rtn_name); page = CORRPAGE(window[C_PAGE]); disp = window[C_DISP]; if (ptype[page] == PORTTYPE*2) { pt_flds6(window, &cur_line, &cur_col, &ul_line, &ul_col, &n_lines, &n_cols); t_attrib = get_word(page, disp+T_ATTRIB); zcuron(); do { if (cur_line >= n_lines) { zscroll(ul_line, ul_col, n_lines, n_cols, t_attrib); cur_line = n_lines-1; cur_col = 0; } zputcur(ul_line + cur_line, ul_col + cur_col); ch = getch(); switch(ch) { case '\0': /* process extended key sequence */ ch = getch(); switch (ch) { case LEFT_ARROW: goto backspace; case RIGHT_ARROW: insert_mode = FALSE; if (sh_ptr < sh_length) { ch = sh_buffer[sh_ptr]; goto one_char; } break; case F3: insert_mode = FALSE; while (i < len && sh_ptr < sh_length) echo_char(sh_buffer[sh_ptr]); break; case F5: if (i) { rlsstr(sh_buffer); if (!(sh_buffer = getmem(i+1))) getmem_error(rtn_name); str2str(sh_buffer, string, i); sh_buffer[i] = '\0'; sh_length = i; for (j = i-1; j >= 0; j--) { if (row[j] < 0) break; zputc(ul_line + (cur_line = row[j]), ul_col + (cur_col = column[j]), ' ', t_attrib); } sh_ptr = i = 0; } insert_mode = FALSE; break; case INSERT: insert_mode = TRUE; break; case DELETE: if (sh_ptr < sh_length) sh_ptr++; insert_mode = FALSE; break; case ENTER_KEY: goto carriage_return; } /* end: switch (ch) */ break; case '\b': /* process backspace key */ backspace: if (i <= 0 || row[i-1] < 0) zbell(); else { i--; if (sh_ptr) sh_ptr--; cur_col = column[i]; cur_line = row[i]; zputc(ul_line + cur_line, ul_col + cur_col, ' ', t_attrib); } insert_mode = FALSE; break; case '\r': /* process return key */ carriage_return: string[i++] = '\r'; /* insert carriage return in buffer */ string[i++] = '\n'; /* insert line feed in buffer */ cur_line++; cur_col = 0; if (cur_line >= n_lines) { zscroll(ul_line, ul_col, n_lines, n_cols, t_attrib); cur_line = n_lines-1; } rlsstr(sh_buffer); if (!(sh_buffer = getmem(i))) getmem_error(rtn_name); str2str(sh_buffer, string, i); sh_buffer[i-1] = '\0'; sh_length = i-2; break; case '\n': /* ignore line feed key */ break; one_char: default: if (i >= len) zbell(); else echo_char(ch); } /* end: switch(ch) */ } while (ch != '\r'); zcuroff(); put_word(page, disp+CUR_LINE, cur_line); put_word(page, disp+CUR_COL, cur_col); *ln = i; } else { printf("[VM INTERNAL ERROR] Bad port for window input\n"); force_debug(); } if (rlsmem(row, len2) || rlsmem(column, len2)) rlsmem_error(rtn_name); } /* end of function: char *read_window(window) */ /************************************************************************/ /* Echo Single Character */ /************************************************************************/ echo_char(ch) int ch; { int j; /* index variable */ string[i++] = ch; if (!insert_mode) sh_ptr++; if (cur_col >= n_cols) { cur_line++; cur_col = 0; } if (cur_line >= n_lines) { zscroll(ul_line, ul_col, n_lines, n_cols, t_attrib); cur_line = n_lines-1; cur_col = 0; for (j = 0; j < i; j++) row[j]--; } row[i-1] = cur_line; column[i-1] = cur_col; if (ch == '\t') { if((cur_col += (8 - (cur_col % 8)))>n_cols) cur_col = n_cols; if (ul_col + cur_col >= 80) zputcur(cur_line, 79); } else { zputc(ul_line + cur_line, ul_col + cur_col, ch, t_attrib); cur_col++; } } /* end of function: out_char(ch) */ /************************************************************************/ /* Force Value Into Range */ /* */ /* Purpose: To test a value to determine if it falls within a range */ /* of values, as specified by an lower and upper bound. */ /* If the value is within the range, the value is returned */ /* unchanged. If it is outside the range, the value of the*/ /* endpoint nearest its value is returned. */ /************************************************************************/ fit_in_range(value, lower, upper) int value; /* value to be tested */ int lower; /* lower bound of range */ int upper; /* upper bound of range */ { return(value < lower ? lower : (value > upper ? upper : value)); } /* end of function: fit_in_range(value, lower, upper) */ /************************************************************************/ /* Support for "read-char-ready?" */ /************************************************************************/ rd_ch_rdy(port) int port[2]; /* register containing port designation */ { int b_pos; /* current buffer position */ int ch; /* character read from a file */ int flags; /* port flags */ int page; /* port's page number */ int retstat = 0; /* the return status */ if (!get_port(port, 0)) { port[C_PAGE] = SPECCHAR*2; /* prepare to return a character */ page = CORRPAGE(tmp_page); if ((b_pos = get_word(page, tmp_disp+BUF_POS)) < get_word(page, tmp_disp+BUF_END)) { ch = get_byte(page, tmp_disp+BUFR+b_pos); return_T: if (ch == '\032' && !(get_word(page,tmp_disp+P_FLAGS) & BINARY)) goto return_eof; port[C_DISP] = ch; goto end_of_routine; } else /* no character in input buffer */ { if ((flags = get_byte(page, tmp_disp+P_FLAGS)) & WINDOW) { if ((ch = zch_rdy())) { ch = ch & 0x00ff; goto return_T; } } else /* not a window */ { if (flags & OPEN) { ssetadr(tmp_page, tmp_disp); ch = take_ch(); if (ch != 256) { pushchar(); port[C_DISP] = ch; } /* end: if (ch != 256) */ else { return_eof: port[C_PAGE] = EOF_PAGE*2; port[C_DISP] = EOF_DISP; } /* end: else */ goto end_of_routine; } /* end: if (flags & OPEN) */ } /* end: else /* not a window */ */ } /* end: else /* no character in input buffer */ */ } /* end: if (!get_port(port, 0)) */ else { set_src_err("CHAR-READY?", 1, port); retstat = -1; } /* no character available-- return '() */ port[C_PAGE] = port[C_DISP] = 0; end_of_routine: return(retstat); } /* end of function: rd_ch_rdy(port) */ /************************************************************************/ /* Support for "read-char" */ /************************************************************************/ read_char(port) int port[2]; { int i; /* temporary */ /* 2-11-86 */ int page; /* port's page number */ int retstat = 0; /* the return status */ if (!get_port(port, 0)) { page = CORRPAGE(tmp_page); port[C_PAGE] = SPECCHAR*2; if ((i = get_byte(page, tmp_disp+P_FLAGS)) & WINDOW && /* 2-11-86 */ !(i & STRSRC) && get_word(page, tmp_disp+BUF_POS) >= get_word(page, tmp_disp+BUF_END)) { zputcur(get_word(page,tmp_disp+UL_LINE)+get_word(page,tmp_disp+CUR_LINE), get_word(page,tmp_disp+UL_COL)+get_word(page,tmp_disp+CUR_COL)); zcuron(); port[C_DISP] = getch(); zcuroff(); put_byte(page, tmp_disp+BUFR, port[C_DISP]); put_word(page, tmp_disp+BUF_POS, 1); put_word(page, tmp_disp+BUF_END, 1); } else { ssetadr(tmp_page,tmp_disp); if ((port[C_DISP] = take_ch()) == 256) { port[C_PAGE] = EOF_PAGE*2; port[C_DISP] = EOF_DISP; } } } else { set_src_err("READ-CHAR", 1, port); retstat = -1; } return(retstat); } /* end of function: read_char(port) */ /************************************************************************/ /* Set Port Address */ /************************************************************************/ setadr(pg, ds, direction) int pg; /* the port's page number */ int ds; /* the port's displacement */ int direction; /* read/write flag */ { if (ptype[pg] == PORTTYPE*2) { port_reg[C_PAGE] = ADJPAGE((port_page = pg)); port_reg[C_DISP] = port_disp = ds; handle = get_word(pg, ds+HANDLE); direction = get_word(pg, ds+P_FLAGS); window_p = direction & WINDOW; string_p = direction & STRSRC; } else { printf("[VM INTERNAL ERROR] setadr: bad port\n"); force_debug(); return(1); } return(0); } /* end of function: setadr(pg, ds, direction) */ /************************************************************************/ /* Output a Single Character */ /************************************************************************/ givechar(ch) int ch; /* the character to be output */ { int cur_col; /* the current column */ int n_cols; /* number of columns */ int length; /* character string length for output */ int stat; /* status returned from zwrite */ /* 2-11-86 */ int sav_page,sav_disp; /*if (ch == '\n') ch = '\r'; Don't change! *** JHAO ***/ /* If transcript file "on", check this port for transcript-enable */ if (TRNS_pag && (get_word(port_page, port_disp+P_FLAGS) & TRANSCRIPT)) { sav_page = port_page; sav_disp = port_disp; setadr(CORRPAGE(TRNS_pag), TRNS_dis, 1); givechar(ch); setadr(sav_page, sav_disp, 1); } /* end: if (TRNS_pag) */ if (window_p) { if (!string_p) { if (ch == '\r') ch = '\n'; putc_window(port_reg, ch); } } else { n_cols = get_word(port_page, port_disp+N_COLS); cur_col = get_word(port_page, port_disp+CUR_COL); length = 1; if (ch == '\n') { ch = '\r'; if ((stat = zwrite(handle, &ch, &length))) /* 2-11-86 */ goto zerror; ch = '\n'; length = 1; if ((stat = zwrite(handle, &ch, &length))) /* 2-11-86 */ goto zerror; } else { if ((stat = zwrite(handle, &ch, &length))) /* 2-11-86 */ goto zerror; if (ch == '\r') { if (handle != prn_handle) { /* write to file CR = CRLF */ ch = '\n'; length = 1; if ((stat = zwrite(handle, &ch, &length))) /* 2-11-86 */ goto zerror; } } } switch (ch) { case '\b': cur_col--; if (cur_col < 0) cur_col = 0; break; case '\t': cur_col += (8 - (cur_col % 8)); break; case '\r': case '\n': cur_col = 0; break; default: if (cur_col >= n_cols) cur_col = 0; else cur_col++; } put_word(port_page, port_disp+CUR_COL, cur_col); } return(0); zerror: /* 2-11-86 */ printf("[VM ERROR encountered!] Write error: DOS error code %d\n%s", stat,"Attempting to execute SCHEME-RESET\n[Returning to top level]"); force_reset(); return(0); } /* end of function: givechar(ch) */ /************************************************************************/ /* Input a Single Character */ /* */ /* Description: Accepts the next character from the currently active */ /* port. */ /* */ /* Calling Sequence: ch = takechar(); */ /* Where ch -- the character read or EOF (0x0100) */ /* */ /* Note: This routine reads from the port data object previously */ /* defined by a call to "SETADR". */ /************************************************************************/ takechar() { char buffer[BUFFSIZE];/* local buffer for sequential read request */ int ch; /* the character to be returned */ int cur_chr; /* buffer position of the current character */ int i; /* index variable */ int length; /* buffer length; number of characters read */ int sav_page,sav_disp;/* port pointer save area */ int stat; /* status variable for read requests */ cur_chr = get_word(port_page, port_disp+BUF_POS); if (cur_chr >= get_word(port_page, port_disp+BUF_END)) { /* buffer empty-- fill it up */ length = BUFFSIZE; if (window_p) { if (string_p) { if (stringrd(port_page, port_disp, buffer, &length)) printf("[VM INTERNAL ERROR] takechar: source not a string\n"); } else { read_window(port_reg, buffer, &length); /* If transcript file "on", check this file for transcript-enable */ if (TRNS_pag && (get_word(port_page, port_disp+P_FLAGS) & TRANSCRIPT)) { sav_page = port_page; sav_disp = port_disp; setadr(CORRPAGE(TRNS_pag), TRNS_dis, 1); printstr(buffer, length - 1); setadr(sav_page, sav_disp, 1); } /* end: if (TRNS_pag ...) */ } } else { if ((stat = zread(handle, buffer, &length))) { printf("[VM ERROR encountered!] Read error: DOS error code %d\n%s",stat, "Attempting to execute SCHEME-RESET\n[Returning to top level]"); force_reset(); } } put_word(port_page, port_disp+BUF_END, length); if (length == 0) { put_word(port_page, port_disp+BUF_POS, 0); return(256); } toblock(port_reg, BUFR, buffer, length); cur_chr = 0; } /* return the next character from the input buffer */ put_word(port_page, port_disp+BUF_POS, cur_chr+1); ch = get_byte(port_page, port_disp+BUFR+cur_chr); /* test for a control-Z-- if so, and we've got a text file, return EOF */ if (ch == '\032' && !(get_word(port_page, port_disp+P_FLAGS) & BINARY)) ch = 256; return(ch); } /* end of function: takechar() */ /************************************************************************/ /* Push a Single Character Back into the Input Buffer */ /************************************************************************/ pushchar() { int cur_chr; /* buffer position of the current character */ cur_chr = get_word(port_page, port_disp+BUF_POS); if (cur_chr > 0) { cur_chr--; put_word(port_page, port_disp+BUF_POS, cur_chr); } else { printf("[VM INTERNAL ERROR] pushchar: failed\n"); force_debug(); } } /* end of function: pushchar() */ /************************************************************************/ /* Return Number of Spaces Remaining on Current Line */ /* */ /* Description: The routine interrogates a port data object and */ /* returns the number of print positions remaining on the */ /* current line. If no line length is associated with the */ /* port (i.e., the line length is zero), the value 0x7fff */ /* is returned. This routine works for both file and */ /* window port data objects. */ /* */ /* Calling Sequence: setadr(pg, ds); */ /* space = currspc(); */ /* */ /* Where pg ---- the port's page number */ /* ds ---- the port's displacement */ /* space - the number of positions remaining on the */ /* current print line */ /************************************************************************/ currspc() { int cur_col; int line_length; /* the port's line length */ cur_col = get_word(port_page, port_disp+CUR_COL); line_length = get_word(port_page, port_disp+N_COLS); return(line_length ? line_length - cur_col : 0x7fff); } /* end of function: currspc() */ /************************************************************************/ /* Return Current Column */ /************************************************************************/ curr_col() { return(get_word(port_page, port_disp+CUR_COL)); } /* end of function: curr_col() */ ******************************************/ /************ The following module is not called by anyone /************************************************************************/ /* Return Line Length of a Port/Window */ /************************************************************************/ lnlen(pg,ds) int pg,ds; { return(ptype[pg] == PORTTYPE*2 ? get_word(pg,ds+N_COLS) : -1); } ****************************************************/ /***** Code turned off 17 May 1985 ***** /************************************************************************/ /* Return Line Length of a Port/Window */ /************************************************************************/ set_lnlen(pg,ds,len) int pg,ds,len; { if (ptype[pg] == PORTTYPE*2) { if (len >= 0) put_word(pg,ds+N_COLS,len); } else { printf("set_lnlen: bad port\n"); force_debug(); } } /* end of function: set_lnlen(pg,ds,len) */ ***** Code turned off 17 May 1985 *****/ /************** /************************************************************************/ /* Modify Transcript File Status */ /************************************************************************/ trns_chg(reg) int reg[2]; { int mode; int page; if (ptype[(page = CORRPAGE(reg[C_PAGE]))] == PORTTYPE*2 && (mode = get_word(page, reg[C_DISP] + P_FLAGS)) & OPEN && mode & 0x03) { TRNS_pag = reg[C_PAGE]; TRNS_dis = reg[C_DISP]; } else { TRNS_pag = TRNS_dis = 0; } } /* end of function: trns_chg(reg) */ /************************************************************************/ /* Write Message to the who-line */ /************************************************************************/ who_write(str) char *str; { extern int port_r[2]; int ds,pg; /* page and displacement components of active port */ int ppg; /* save the current port */ ds = port_r[C_DISP]; pg = CORRPAGE(port_r[C_PAGE]); ppg = port_r[C_PAGE]; /* write message to the "who line" */ ssetadr(ADJPAGE(WHO_PAGE), WHO_DISP); printstr(str, strlen(str)); /* restore the port which was in effect when we started */ if (ptype[pg] == PORTTYPE*2 && get_byte(pg,ds) == PORTTYPE) ssetadr(ppg, ds); } /* end of function: who_write(str) */ **************************************************/ /************************************************************************/ /* Write "GC On"Message to the who-line */ /************************************************************************/ gc_on() { int lcl_reg[2]; char *text; char *string_asciz(); GC_ING = 1; intern(lcl_reg, "PCS-GC-MESSAGE", 14); if (sym_lookup (lcl_reg, GNV_reg) && (text = string_asciz(lcl_reg))) { who_write("\n"); who_write(text); rlsstr(text); } else { who_write("\n * Garbage Collecting *"); } } /* end of function: gc_on() */ /************************************************************************/ /* Un-Write "GC On"Message to the who-line */ /************************************************************************/ gc_off() { GC_ING = 0; who_clear(); } /* end of function: gc_off() */