Back to index

lightning-sunbird  0.9+nobinonly
Functions
ltermIO.c File Reference
#include "lineterm.h"
#include "ltermPrivate.h"

Go to the source code of this file.

Functions

static int ltermWrite (struct lterms *lts, int *opcodes)
 Writes data from input buffer pipe to pseudo-TTY, processing one complete record read from input buffer pipe and returning OPCODES ::= LINEDATA ( INPUT ( NEWLINE HIDE? )? | INPUT META ( COMPLETION | NEWLINE HIDE? ) ) NOTE: This call may block to read data from input buffer pipe, if lts->inputBufRecord is false.
static int ltermReturnStreamData (struct lterms *lts, struct LtermRead *ltr)
 Returns stream data from STDOUT (Auxiliary procedure for ltermRead.) OPCODES ::= STREAMDATA NEWLINE? ERROR? COOKIESTR? DOCSTREAM? XMLSTREAM? WINSTREAM? The LtermRead structure *LTR contains both input and output parameters.
static int ltermReturnScreenData (struct lterms *lts, struct LtermRead *ltr, int opcodes, int opvals, int oprow)
 Returns processed screen data (Auxiliary procedure for ltermRead.) The LtermRead structure *LTR contains both input and output parameters.
static int ltermReturnInputLine (struct lterms *lts, struct LtermRead *ltr, int completionRequested)
 Returns incomplete input line, prefixed with prompt or incomplete output.
static int ltermReturnOutputLine (struct lterms *lts, struct LtermRead *ltr)
 Returns output line data (Auxiliary procedure for ltermRead.) The LtermRead structure *LTR contains both input and output parameters.
int ltermSendLine (struct lterms *lts, UNICHAR uch, int echoControl, int completionCode)
 Transmits input line + optional control character UCH to child process.
int ltermRead (struct lterms *lts, struct LtermRead *ltr, int timeout)
 Reads a (possibly incomplete) line from LTERM.
int ltermInterruptOutput (struct lterms *lts)
 Interrupts output operations in response to an input TTY interrupt signal.

Function Documentation

int ltermInterruptOutput ( struct lterms lts)

Interrupts output operations in response to an input TTY interrupt signal.

Returns:
0 if successful, -1 if an error occurred

Definition at line 818 of file ltermIO.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);

  if (lto->outputMode == LTERM0_STREAM_MODE) {
    /* Abnormally terminate output stream */
    lto->streamOpcodes |= LTERM_ERROR_CODE;
  }

  return 0;
}

Here is the caller graph for this function:

int ltermRead ( struct lterms lts,
struct LtermRead ltr,
int  timeout 
)

Reads a (possibly incomplete) line from LTERM.

The LtermRead structure *LTR contains both input and output parameters, returning opcodes values of OPCODES ::= STREAMDATA NEWLINE? ERROR? COOKIESTR? DOCSTREAM? XMLSTREAM? WINSTREAM? if StreamMode data is being returned.

OPCODES ::= SCREENDATA BELL? ( OUTPUT | CLEAR | INSERT | DELETE | SCROLL )? if ScreenMode data is being returned.

OPCODES ::= LINEDATA BELL? ( CLEAR | OUTPUT NEWLINE? ) if LineMode data is being returned.

(Auxiliary procedure for lterm_read.)

Returns:
0 if successful, -1 if an error occurred while reading, -2 if pseudo-TTY has been closed, -3 if more than MAX_COUNT characters are present in the line (in this case the first MAX_COUNT characters are returned in BUF, and the rest are discarded).

Definition at line 477 of file ltermIO.c.

{
  struct LtermInput *lti = &(lts->ltermInput);
  struct LtermOutput *lto = &(lts->ltermOutput);
  int waitTime, nfds_all, pollCode, rePoll;
  int inputAvailable, newOutputAvailable;
  int outOpcodes, outOpvals, outOprow, returnCode;
  int j;

  LTERM_LOG(ltermRead,20,("start outputMode=%d\n", lto->outputMode));

  if (lto->outputMode == LTERM1_SCREEN_MODE) {
    char modifiedRows[81];
    int showRows = (lts->nRows < 80) ? lts->nRows : 80;
    for (j=0; j<showRows; j++) {
      if (lto->modifiedCol[j] > -1)
        modifiedRows[j] = 'M';
      else
        modifiedRows[j] = '.';
    }
    modifiedRows[showRows] = '\0';
    LTERM_LOG(ltermRead,28,("modifiedRows=%s\n", modifiedRows));
  }

  waitTime = timeout;

  if (lts->inputBufRecord) {
    /* Complete input record available in buffer */

    LTERM_LOG(ltermRead,21,("inputBufRecord=%d\n", lts->inputBufRecord));
    waitTime = 0;

  } else if ((lto->decodedChars > 0) && !lto->incompleteEscapeSequence) {
    /* Do not wait if there are decoded characters to be processed that are
       not part of an incomplete ESCAPE sequence */

    LTERM_LOG(ltermRead,21,("decodedChars=%d,incompleteEscapeSequence=%d\n",
                  lto->decodedChars, lto->incompleteEscapeSequence));

    waitTime = 0;

  } else if (lto->outputMode == LTERM1_SCREEN_MODE) {
    /* Screen mode: do not wait if there are any modified rows */
    for (j=0; j<lts->nRows; j++)
      if (lto->modifiedCol[j] >= 0) {
        waitTime = 0;
        break;
      }

    if (j<lts->nRows) {
      LTERM_LOG(ltermRead,21,("j=%d, modifiedCol[j] = %d\n",
                    j, lto->modifiedCol[j]));
    }
  }

  /* If stream mode, do not poll STDERR output */
  if (lto->outputMode == LTERM0_STREAM_MODE)
    nfds_all = POLL_COUNT-1;
  else
    nfds_all = lto->nfds;

  do {
    /* Do not re-poll unless something special occurs */
    rePoll = 0;

    /* Default return values in LtermRead structure */
    ltr->read_count = 0;
    ltr->opcodes = 0;
    ltr->opvals = 0;
    ltr->buf_row = -1;
    ltr->buf_col = -1;
    ltr->cursor_row = -1;
    ltr->cursor_col = -1;

    LTERM_LOG(ltermRead,21,("polling nfds = %d, waitTime = %d\n",
                lto->nfds, waitTime));

    /* Poll all files for data to read */
    pollCode = POLL(lto->pollFD, (SIZE_T) lto->nfds, waitTime);

    if (pollCode == -1) {
#if defined(DEBUG_LTERM) && !defined(USE_NSPR_IO)
      int errcode = errno;
      perror("ltermRead");
#else
      int errcode = 0;
#endif
      LTERM_ERROR( "ltermRead: Error return from poll, code=%d\n", errcode);
      return -1;
    }

    /* Do not wait for polling the second time around */
    waitTime = 0;

    /* Check if input data is available */
    inputAvailable = lts->inputBufRecord ||
                     ( (pollCode > 0) &&
                       (lto->pollFD[POLL_INPUTBUF].POLL_REVENTS != 0) );

    /* Check if STDOUT/STDERR data is available */
    newOutputAvailable = (pollCode > 0) &&
                          ( (lto->pollFD[POLL_STDOUT].POLL_REVENTS != 0) ||
                            (lto->pollFD[POLL_STDERR].POLL_REVENTS != 0) );

    LTERM_LOG(ltermRead,21,
            ("inputAvailable=%d, newOutputAvailable=%d, completionRequest=%d\n",
            inputAvailable, newOutputAvailable, lts->completionRequest));

    if (inputAvailable && (!newOutputAvailable ||
                           (lts->completionRequest == LTERM_NO_COMPLETION)) ) {
      /* Process an input data record; either no new output is available, or
       * output is available but command completion has not been requested
       */
      int inOpcodes;

      returnCode = ltermWrite(lts, &inOpcodes);
      if (returnCode < 0)
        return returnCode;

      if (inOpcodes != 0) {
        /* Echoable input data processed; return input line */
        returnCode = ltermReturnInputLine(lts, ltr, 0);
        if (returnCode < 0)
          return returnCode;

        if (inOpcodes & LTERM_META_CODE) {
          ltr->opcodes |= LTERM_META_CODE;

          if (inOpcodes & LTERM_COMPLETION_CODE)
            ltr->opcodes |= LTERM_COMPLETION_CODE;
        }

        if (inOpcodes & LTERM_NEWLINE_CODE) {
          /* Input line break */
          ltr->opcodes |= LTERM_NEWLINE_CODE;

          if (inOpcodes & LTERM_HIDE_CODE)
            ltr->opcodes |= LTERM_HIDE_CODE;

          /* Clear input line buffer */
          ltermClearInputLine(lts);
        }

        if (lts->disabledInputEcho) {
          /* Input echo is disabled, re-poll */
          rePoll = 1;
          LTERM_LOG(ltermRead,32,("Input echo disabled; RE-POLLING\n\n"));
          continue;
        }

        return 0;
      }

      inputAvailable = 0;
    }

    if (newOutputAvailable) {
      /* Read data from STDOUT/STDERR */
      int outChars;

      outChars = ltermReceiveData(lts, nfds_all==POLL_COUNT);
      if (outChars < 0)
        return outChars;
    }

    if (lto->outputMode == LTERM0_STREAM_MODE) {
      /* Stream mode */
      return ltermReturnStreamData(lts, ltr);
    }

    /* If there is some complete decoded output, process it */
    if ((lto->decodedChars > 0) && !lto->incompleteEscapeSequence) {
      returnCode = ltermProcessOutput(lts, &outOpcodes, &outOpvals, &outOprow);
      if (returnCode < 0)
        return -1;

    } else {
      /* No new output to process */
      if (lto->outputMode == LTERM1_SCREEN_MODE) {
        outOpcodes = LTERM_SCREENDATA_CODE;
        outOpvals = 0;
        outOprow = -1;
      } else {
        /* No new output in line mode; return nothing */
        return 0;
      }
    }

    if (outOpcodes & LTERM_SCREENDATA_CODE) {
      /* Return screen mode output */
      return ltermReturnScreenData(lts, ltr, outOpcodes, outOpvals, outOprow);
    }

    if (outOpcodes & LTERM_LINEDATA_CODE) {

      LTERM_LOG(ltermRead,32,
       ("inputLineBreak=%d, completionRequest=%d, completionChars=%d\n",
        lts->inputLineBreak, lts->completionRequest, lts->completionChars));

      if (outOpcodes & LTERM_OUTPUT_CODE) {
        /* Return output line */
        int echoMatch = 0;

        returnCode = ltermReturnOutputLine(lts, ltr);
        if (returnCode < 0)
          return returnCode;

        LTERM_LOG(ltermRead,33, ("read_count=%d, echoChars=%d\n",
                                 ltr->read_count, lts->echoChars));

        if (lts->inputLineBreak) {
          /* Compare output line to initial portion of echo line */
          echoMatch = 1;

          if ( (ltr->read_count > lts->echoChars) ||
               ((ltr->read_count != lts->echoChars) &&
                (outOpcodes & LTERM_NEWLINE_CODE)) ) {
            echoMatch = 0;
          } else {
            int k;
            for (k=0; k<ltr->read_count; k++) {
              if (ltr->buf[k] != lts->echoLine[k]) {
                echoMatch = 0;
                break;
              }
            }
          }
        }

        if (outOpcodes & LTERM_NEWLINE_CODE) {
          /* Complete output line */
          if (!echoMatch)
            ltr->opcodes |= LTERM_NEWLINE_CODE;

          /* Clear output line buffer */
          ltermClearOutputLine(lts);

          /* Clear input line break flag */
          lts->inputLineBreak = 0;

        } else {
          /* Incomplete output line */

          if (lts->completionRequest != LTERM_NO_COMPLETION) {
            /* Completion requested;
             * Compare first/last part of output line to parts of echo line
             */
            int k;
            int extraChars = ltr->read_count - lts->echoChars;
            int compChars = ltr->read_count;
            int preMatch = 1;

            if (extraChars > 0)
              compChars = lts->echoChars;

            for (k=0; k<compChars; k++) {
              if (ltr->buf[k] != lts->echoLine[k]) {
                preMatch = 0;
                break;
              }
            }

            if (!preMatch) {
              /* No match; cancel completion request */
              if (ltermCancelCompletion(lts) != 0)
                return -1;

            } else if (extraChars >= 0) {
              /* Matched complete echo line and perhaps more */

              if ((extraChars > 0) && (extraChars <= MAXCOLM1)) {
                /* Insert extra characters into input line */
                lts->completionChars = extraChars;

                for (k=0; k<extraChars; k++) {
                  if (ltermInsertChar(lti, ltr->buf[compChars+k]) != 0)
                    return -1;
                }

                LTERM_LOG(ltermRead,32,
                          ("++++++++++++ COMPLETION SUCCESSFUL\n"));

                LTERM_LOGUNICODE(ltermRead,32,
                                 (ltr->buf+compChars, extraChars));
              }

              /* Return updated input line, prefixed with prompt */
              returnCode = ltermReturnInputLine(lts, ltr, 1);
              if (returnCode < 0)
                return returnCode;

            } else {
              /* Partial match; do not echo */
              echoMatch = 1;
            }

          } else if (lto->promptChars == lto->outputChars) {
            /* Incomplete output line with just a prompt */

            LTERM_LOG(ltermRead,32,("Prompt-only line\n"));

            /* Return updated input line, prefixed with prompt */
            returnCode = ltermReturnInputLine(lts, ltr, 0);
            if (returnCode < 0)
              return returnCode;
          }
        }

        if (echoMatch) {
          /* Do not display output line; re-poll */
          rePoll = 1;
          LTERM_LOG(ltermRead,32,("Echo match; RE-POLLING\n\n"));
          continue;
        } else {
          return 0;
        }

      } else {
        /* Line mode data with modifier flags; return just cursor position */
        ltr->opcodes = outOpcodes;
        ltr->opvals = 0;

        /* Copy full screen cursor position */
        ltr->cursor_row = -1;
        ltr->cursor_col = 0;

        ltr->read_count = 0;

        return 0;
      }
    }

  } while (rePoll);

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ltermReturnInputLine ( struct lterms lts,
struct LtermRead ltr,
int  completionRequested 
) [static]

Returns incomplete input line, prefixed with prompt or incomplete output.

(Auxiliary procedure for ltermRead.) The LtermRead structure *LTR contains both input and output parameters. Set COMPLETIONREQUESTED to true if this is a completed command line.

Returns:
0 if successful, -1 if an error occurred while reading, -3 if more than COUNT characters are present in the line (in this case the first COUNT characters are returned in BUF, and the rest are discarded).

Definition at line 1083 of file ltermIO.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  struct LtermInput *lti = &(lts->ltermInput);
  int outChars, charCount, inputCursorCol, returnCode;
  int j;

  LTERM_LOG(ltermReturnInputLine,30, ("outputChars=%d, promptChars=%d\n",
                                        lto->outputChars, lto->promptChars));

  if (lto->promptChars > 0) {
    /* Prefix with prompt output data */
    ltr->opcodes = LTERM_LINEDATA_CODE;

    outChars = lto->promptChars;

    if (!completionRequested) {
      /* Hack to handle misidentified prompts;
       *  if output characters following the prompt differ from input line,
       *  display them.
       */
      for (j=0; j<lti->inputChars; j++) {
        if (((j+outChars) < lto->outputChars) && 
            (lto->outputLine[j+outChars] != lti->inputLine[j])) {
          outChars = lto->outputChars;
          break;
        }
      }
    }

    if (outChars > ltr->max_count)
      outChars = 0;

    if (outChars > 0) {
      ltr->opcodes |= LTERM_PROMPT_CODE;
      for (j=0; j<outChars; j++) {
        ltr->buf[j] = lto->outputLine[j];
        ltr->style[j] = LTERM_PROMPT_STYLE;
      }
    }

  } else {
    /* Prefix with entire output line */
    returnCode = ltermReturnOutputLine(lts, ltr);
    if (returnCode < 0)
      return returnCode;

    outChars = ltr->read_count;
  }

  ltr->opcodes |= LTERM_INPUT_CODE;

  charCount = outChars + lti->inputChars;

  if (charCount <= ltr->max_count) {
    returnCode = 0;
  } else {
    /* Too much data to fit into output buffer; truncate */
    charCount = ltr->max_count;
    returnCode = -3;
  }

  /* Append STDIN data, with markup and escape sequences */
  for (j=outChars; j<charCount; j++) {
    ltr->buf[j] = lti->inputLine[j-outChars];
    ltr->style[j] = LTERM_STDIN_STYLE;
  }

  inputCursorCol = lti->inputGlyphColIndex[lti->inputCursorGlyph];

  ltr->buf_row = -1;
  ltr->buf_col = 0;

  ltr->cursor_row = -1;
  ltr->cursor_col = outChars + lti->inputColCharIndex[inputCursorCol];

  ltr->read_count = charCount;

  LTERM_LOG(ltermReturnInputLine,32,("returning INPUT LINE data\n"));
  LTERM_LOGUNICODE(ltermReturnInputLine,32,(ltr->buf, ltr->read_count));

  return returnCode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ltermReturnOutputLine ( struct lterms lts,
struct LtermRead ltr 
) [static]

Returns output line data (Auxiliary procedure for ltermRead.) The LtermRead structure *LTR contains both input and output parameters.

Returns:
0 if successful, -1 if an error occurred while reading, -3 if more than COUNT characters are present in the line (in this case the first COUNT characters are returned in BUF, and the rest are discarded).

Definition at line 1178 of file ltermIO.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  int charCount, returnCode, j;

  LTERM_LOG(ltermReturnOutputLine,30,
            ("outputChars=%d, promptChars=%d, CursorChar=%d\n",
             lto->outputChars, lto->promptChars, lto->outputCursorChar));

  ltr->opcodes = LTERM_LINEDATA_CODE;

  charCount = lto->outputChars;

  if (charCount <= ltr->max_count) {
    returnCode = 0;
  } else {
    /* Too much data to fit into output buffer; truncate */
    charCount = ltr->max_count;
    returnCode = -3;
  }

  /* Copy output characters (plain text; no markup or escape sequences) */
  ltr->opcodes |= LTERM_OUTPUT_CODE;
  for (j=0; j<charCount; j++) {
    ltr->buf[j] = lto->outputLine[j];
    ltr->style[j] = lto->outputStyle[j];
  }

  if ((lto->promptChars > 0) && (lto->promptChars <= charCount)) {
    /* Set prompt style */
    ltr->opcodes |= LTERM_PROMPT_CODE;
    for (j=0; j<lto->promptChars; j++) {
      ltr->style[j] = LTERM_PROMPT_STYLE;
    }
  }

  ltr->buf_row = -1;
  ltr->buf_col = 0;

  ltr->cursor_row = -1;
  ltr->cursor_col = lto->outputCursorChar;

  ltr->read_count = charCount;

  LTERM_LOG(ltermReturnOutputLine,31,("returning OUTPUT LINE data\n"));
  LTERM_LOGUNICODE(ltermReturnOutputLine,31,(ltr->buf, ltr->read_count));

  return returnCode;
}

Here is the caller graph for this function:

static int ltermReturnScreenData ( struct lterms lts,
struct LtermRead ltr,
int  opcodes,
int  opvals,
int  oprow 
) [static]

Returns processed screen data (Auxiliary procedure for ltermRead.) The LtermRead structure *LTR contains both input and output parameters.

Returns:
0 if successful, -1 if an error occurred while reading, -3 if more than COUNT characters are present in the line (in this case the first COUNT characters are returned in BUF, and the rest are discarded).

Definition at line 976 of file ltermIO.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  int cursorMoved, returnRow, charCount, returnCode;
  int jOffset, j;

  cursorMoved = (lto->returnedCursorRow != lto->cursorRow) ||
                (lto->returnedCursorCol != lto->cursorCol);

  lto->returnedCursorRow = lto->cursorRow;
  lto->returnedCursorCol = lto->cursorCol;

  LTERM_LOG(ltermReturnScreenData,30,("cursorMoved=%d\n", cursorMoved));

  /* Screen mode data with possible modifier flags */
  ltr->opcodes = opcodes;
  ltr->opvals = opvals;

  /* Copy full screen cursor position */
  ltr->cursor_row = lto->returnedCursorRow;
  ltr->cursor_col = lto->returnedCursorCol;

  if (opcodes &
      (LTERM_CLEAR_CODE|LTERM_INSERT_CODE|LTERM_DELETE_CODE|LTERM_SCROLL_CODE)) {
    /* Screen modifier flags; return no character data */
    if (oprow >= 0) {
      ltr->buf_row = oprow;
    } else {
      ltr->buf_row = lto->cursorRow;
    }

    ltr->buf_col = 0;

    ltr->read_count = 0;

    return 0;
  }

  /* Check if any row has been modified */
  returnRow = -1;

  for (j=0; j<lts->nRows; j++)
    if (lto->modifiedCol[j] >= 0) {
      returnRow = j;
      break;
    }

  if (returnRow < 0) {
    /* No modified rows */
    ltr->read_count = 0;
    ltr->buf_row = 0;
    ltr->buf_col = 0;

    if (!cursorMoved && (ltr->opcodes == LTERM_SCREENDATA_CODE)) {
      /* Return no data (***IMPORTANT ACTION, TO PREVENT LOOPING***) */
      ltr->opcodes = 0;
    }

    return 0;
  }

  /* Returning modified row */
  ltr->opcodes |= LTERM_OUTPUT_CODE;

  /* Copy entire row */
  ltr->buf_row = returnRow;
  ltr->buf_col = 0;

  charCount = lts->nCols;

  if (charCount <= ltr->max_count) {
    returnCode = 0;
  } else {
    /* Too much data to fit into output buffer; truncate */
    charCount = ltr->max_count;
    returnCode = -3;
  }

  jOffset = ltr->buf_row * lts->nCols + ltr->buf_col;
  for (j=0; j<charCount; j++) {
    ltr->buf[j]   = lto->screenChar[jOffset+j];
    ltr->style[j] = lto->screenStyle[jOffset+j];
  }

  /* Clear modified flag in returned row */
  lto->modifiedCol[returnRow] = -1;

  ltr->read_count = charCount;

  LTERM_LOG(ltermReturnScreenData,31,("returning SCREEN data\n"));
  LTERM_LOGUNICODE(ltermReturnScreenData,31,(ltr->buf, ltr->read_count));

  return returnCode;
}

Here is the caller graph for this function:

static int ltermReturnStreamData ( struct lterms lts,
struct LtermRead ltr 
) [static]

Returns stream data from STDOUT (Auxiliary procedure for ltermRead.) OPCODES ::= STREAMDATA NEWLINE? ERROR? COOKIESTR? DOCSTREAM? XMLSTREAM? WINSTREAM? The LtermRead structure *LTR contains both input and output parameters.

Returns:
0 if successful, -1 if an error occurred while reading,

Definition at line 839 of file ltermIO.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  UNICHAR *locTerminator;
  int streamTerminated, charCount, deleteCount, j;

  LTERM_LOG(ltermReturnStreamData,30,("start\n"));

  if (lto->streamOpcodes & LTERM_ERROR_CODE) {
    /* Error in stream output; terminate stream abnormally */
    LTERM_LOG(ltermReturnStreamData,32,("Error termination of STREAM mode\n"));

    if (lto->savedOutputMode == LTERM1_SCREEN_MODE) {
      if (ltermSwitchToScreenMode(lts) != 0)
        return -1;
    } else {
      if (ltermSwitchToLineMode(lts) != 0)
        return -1;
    }

    ltr->opcodes = lto->streamOpcodes | LTERM_STREAMDATA_CODE
                                      | LTERM_NEWLINE_CODE;
    ltr->read_count = 0;
    return 0;

  } else if (lto->decodedChars == 0) {
    /* No output data available; return null opcode */
    return 0;
  }

  ltr->opcodes = LTERM_STREAMDATA_CODE | lto->streamOpcodes;

  if (ucslen(lto->streamTerminator) == 0) {
    /* Null terminated stream */
    locTerminator = NULL;
    for (j=0; j<lto->decodedChars; j++) {
      if (lto->decodedOutput[j] == 0) {
        locTerminator = &lto->decodedOutput[j];
        break;
      }
    }

  } else {
    /* Non-null terminated stream */
    assert(lto->decodedChars < MAXCOL);

    /* Insert terminating null character in decoded buffer */
    lto->decodedOutput[lto->decodedChars] = U_NUL;

    /* There should be no NULs in decoded output */
    assert((int)ucslen(lto->decodedOutput) == lto->decodedChars);

    /* Search for stream terminator string in decoded output */
    locTerminator = ucsstr(lto->decodedOutput, lto->streamTerminator);
  }

  /* Stream termination flag */
  streamTerminated = 0;

  if (locTerminator == NULL) {
    /* No terminator found; return decoded stream data */
    charCount = lto->decodedChars;
    if (charCount > ltr->max_count)
      charCount = ltr->max_count;

  } else {
    /* Count stream portion of decoded output (excluding terminator) */
    charCount = locTerminator - lto->decodedOutput;

    if (charCount > ltr->max_count) {
      /* Return only portion of stream data that fits into output buffer,
       * without terminating stream mode
       */
      charCount = ltr->max_count;

    } else {
      /* Return all remaining stream data, terminate stream mode and
       * revert to saved output mode
       */
      streamTerminated = 1;
      if (lto->savedOutputMode == LTERM1_SCREEN_MODE) {
        if (ltermSwitchToScreenMode(lts) != 0)
          return -1;
      } else {
        if (ltermSwitchToLineMode(lts) != 0)
          return -1;
      }
      LTERM_LOG(ltermReturnStreamData,32,("terminating STREAM mode\n"));
    }
  }

  /* Copy stream data to output buffer */
  for (j=0; j<charCount; j++) {
    ltr->buf[j] = lto->decodedOutput[j];
    ltr->style[j] = LTERM_STDOUT_STYLE;
  }

  /* Count of characters read */
  ltr->read_count = charCount;

  /* Count of characters to be deleted */
  deleteCount = charCount;

  if (streamTerminated) {
    /* Stream terminated */
    ltr->opcodes |= LTERM_NEWLINE_CODE;

    /* Delete terminator string from decoded buffer */
    if (ucslen(lto->streamTerminator) == 0) {
      deleteCount += 1;
    } else {
      deleteCount += ucslen(lto->streamTerminator);
    }
  }

  /* Shift remaining characters in decoded buffer */
  for (j=deleteCount; j<lto->decodedChars; j++)
    lto->decodedOutput[j-deleteCount] = lto->decodedOutput[j];

  lto->decodedChars -= deleteCount;

  LTERM_LOG(ltermReturnStreamData,31,("returning STREAM data (%d bytes)\n",
                                         ltr->read_count));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermSendLine ( struct lterms lts,
UNICHAR  uch,
int  echoControl,
int  completionCode 
)

Transmits input line + optional control character UCH to child process.

If UCH is 0, no control character is transmitted. Copy of the transmitted plain text (without any markup or character escapes) is saved in the echo buffer, prefixed by the prompt. If echoControl is true, control character is echoed in printable form. If completionCode == LTERM_NO_COMPLETION, transmit complete line and set input line break flag. If completionCode != LTERM_NO_COMPLETION, transmit only characters to left of current and set completion request flag. Called from ltermLineInput.

Returns:
0 on success, -1 on error.

Definition at line 69 of file ltermIO.c.

{
  struct LtermInput *lti = &(lts->ltermInput);
  struct LtermOutput *lto = &(lts->ltermOutput);
  UNICHAR insch;
  int glyphCount, prefixChars, charCount, sendCount;
  int j, k, startCol, nCols, charIndex;

  LTERM_LOG(ltermSendLine,40,
       ("uch=0x%x, echoControl=%d, completionCode=%d, completionRequest=%d\n",
         uch, echoControl, completionCode, lts->completionRequest));

  if ((lts->completionRequest == LTERM_HISTORY_COMPLETION) &&
      (lts->completionChars > 0)) {
    /* Delete prior completion inserts */
    if (ltermDeleteGlyphs(lti, lts->completionChars) != 0)
      return -1;
  }

  if (completionCode != LTERM_NO_COMPLETION) {
    /* Send only glyphs to left of cursor */
    glyphCount = lti->inputCursorGlyph;

  } else {
    /* Send all glyphs in input line */
    glyphCount = lti->inputGlyphs;
  }

  if (lto->promptChars > 0) {
    /* Insert output prompt into echo buffer */
    prefixChars = lto->promptChars;
  } else {
    /* Insert entire output line into echo buffer */
    prefixChars = lto->outputChars;
  }

  charCount = prefixChars;

  LTERM_LOG(ltermSendLine,42,
            ("lto->promptChars=%d, outputChars=%d, glyphCount=%d\n",
             lto->promptChars, lto->outputChars, glyphCount));

  if (charCount >= MAXCOLM1) {
    /* Buffer overflow; error return */
    LTERM_ERROR("ltermSendLine: Error - character buffer overflow\n");
    return -1;
  }

  for (j=0; j<charCount; j++)
    lts->echoLine[j] = lto->outputLine[j];

  /* Append input line */
  for (j=0; j<glyphCount; j++) {
    startCol = lti->inputGlyphColIndex[j];
    nCols = lti->inputGlyphColIndex[j+1] - startCol;

    for (k=startCol; k<startCol+nCols; k++) {
      charIndex = lti->inputColCharIndex[k];

      insch = lti->inputLine[charIndex];

#if 0
      /* COMMENTED OUT: Plain text not escaped; use later in HTML insert */
      if (insch == U_AMPERSAND) {
        /* Escaped character */

        /* Assert that there is one free character position in buffer */
        assert(lti->inputChars < MAXCOL);

        /* Insert null character at the end of the input buffer */
        lti->inputLine[lti->inputChars] = U_NUL;

        /* Match escape sequence against known escape sequences */
        for (m=0; m<LTERM_XML_ESCAPES; m++) {
          if (ucsncmp(lti->inputLine+charIndex,
                      ltermGlobal.escapeSeq[m],
                      (unsigned int) ltermGlobal.escapeLen[m]) == 0)
            break;
        }

        if (m < LTERM_XML_ESCAPES) {
          /* Subsitute single character for escape sequence */
          insch = (UNICHAR) ltermGlobal.escapeChars[m];
        } else {
          LTERM_WARNING("ltermSendLine: Warning - unknown XML character escape sequence\n");
        }
      }
#endif /* 0 */

      if (charCount >= MAXCOLM1) {
        /* Buffer overflow; error return */
        LTERM_ERROR("ltermSendLine: Error - character buffer overflow\n");
        return -1;

      } else {
        /* Insert character into echo line buffer */
        lts->echoLine[charCount++] = insch;
      }
    }
  }


  /* Transmit data to process */
  sendCount = charCount - prefixChars;

  if (lts->completionRequest != LTERM_NO_COMPLETION) {
    /* Completion already requested */

    /* Send only control character */
    if (uch != U_NUL) {
      if (ltermSendData(lts, &uch, 1) != 0)
        return -1;
    }

  } else {
    if (uch != U_NUL) {
      /* Send line+control character to child process */

      /* Insert control character at the end of the buffer (temporarily) */
      lts->echoLine[charCount] = uch;

      sendCount++;
    }

    if (ltermSendData(lts, lts->echoLine+prefixChars, sendCount) != 0)
      return -1;
  }

  if (completionCode != LTERM_NO_COMPLETION) {
    /* Request completion */
    lts->completionRequest = completionCode;

    /* No completion text inserted yet */
    lts->completionChars = 0;

  } else {
    /* Set input line break flag;
     * cleared only by output line break processing
     */
    lts->inputLineBreak = 1;
  }

  if (echoControl && (charCount+2 < MAXCOLM1)) {
    /* Echo control character in printable form */
    lts->echoLine[charCount++] = U_CARET;
    lts->echoLine[charCount++] = U_ATSIGN + uch;
  }

  /* Set count of echo characters (excluding control character) */
  lts->echoChars = charCount;

  LTERM_LOG(ltermSendLine,41,("glyphCount=%d, sendCount=%d\n",
                                 glyphCount, sendCount));
  LTERM_LOGUNICODE(ltermSendLine,41,(lts->echoLine, charCount));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermWrite ( struct lterms lts,
int opcodes 
) [static]

Writes data from input buffer pipe to pseudo-TTY, processing one complete record read from input buffer pipe and returning OPCODES ::= LINEDATA ( INPUT ( NEWLINE HIDE? )? | INPUT META ( COMPLETION | NEWLINE HIDE? ) ) NOTE: This call may block to read data from input buffer pipe, if lts->inputBufRecord is false.

Non-zero OPCODES means echoable input line data was processed. Zero OPCODES implies that no echoable input data was processed, i.e., an incomplete record or screen/output data processing.

Returns:
0 if successful, -1 on error, and -2 if pseudo-TTY has been closed.

Definition at line 243 of file ltermIO.c.

{
  struct LtermInput *lti = &(lts->ltermInput);
  struct LtermOutput *lto = &(lts->ltermOutput);
  char *byteBuf = (char *) lti->inputBuf;
  int returnCode, availableChars, processedChars, headerChars, totalChars, j;

  LTERM_LOG(ltermWrite,20, ("inputLineBreak=%d, inputBufRecord=%d\n",
                               lts->inputLineBreak, lts->inputBufRecord));

  *opcodes = 0;

  if (!lts->inputBufRecord) {
    /* Complete record not available in buffer; read data from input pipe */
    int readMax, n_read;

    readMax = (PIPEHEADER+MAXCOL)*sizeof(UNICHAR) - lti->inputBufBytes;

    assert(readMax > 0);

    n_read = READ(lts->readBUFFER, byteBuf + lti->inputBufBytes,
                  (SIZE_T) readMax);

    if (n_read < 0) {
      LTERM_WARNING("ltermWrite: Warning - error %d in reading from input buffer pipe\n", n_read);
      return -1;
    }

    LTERM_LOG(ltermWrite,22,
              ("read %d bytes from input buffer pipe\n", n_read));

    if (n_read == 0) {
      /* End of file */
      LTERM_LOG(ltermWrite,21,("input buffer pipe has been closed\n"));

      /* Suspend LTERM */
      lts->suspended = 1;

      return -2;
    }

    /* Update count of bytes read so far */
    lti->inputBufBytes += n_read;

    LTERM_LOGUNICODE(ltermWrite,12,(lti->inputBuf,
                                    lti->inputBufBytes/sizeof(UNICHAR)));

    /* Check if one or more complete records is now available in buffer */
    lts->inputBufRecord = (lti->inputBufBytes >= (int)sizeof(UNICHAR)) &&
  (lti->inputBufBytes >= (PIPEHEADER+lti->inputBuf[0])*((int)sizeof(UNICHAR)));

    if (!lts->inputBufRecord) {
      /* Incomplete input record; return */
      return 0;
    }
  }

  /* availableChars may be zero; such zero length input data records
   * are used to notify the "input thread" about output processing events,
   * such as the detection of a command line prompt (which would
   * enable the command completion input mode)
   */
  availableChars = lti->inputBuf[0];
  processedChars = 0;

  LTERM_LOG(ltermWrite,22, ("inputBuf[0]=%d, inputBuf[1]=%d\n",
                              lti->inputBuf[0], lti->inputBuf[1]));

  if (lti->inputBuf[1] == LTERM_WRITE_CLOSE_MESSAGE) {
    /* LTERM being closed */
    return -2;
  }

  if (lti->inputBuf[1] == LTERM_WRITE_PLAIN_INPUT) {
    /* Process plain text input record */
    int doNotCancelCompletion = 0;

    if (lti->inputMode >= LTERM3_COMPLETION_MODE) {

      if (availableChars == 1) {
        /* Single control character completion requests */

        doNotCancelCompletion =
         ( (lts->completionRequest == LTERM_TAB_COMPLETION) &&
           (lti->inputBuf[2] == U_TAB) ) ||
         ( (lts->completionRequest == LTERM_HISTORY_COMPLETION) &&
            ((lti->inputBuf[2] == U_CTL_P) || (lti->inputBuf[2] == U_CTL_N)) );

      } else if (availableChars == 3) {
        /* Three character escape sequences for up/down arrow keys */
        /* NOTE: Input CSI escape sequence; may not be portable */

        doNotCancelCompletion =
       ( (lts->completionRequest == LTERM_HISTORY_COMPLETION) &&
         (lti->inputBuf[2] == U_ESCAPE) && (lti->inputBuf[3] == U_LBRACKET) &&
         ((lti->inputBuf[4] == U_A_CHAR) || (lti->inputBuf[4] == U_B_CHAR)) );
      }
    }

    if (!doNotCancelCompletion &&
        (lts->completionRequest != LTERM_NO_COMPLETION)) {
      /* Cancel any completion request */

      if (ltermCancelCompletion(lts) != 0)
        return -1;
    }

    LTERM_LOGUNICODE(ltermWrite,12,(lti->inputBuf+PIPEHEADER, availableChars));

    returnCode = ltermPlainTextInput(lts, lti->inputBuf+PIPEHEADER,
                                     availableChars, opcodes);
    if (returnCode < 0)
      return returnCode;

    processedChars = availableChars;

  } else if (lti->inputBuf[1] == LTERM_WRITE_XML_INPUT) {
    /* Insert complete XML element into input line, after checks */

    if (lts->completionRequest != LTERM_NO_COMPLETION) {
      /* Cancel command completion request */
      if (ltermCancelCompletion(lts) != 0)
        return -1;
    }

    LTERM_WARNING("ltermWrite: Warning - LTERM_WRITE_XML_INPUT not yet implemented\n");

    processedChars = availableChars;

  } else if (lti->inputBuf[1] == LTERM_WRITE_PLAIN_OUTPUT) {
    /* Insert plain text in decoded character buffer */
    int decodeMax = MAXCOLM1 - lto->decodedChars;

    processedChars = availableChars;

    if (processedChars > decodeMax)
      processedChars = decodeMax;

    if (processedChars > 0) {
      /* Copy characters to decoded character buffer */
      int offset;

      if ((lto->decodedChars > 0) &&
          lto->incompleteEscapeSequence &&
          (lto->decodedStyle[0] != LTERM_ALTOUT_STYLE)) {
        /* Move incomplete escape sequence to end of decoded buffer */
        for (j=lto->decodedChars-1; j>=0; j--) {
          lto->decodedOutput[j+processedChars] = lto->decodedOutput[j];
          lto->decodedStyle[j+processedChars] = lto->decodedStyle[j];
        }

        /* Incomplete escape sequence no longer at beginning of buffer */
        lto->incompleteEscapeSequence = 0;

        /* Insert new characters at beginning of decoded buffer */
        offset = 0;

      } else {
        /* Append new characters at the end of the decoded buffer */
        offset = lto->decodedChars;
      }

      /* Insert new characters in decoded buffer, with appropriate offset */
      for (j=0; j<processedChars; j++) {
        lto->decodedOutput[j+offset] = lti->inputBuf[PIPEHEADER+j];
        lto->decodedStyle[j+offset] = LTERM_ALTOUT_STYLE;
      }

      /* Increment decoded character count */
      lto->decodedChars += processedChars;
    }

    returnCode = 0;
  }

  if (processedChars == availableChars) {
    /* Delete current record completely from buffer */
    processedChars += PIPEHEADER;
    headerChars = 0;

  } else {
    /* Delete processed characters from current record */
    headerChars = PIPEHEADER;

    /* Decrement character count in record header */
    lti->inputBuf[0] -= processedChars;
  }

  LTERM_LOG(ltermWrite,23, ("processedChars=%d, headerChars=%d\n",
                               processedChars, headerChars));

  /* Shift remaining data in buffer */
  totalChars = lti->inputBufBytes/sizeof(UNICHAR);

  for (j=headerChars; j<(totalChars-processedChars); j++)
    lti->inputBuf[j] = lti->inputBuf[j+processedChars];

  /* Decrement buffer count */
  lti->inputBufBytes -= processedChars*sizeof(UNICHAR);

  /* Check if one or more complete records is now left in buffer */
  lts->inputBufRecord = (lti->inputBufBytes >= (int)sizeof(UNICHAR)) &&
  (lti->inputBufBytes >= (PIPEHEADER+lti->inputBuf[0])*((int)sizeof(UNICHAR)));

  LTERM_LOG(ltermWrite,21,
            ("return opcodes=0x%x, inputBufBytes=%d, inputBufRecord=%d\n",
             *opcodes, lti->inputBufBytes, lts->inputBufRecord));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: