home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name apquery -- Read response from CON: keyboard, echoing
- * characters to the active page on the current
- * display device.
- *
- * Synopsis final = apquery(presp,resp_size,pscan,pnum_scrolled);
- *
- * char final Character that terminated input, or
- * NUL ('\0') if an extended key
- * sequence terminated the input.
- * char *presp Pointer to character buffer in which
- * to return response.
- * int resp_size Size of input buffer in bytes (including
- * one byte for the trailing NUL ('\0')).
- * int *pscan If the terminal character was an ASCII
- * character, this is its value;
- * if it was an extended key
- * sequence, this is its scan code.
- * int *pnum_scrolled
- * Number of lines the screen was scrolled.
- *
- * Description This function returns a string of keystrokes from the
- * user, echoing keystrokes and confining all I/O to the
- * active page on the current display device.
- *
- * The user may type characters as usual, terminating the
- * input by one of the following: ENTER, CTRL-M, CTRL-J,
- * or a function key or other extended key sequence. The
- * characters are echoed and the cursor moves across the
- * screen. When the rightmost column of the screen is
- * reached, the cursor moves to the next row, except that
- * the screen is scrolled when the lower right corner of
- * the screen is reached. The input stops when the buffer
- * is full.
- *
- * Once the input buffer is full, the cursor remains just
- * after the last response character. Further keystrokes
- * (except for backspace and terminating keys) cause beeps
- * and are discarded. Backspace works as usual. The
- * function does not return until ENTER or another
- * terminating key has been pressed (even if the buffer is
- * full).
- *
- * The terminating character is not returned as part of the
- * input. If the terminating character is an ASCII
- * character, its value is returned in *pscan and as the
- * value of the function; if it was an extended key
- * sequence, its scan code is returned in *pscan and the
- * value of the function is zero.
- *
- * Special The following keystrokes have special effects when
- * characters entered as part of the response:
- *
- * Backspace or CTRL-H ('\b') deletes the previous
- * character entered and moves the cursor to that
- * character's location. A backspace at the beginning of
- * the response has no effect.
- *
- * ENTER or CTRL-M ('\15') terminates the response.
- *
- * CTRL-J ('\12') terminates the response.
- *
- * NULs (ASCII 0) are ignored and discarded.
- *
- * TAB or CTRL-I ('\9') is echoed as one or more blank
- * spaces as usual. The TAB character is returned in the
- * buffer.
- *
- * CTRL-G causes a beep but is not returned as part of the
- * response.
- *
- * Special non-ASCII IBM keys (such as function keys and
- * some ALT keys) terminate the response.
- *
- * All other ASCII characters, including control
- * characters, are echoed. (Control characters are echoed
- * as themselves, that is, without an uparrow ('^')
- * prefix.)
- *
- * Returns final Character that terminated input, or
- * NUL ('\0') if an extended key
- * sequence terminated the input.
- * *pscan ASCII code or extended code of
- * keystroke that terminated input.
- * *presp User's response as a string.
- *
- * Version 3.0 Copyright (C) Blaise Computing Inc. 1986
- *
- **/
-
- #include <bapplic.h>
- #include <bkeybd.h>
- #include <bscreen.h>
-
- #define BEL 7 /* Bell (CTRL-G) */
- #define BS 8 /* Backspace (CTRL-H) */
- #define TAB 9 /* Tab (CTRL-I) */
- #define LF 10 /* Line feed (CTRL-J) */
- #define ENTER 13 /* ENTER or carriage return (CTRL-M) */
- #define CR 13
-
- #define TAB_WIDTH 8 /* Distance between tab stops (for */
- /* echoing TAB characters) */
-
- char apquery(presp,resp_size,pscan,pnum_scrolled)
- char *presp;
- int resp_size,*pscan,*pnum_scrolled;
- {
- int old_page,mode,columns,act_page;
- char ch;
- int is_char;
- int row,col,begin_row,begin_col;
- int num_have = 0;
- char *pbegin = presp;
- char *ptemp;
-
- old_page = b_curpage; /* Save former display page. */
- scmode(&mode,&columns,&act_page);
- scpage(act_page); /* Direct I/O to active page. */
-
- *pnum_scrolled =
- num_have = 0;
- sccurpos(&begin_row,&begin_col);
- row = begin_row;
- col = begin_col;
-
- do /* Collect the response. */
- {
- /* Await a keystroke. */
- if (is_char = kbin(pscan))
- { /* Got an ASCII character. */
-
- switch (ch = (char) *pscan)
- {
- case LF:
- case ENTER:
- break; /* This is a terminating */
- /* character: handle it at */
- /* loop exit. */
-
- case '\0': /* Ignore NULs. */
- break;
-
- case BEL: /* BEL: just beep. */
- scttywrt((char) BEL,1);
- break;
-
- default:
- if (num_have >= resp_size - 1) /* Buffer full */
- {
- scttywrt((char) BEL,1);
- }
- else
- {
- do /* Echo spaces or the char, */
- { /* noting any scrolling. */
- if ( col >= columns - 1
- && row >= scrows() - 1)
- ++*pnum_scrolled;
- scttywrt((ch == TAB ? (char) ' ' : ch),1);
- sccurpos(&row,&col);
- } while (ch == TAB && (col % TAB_WIDTH));
-
- /* Update response buffer. */
- num_have++;
- *presp++ = ch;
- }
- break;
-
- case BS:
- if (num_have)
- {
- num_have--;
- /* Move cursor to last char */
- /* entered. */
- if (*--presp == TAB)
- { /* Delete TABs specially: */
- *presp = '\0';
- row = begin_row - *pnum_scrolled;
- col = begin_col;
- ptemp = pbegin;
-
- /* Find new cursor location by */
- /* walking forward through the */
- /* response again. */
- while ((ch = *ptemp++) != '\0')
- {
- do
- {
- if (++col > columns - 1)
- {
- row++;
- col = 0;
- }
- } while (ch == TAB && (col % TAB_WIDTH));
- }
- sccurset(row,col);
- /* Don't need to erase with a */
- /* blank since the TAB was */
- /* already displayed using */
- /* blanks. */
-
- /* ("row" may be negative here */
- /* if begin_row was scrolled */
- /* off the screen, but that */
- /* can only happen if user */
- /* fills the screen with input.)*/
- }
- else
- { /* Just delete a normal */
- /* character. */
-
- if (col) /* Back up one column. */
- sccurset(row,--col);
- else /* Back up to previous row. */
- sccurset(--row,col = columns - 1);
-
- /* Erase previous character.*/
- scwrite((char) ' ',1);
- }
- }
- else
- {
- /* Do nothing */ /* Can't delete past */
- } /* beginning. */
-
- break;
- }
- }
-
- /* Note: at this point, row and col indicate the next */
- /* position on the screen. */
-
- } while (is_char && (ch != ENTER) && (ch != LF));
-
- *presp = '\0'; /* Terminate response string. */
-
- scttywrt((char) CR,1); /* Perform a final newline. */
- scttywrt((char) LF,1);
- if (row >= scrows() - 1)
- ++*pnum_scrolled;
-
- scpage(old_page); /* Restore current display page */
-
- return is_char ? ch : (char) '\0';/* Successful exit. */
- }