Back to index

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

Go to the source code of this file.

Functions

static int ltermAppendOutput (struct lterms *lts, const char *cbuf, int count, UNISTYLE style, int interleaveCheck, int *interleavedBytes, int rawIncompleteMax, int *rawIncompleteBytes, char *rawIncompleteBuf)
 Process COUNT bytes raw data from CBUF, converting complete character encodings to Unicode, saving RAWINCOMPLETEBYTES in RAWINCOMPLETEBUF, whose maximum size is specified by RAWINCOMPLETEMAX.
static int ltermDecode (const char *rawBuf, int n_total, UNICHAR *decodedBuf, int decodeMax, int decodeNUL, int *rawIncompleteBytes)
 Decodes N_TOTAL bytes in RAWBUF, returning upto DECODEMAX Unicode characters in DECODEDBUF, leaving *RAWINCOMPLETEBYTES at the end of RAWBUF undecoded.
static int ltermPromptLocate (struct lterms *lts)
 Search for prompt string in the output line buffer.
int ltermProcessOutput (struct lterms *lts, int *opcodes, int *opvals, int *oprow)
 Processes output from decoded output buffer and returns *opcodes: OPCODES ::= SCREENDATA BELL? ( CLEAR | INSERT | DELETE | SCROLL )? if ScreenMode data is being returned.
void ltermClearOutputLine (struct lterms *lts)
 Clears output line buffer.
int ltermClearOutputScreen (struct lterms *lts)
 Clears output screen buffer (allocating memory, if first time/resized)
int ltermSwitchToStreamMode (struct lterms *lts, int streamOpcodes, const UNICHAR *streamTerminator)
 Saves current output mode value and switches to stream output mode, with specified opcodes and terminator string.
int ltermSwitchToScreenMode (struct lterms *lts)
 Switches to screen output mode.
int ltermSwitchToLineMode (struct lterms *lts)
 Switches to line output mode.
int ltermReceiveData (struct lterms *lts, int readERR)
 Reads data from process STDOUT and/or STDERR using file descriptors from the LTERM POLL structure, and converts to Unicode, saving incomplete character encodings in corresponding incomplete raw buffers.

Function Documentation

static int ltermAppendOutput ( struct lterms lts,
const char *  cbuf,
int  count,
UNISTYLE  style,
int  interleaveCheck,
int interleavedBytes,
int  rawIncompleteMax,
int rawIncompleteBytes,
char *  rawIncompleteBuf 
) [static]

Process COUNT bytes raw data from CBUF, converting complete character encodings to Unicode, saving RAWINCOMPLETEBYTES in RAWINCOMPLETEBUF, whose maximum size is specified by RAWINCOMPLETEMAX.

If INTERLEAVECHECK, check for starting NEWLINE and other interleavable characters, and if found "decode" just those characters and set INTERLEAVEDBYTES to the number of bytes consumed on return; otherwise INTERLEAVEDBYTES is set to 0. The decoded characters are appended to the decodedOutput buffer, with style STYLE.

Returns:
the number of characters appended (>=0) if successful, -1 if an error occurred during processing, or -2 if pseudo-TTY has been closed.

Definition at line 829 of file ltermOutput.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  int decodeMax, n_decoded, decodeNUL, j;

  LTERM_LOG(ltermAppendOutput,30,("count=%d, style=0x%X, iCheck=%d, rawIncMax=%d\n",
            count, style, interleaveCheck, rawIncompleteMax));

  if (interleaveCheck && (count > 0) && (cbuf[0] == '\n')) {
    /* Raw buffer starts with NEWLINE character; interleave */

    assert(lto->decodedChars < MAXCOLM1);

    /* "Decode" just the NEWLINE character */
    lto->decodedOutput[lto->decodedChars] = U_LINEFEED;
    lto->decodedStyle[lto->decodedChars] = LTERM_STDOUT_STYLE;

    lto->decodedChars++;

    *interleavedBytes = 1;

    LTERM_LOG(ltermAppendOutput,32,("INTERLEAVED %d bytes\n",
                                    *interleavedBytes));

    return 1;
  }

  if (interleavedBytes != NULL)
    *interleavedBytes = 0;

  if (count == 0)
    return 0;

  /* Decode all complete encoded character sequences */
  decodeMax = MAXCOLM1 - lto->decodedChars;
  decodeNUL = (lts->options & LTERM_NONUL_FLAG) == 0;
  n_decoded = ltermDecode(cbuf, count,
                          lto->decodedOutput+lto->decodedChars,
                          decodeMax, decodeNUL,
                          rawIncompleteBytes);

  if (n_decoded < 0)
    return -1;

  /* Save any incomplete raw byte encodings */
  if (*rawIncompleteBytes > rawIncompleteMax) {
    LTERM_ERROR("ltermAppendOutput: Error - too many incomplete raw characters\n");
    return -1;
  }

  for (j=0; j<*rawIncompleteBytes; j++)
    rawIncompleteBuf[j] = cbuf[j+count-*rawIncompleteBytes];

  /* Set decoded character styles */
  for (j=lto->decodedChars; j<lto->decodedChars+n_decoded; j++)
    lto->decodedStyle[j] = style;

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

  LTERM_LOG(ltermAppendOutput,32,("Appended %d bytes\n", n_decoded));

  return n_decoded;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ltermClearOutputLine ( struct lterms lts)

Clears output line buffer.

Definition at line 409 of file ltermOutput.c.

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

  LTERM_LOG(ltermClearOutputLine,40,("\n"));

  lto->outputChars = 0;
  lto->outputCursorChar = 0;
  lto->outputModifiedChar = 0;
  lto->promptChars = 0;

  lts->commandNumber = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermClearOutputScreen ( struct lterms lts)

Clears output screen buffer (allocating memory, if first time/resized)

Definition at line 425 of file ltermOutput.c.

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

  LTERM_LOG(ltermClearOutputScreen,40,("\n"));

  if (lto->screenChar == NULL) {
    /* Allocate memory for full screen */
    int screenSize = lts->nRows * lts->nCols;

    lto->screenChar = (UNICHAR *) MALLOC(screenSize * sizeof(UNICHAR));

    if (lto->screenChar == NULL) {
      LTERM_ERROR("ltermClearOutputScreen: Error - failed to allocate memory for chars\n");
      return -1;
    }

    assert(lto->screenStyle == NULL);
    lto->screenStyle = (UNISTYLE *) MALLOC(screenSize * sizeof(UNISTYLE));

    if (lto->screenStyle == NULL) {
      LTERM_ERROR("ltermClearOutputScreen: Error - failed to allocate memory for style\n");
      return -1;
    }
  }  

  /* Position cursor at home */
  lto->cursorRow = lts->nRows - 1;
  lto->cursorCol = 0;

  /* Blank out entire screen */
  if (ltermInsDelEraseLine(lts, lts->nRows, lts->nRows-1, LTERM_ERASE_ACTION) != 0)
    return -1;

  /* No rows modified yet */
  for (j=0; j<lts->nRows; j++) {
    lto->modifiedCol[j] = -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ltermDecode ( const char *  rawBuf,
int  n_total,
UNICHAR decodedBuf,
int  decodeMax,
int  decodeNUL,
int rawIncompleteBytes 
) [static]

Decodes N_TOTAL bytes in RAWBUF, returning upto DECODEMAX Unicode characters in DECODEDBUF, leaving *RAWINCOMPLETEBYTES at the end of RAWBUF undecoded.

Any NUL (zero) characters in RAWBUF are skipped, unless decodeNUL is true. If there is not enough space in DECODEDBUF for all characters to be decoded, an error is returned.

Returns:
the number of Unicoded characters decoded (>=0) or -1 on error.

Definition at line 907 of file ltermOutput.c.

{
  int n_decoded, result;

  LTERM_LOG(ltermDecode,40,("\n"));

  if (decodeMax < n_total) {
    LTERM_ERROR("ltermDecode: Error - decode buffer overflow\n");
    return -1;
  }

  result = utf8toucs(rawBuf, n_total, decodedBuf, decodeMax,
                     !decodeNUL, rawIncompleteBytes, &n_decoded);

  if (result != 0) {
    LTERM_WARNING("ltermDecode: Warning - Invalid UTF8 data encountered\n");
  }

  LTERM_LOG(ltermDecode,41,("result=%d, incomplete=%d, n_decoded=%d\n",
                            result, *rawIncompleteBytes, n_decoded));
  LTERM_LOGUNICODE(ltermDecode,42,(decodedBuf, n_decoded));

  return n_decoded;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermProcessOutput ( struct lterms lts,
int opcodes,
int opvals,
int oprow 
)

Processes output from decoded output buffer and returns *opcodes: OPCODES ::= SCREENDATA BELL? ( CLEAR | INSERT | DELETE | SCROLL )? if ScreenMode data is being returned.

OPCODES ::= LINEDATA BELL? ( CLEAR | OUTPUT NEWLINE?) if LineMode data is being returned. OPVALS contains return value(s) for specific screen operations such as INSERT, DELETE, and SCROLL. OPROW contains the row value for specific screen operations such as INSERT, DELETE, and SCROLL (or -1, cursor row is to be used).

Returns:
0 on success and -1 on error.

Definition at line 70 of file ltermOutput.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  UNICHAR uch;
  UNISTYLE ustyle;
  int charIndex, returnCode, consumedChars, remainingChars, j;
  int bellFlag;

  LTERM_LOG(ltermProcessOutput,30,("lto->outputMode=%d, cursorChar=%d, Chars=%d\n",
                lto->outputMode, lto->outputCursorChar, lto->outputChars));

  LTERM_LOG(ltermProcessOutput,32, ("lts->commandNumber=%d\n",
                                      lts->commandNumber));

  /* Set default returned opcodes, opvals, oprow */
  *opcodes = 0;
  *opvals = 0;
  *oprow = -1;

  charIndex = 0;
  bellFlag = 0;

  while ((*opcodes == 0) && (charIndex < lto->decodedChars)) {
    uch = lto->decodedOutput[charIndex];
    ustyle = lto->decodedStyle[charIndex] | lto->styleMask;

    consumedChars = 1;

    if (uch == U_ESCAPE) {
      /* Process escape sequence */
      int savedOutputMode = lto->outputMode;

      LTERM_LOG(ltermProcessOutput,31,("ESCAPE sequence\n"));

      returnCode = ltermProcessEscape(lts, lto->decodedOutput+charIndex,
                                      lto->decodedChars-charIndex,
                                      lto->decodedStyle+charIndex,
                                      &consumedChars, opcodes, opvals, oprow);
      if (returnCode < 0)
        return -1;

      if (returnCode == 1) {
        /* Incomplete escape sequence */
        lto->incompleteEscapeSequence = 1;
        if (lto->outputMode == LTERM1_SCREEN_MODE)
          *opcodes = LTERM_SCREENDATA_CODE;
        else
          *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
      }

      /* Assert that change in output mode is a loop terminating condition */
      if (lto->outputMode != savedOutputMode)
        assert(*opcodes != 0);

    } else if (lto->outputMode == LTERM1_SCREEN_MODE) {
      /* Screen mode processing */

      if ((uch >= (UNICHAR)U_SPACE) && (uch != (UNICHAR)U_DEL)) {
        /* Printable non-TAB character */

        LTERM_LOG(ltermProcessOutput,39,("Screen mode, printable char - %c\n",
                      (char) uch));

        if (lto->insertMode) {
          /* Insert blank character at cursor position */
          if (ltermInsDelEraseChar(lts, 1, LTERM_INSERT_ACTION) != 0)
            return -1;
        }

        /* Mark column as being modified */
        if ((lto->modifiedCol[lto->cursorRow] == -1) ||
            (lto->modifiedCol[lto->cursorRow] > lto->cursorCol))
          lto->modifiedCol[lto->cursorRow] = lto->cursorCol;

        /* Replace character and style info at current cursor location */
        j = lto->cursorRow*lts->nCols + lto->cursorCol;

        assert(j < (lts->nRows * lts->nCols));

        lto->screenChar[j] = uch;
        lto->screenStyle[j] = ustyle;

        if (lto->cursorCol < lts->nCols-1) {
          /* Move cursor right */
          lto->cursorCol++;
        }

      } else {
        /* Control character */

        switch (uch) {
        case U_BACKSPACE:                 /* Backspace */
          LTERM_LOG(ltermProcessOutput,32,("Screen mode, BACKSPACE\n"));
          if (lto->cursorCol > 0)
            lto->cursorCol--;
          break;

        case U_TAB:                       /* Tab */
          LTERM_LOG(ltermProcessOutput,32,("Screen mode, TAB\n"));
          lto->cursorCol = ((lto->cursorCol/8)+1)*8;
          if (lto->cursorCol > lts->nCols-1)
            lto->cursorCol = lts->nCols-1;
          break;

        case U_BEL:                       /* Bell */
          LTERM_LOG(ltermProcessOutput,32,("************ Screen mode, BELL\n"));
          bellFlag = 1;
          break;

        case U_CRETURN:                   /* Carriage return */
          lto->cursorCol = 0;
          break;

        case U_LINEFEED:                  /* Newline */
          LTERM_LOG(ltermProcessOutput,32,("************ Screen mode, NEWLINE\n\n"));

          *opcodes =  LTERM_SCREENDATA_CODE;

          if (lto->cursorRow > lto->botScrollRow) {
            /* Not bottom scrolling line; simply move cursor down one row */
            lto->cursorRow--;

          } else {
            /* Delete top scrollable line, scrolling up */
            if (ltermInsDelEraseLine(lts, 1, lto->topScrollRow, LTERM_DELETE_ACTION) != 0)
              return -1;
            *opcodes |= LTERM_DELETE_CODE;
            *opvals = 1;
            *oprow = lto->topScrollRow;
          }
          break;

        default:
          /* Ignore other control characters (including NULs) */
          break;
        }
      }

    } else {
      /* Line mode processing */

      if ( ((uch >= (UNICHAR)U_SPACE) && (uch != (UNICHAR)U_DEL)) ||
           (uch == (UNICHAR)U_TAB)) {
        /* Printable/TAB character; replace/insert at current cursor location
           or append to end of line */

        LTERM_LOG(ltermProcessOutput,39,("Line mode, printable char - %c\n",
                      (char) uch));

        if (lto->outputCursorChar == lto->outputChars) {
          /* Append single character to end of line */

          if (lto->outputChars+1 > MAXCOLM1) {
            /* Output buffer overflow; ignore character */
            LTERM_WARNING("ltermProcessOutput: Warning - output line buffer overflow\n");
          }

          lto->outputLine[lto->outputChars] = uch;
          lto->outputStyle[lto->outputChars] = ustyle;
          lto->outputChars++;           /* Insert character in output line */

          lto->outputCursorChar++;      /* Reposition cursor */

        } else {
          /* Replace/insert single character in the middle of line */

          if (lto->insertMode) {
            /* Insert blank character at cursor position */
            if (ltermInsDelEraseChar(lts, 1, LTERM_INSERT_ACTION) != 0)
              return -1;
          }

          /* Overwrite single character in the middle of line */
          lto->outputLine[lto->outputCursorChar] = uch;
          lto->outputStyle[lto->outputCursorChar] = ustyle;

          /* Note modifications */
          if (lto->outputCursorChar < lto->outputModifiedChar)
            lto->outputModifiedChar = lto->outputCursorChar;

          lto->outputCursorChar++;      /* Reposition cursor */
        }

      } else {
        /* Control character */

        switch (uch) {
        case U_BACKSPACE:                /* Backspace */
          LTERM_LOG(ltermProcessOutput,32,("Line mode, BACKSPACE\n"));
          if (lto->outputCursorChar > 0)
            lto->outputCursorChar--;
          break;

        case U_CRETURN:                  /* Carriage return */
          LTERM_LOG(ltermProcessOutput,32,("Line mode, CRETURN\n"));
          lto->outputCursorChar = 0;
          break;

        case U_BEL:                      /* Bell */
          LTERM_LOG(ltermProcessOutput,32,("************ Line mode, BELL\n"));
          bellFlag = 1;
          break;

        case U_CTL_L:                    /* Formfeed; clear line and return */
          LTERM_LOG(ltermProcessOutput,32,("************ Line mode, FORMFEED\n\n"));

          ltermClearOutputLine(lts);
          *opcodes = LTERM_LINEDATA_CODE | LTERM_CLEAR_CODE;
          break;

        case U_LINEFEED:                  /* Newline; return complete line */
          LTERM_LOG(ltermProcessOutput,32,("************ Line mode, NEWLINE\n\n"));

          *opcodes =  LTERM_LINEDATA_CODE
                     | LTERM_OUTPUT_CODE
                     | LTERM_NEWLINE_CODE;
          break;

        default:
          /* Ignore other control characters (including NULs) */
          break;
        }
      }
    }

    /* Increment character index */
    charIndex += consumedChars;
  }

  /* Determine count of unprocessed characters */
  remainingChars = lto->decodedChars - charIndex;

  if (remainingChars > 0) {
    /* Move unprocessed output to beginning of decode buffer */

    LTERM_LOG(ltermProcessOutput,32,("Moved %d chars to beginning of decodedOutput\n", remainingChars));
    for (j=0; j<remainingChars; j++) {
      lto->decodedOutput[j] = lto->decodedOutput[j+charIndex];
      lto->decodedStyle[j] = lto->decodedStyle[j+charIndex];
    }
  }

  /* Update remaining decoded character count */
  lto->decodedChars = remainingChars;

  if (*opcodes == 0) {
    /* All output processed; without any special terminating condition */
    if (lto->outputMode == LTERM1_SCREEN_MODE) {
      /* Full screen mode */
      *opcodes = LTERM_SCREENDATA_CODE;

    } else {
      /* Line mode */
      *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
    }
  }

  /* Set bell code */
  if (bellFlag)
    *opcodes |= LTERM_BELL_CODE;

  if (*opcodes & LTERM_LINEDATA_CODE) {
    /* Returning line mode data; check for prompt */

    if ((lts->commandNumber == 0) ||
        (lto->outputModifiedChar < lto->promptChars)) {
      /* If not command line or if "prompt string" may have been modified,
       * search for prompt
       */
      int promptLen;

      LTERM_LOG(ltermProcessOutput,39,("Prompt? modifiedChar=%d, promptChars=%d\n",
                     lto->outputModifiedChar, lto->promptChars));

      /* Reset modification marker */
      lto->outputModifiedChar = lto->outputChars;

      /* Check if prompt string is present in output */
      promptLen = ltermPromptLocate(lts);

      if (promptLen > 0) {
        /* Prompt string found */
        lto->promptChars = promptLen;

        if (lts->commandNumber == 0) {
          /* Set command number */

          /* New command number */
          if (lts->lastCommandNum == 0xFFFF)
            lts->lastCommandNum = 0;
          lts->lastCommandNum++;

          lts->commandNumber = lts->lastCommandNum;

          LTERM_LOG(ltermProcessOutput,32,
                    ("************ Prompt found; commandNumber=%d\n\n",
                     lts->commandNumber));
        }

      } else {
        /* No prompt string */
        if (lts->commandNumber != 0) {
          /* Unset command number and prompt columns */
          UNICHAR temLine[2] = {0, LTERM_WRITE_PLAIN_INPUT};

          lts->commandNumber = 0;
          lto->promptChars = 0;

          /* Notify "input thread" by writing null input record */
          WRITE(lts->writeBUFFER, temLine, 2*sizeof(UNICHAR));

          LTERM_LOG(ltermProcessOutput,32,
                    ("************  No prompt found; not command line\n\n"));
        }
      }
    }
  }

  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(ltermProcessOutput,38,("modifiedRows=%s\n", modifiedRows));
  }

  LTERM_LOG(ltermProcessOutput,31,("returned opcodes=0x%X\n", *opcodes));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ltermPromptLocate ( struct lterms lts) [static]

Search for prompt string in the output line buffer.

TEMPORARY implementation: assume promptRegexp is just a list of delimiters

Returns:
the length of the matching prompt string, or 0 if there is no match.

Definition at line 941 of file ltermOutput.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  int prefixCount, promptLen;

  LTERM_LOG(ltermPromptLocate,49,("lto->outputChars=%d\n",
                lto->outputChars));

  /* Assert that there is at least one free character in the buffer */
  assert(lto->outputChars < MAXCOL);

  if (lto->outputChars == 0)
    return 0;

  /* Insert null character at the end of the output buffer */
  lto->outputLine[lto->outputChars] = U_NUL;

  /* Determine length of initial non-delimiter prefix */
  prefixCount = ucscspn(lto->outputLine, lts->promptRegexp);

  if (prefixCount+1 >= lto->outputChars) {
    promptLen = 0;

  } else {
    /* Skip any whitespace following the delimiter */
    const UNICHAR spaceStr[3] = {U_SPACE, U_TAB, U_NUL};
    int spaceCount = ucsspn(lto->outputLine+prefixCount+1, spaceStr);

    promptLen = prefixCount + 1 + spaceCount;

    LTERM_LOGUNICODE(ltermPromptLocate,41,(lto->outputLine, promptLen));
  }

  return promptLen;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermReceiveData ( struct lterms lts,
int  readERR 
)

Reads data from process STDOUT and/or STDERR using file descriptors from the LTERM POLL structure, and converts to Unicode, saving incomplete character encodings in corresponding incomplete raw buffers.

Decoded characters are appended to the decodedOutput buffer, with appropriate style settings. If READERR is false, STDERR is never read.

Returns:
the number of decoded characters appended (>=0) if successful, -1 if an error occurred during processing, or -2 if pseudo-TTY has been closed.

Definition at line 616 of file ltermOutput.c.

{
  struct LtermOutput *lto = &(lts->ltermOutput);
  char temERRBuf[MAXCOL], temOUTBuf[MAXCOL];
  int readERRMax, readOUTMax;
  int nReadERR, nTotalERR, nReadOUT, nTotalOUT;
  int interleavedBytes, n_decoded, n_decoded_tot, j;

  LTERM_LOG(ltermReceiveData,30,("\n"));

  nTotalERR = 0;
  if (readERR && (lto->pollFD[POLL_STDERR].POLL_REVENTS != 0)) {
    /* Read data from STDERR */

    /* Read maximum number of bytes that will all fit into decodedOutput
       when decoded, assuming number of decoded characters will not exceed
       the number of encoded bytes */

    readERRMax = MAXCOLM1 - lto->decodedChars - lto->rawERRBytes;

    /* Reduce by half to leave some space for STDOUT data */
    readERRMax = readERRMax / 2;

    if (readERRMax <= 0) {
      /* Decoded buffer overflow */
      LTERM_WARNING("ltermReceiveData: Warning - decoded buffer overflow\n");

      /* Non-fatal error recovery; return without reading */
      return 0;
    }

    /* Copy any incomplete raw output to beginning of buffer */
    for (j=0; j<lto->rawERRBytes; j++)
      temERRBuf[j] = lto->rawERRBuf[j];

    /* Read STDERRdata (blocking mode) */
    nReadERR = READ(lto->pollFD[POLL_STDERR].fd,
                    temERRBuf + lto->rawERRBytes, (SIZE_T) readERRMax);

    if (nReadERR < 0) {
#if defined(DEBUG_LTERM) && !defined(USE_NSPR_IO)
      int errcode = errno;
      /*    perror("ltermReceiveData"); */
#else
      int errcode = 0;
#endif
      LTERM_ERROR( "ltermReceiveData: Error %d in reading from process STDERR\n",
                   errcode);
      return -1;
    }

    if (nReadERR == 0) {
      /* End of file => pseudo-TTY has been closed */
      LTERM_LOG(ltermReceiveData,31,("pseudo-TTY has been closed\n"));

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

      return -2;
    }


    LTERM_LOG(ltermReceiveData,32,("Read %d raw bytes from STDERR\n", nReadERR));
    nTotalERR = nReadERR + lto->rawERRBytes;
  }

  nTotalOUT = 0;
  if (lto->pollFD[POLL_STDOUT].POLL_REVENTS != 0) {
    /* Read data from STDOUT */

    /* Read maximum number of bytes that will all fit into decodedOutput
       when decoded, assuming number of decoded characters will not exceed
       the number of encoded bytes */
    readOUTMax = MAXCOLM1 - lto->decodedChars - lto->rawOUTBytes - nTotalERR;

    if (readOUTMax <= 0) {
      /* Decoded buffer overflow */
      LTERM_WARNING("ltermReceiveData: Warning - decoded buffer overflow\n");

      /* Non-fatal error recovery; return without reading */
      return 0;
    }

    /* Copy any incomplete raw output to beginning of buffer */
    for (j=0; j<lto->rawOUTBytes; j++)
      temOUTBuf[j] = lto->rawOUTBuf[j];

    /* Read STDOUTdata (blocking mode) */
    nReadOUT = READ(lto->pollFD[POLL_STDOUT].fd,
                    temOUTBuf + lto->rawOUTBytes, (SIZE_T) readOUTMax);

    if (nReadOUT < 0) {
#if defined(DEBUG_LTERM) && !defined(USE_NSPR_IO)
      int errcode = errno;
      /*    perror("ltermReceiveData"); */
#else
      int errcode = 0;
#endif
      LTERM_ERROR( "ltermReceiveData: Error %d in reading from process STDOUT\n",
                   errcode);
      return -1;
    }

    if (nReadOUT == 0) {
      /* End of file => pseudo-TTY has been closed */
      LTERM_LOG(ltermReceiveData,31,("pseudo-TTY has been closed\n"));

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

      return -2;
    }

    LTERM_LOG(ltermReceiveData,32,("Read %d raw bytes from STDOUT\n", nReadOUT));

    nTotalOUT = nReadOUT + lto->rawOUTBytes;
  }

  n_decoded_tot = 0;

  if (lts->readERRfirst) {
    /* Decode STDERR data first */
    interleavedBytes = 0;
    n_decoded = ltermAppendOutput(lts, temERRBuf, nTotalERR,
                                  LTERM_STDERR_STYLE,
                                  lts->interleave, &interleavedBytes,
                                  MAXRAWINCOMPLETE,
                                  &(lto->rawERRBytes), lto->rawERRBuf);
    if (n_decoded < 0)
      return -1;
    n_decoded_tot += n_decoded;

    /* Decode STDOUT data next */
    n_decoded = ltermAppendOutput(lts, temOUTBuf, nTotalOUT,
                                  LTERM_STDOUT_STYLE,
                                  0, NULL,
                                  MAXRAWINCOMPLETE,
                                  &(lto->rawOUTBytes), lto->rawOUTBuf);
    if (n_decoded < 0)
      return -1;
    n_decoded_tot += n_decoded;

    if (interleavedBytes > 0) {
      /* Decode remaining STDERR data */
      n_decoded = ltermAppendOutput(lts, temERRBuf+interleavedBytes,
                                    nTotalERR-interleavedBytes,
                                    LTERM_STDERR_STYLE,
                                    0, NULL,
                                    MAXRAWINCOMPLETE,
                                    &(lto->rawERRBytes), lto->rawERRBuf);
      if (n_decoded < 0)
        return -1;
      n_decoded_tot += n_decoded;
    }

  } else {
    /* Decode STDOUT data first */
    interleavedBytes = 0;
    n_decoded = ltermAppendOutput(lts, temOUTBuf, nTotalOUT,
                                  LTERM_STDOUT_STYLE,
                                  lts->interleave, &interleavedBytes,
                                  MAXRAWINCOMPLETE,
                                  &(lto->rawOUTBytes), lto->rawOUTBuf);
    if (n_decoded < 0)
      return -1;
    n_decoded_tot += n_decoded;

    /* Decode STDERR data next */
    n_decoded = ltermAppendOutput(lts, temERRBuf, nTotalERR,
                                  LTERM_STDERR_STYLE,
                                  0, NULL,
                                  MAXRAWINCOMPLETE,
                                  &(lto->rawERRBytes), lto->rawERRBuf);
    if (n_decoded < 0)
      return -1;
    n_decoded_tot += n_decoded;

    if (interleavedBytes > 0) {
      /* Decode remaining STDOUT data */
      n_decoded = ltermAppendOutput(lts, temOUTBuf+interleavedBytes,
                                    nTotalOUT-interleavedBytes,
                                    LTERM_STDOUT_STYLE,
                                    0, NULL,
                                    MAXRAWINCOMPLETE,
                                    &(lto->rawOUTBytes), lto->rawOUTBuf);
      if (n_decoded < 0)
        return -1;
      n_decoded_tot += n_decoded;
    }
  }

  if (n_decoded_tot > 0) {
    /* New characters have been decoded; no longer incomplete escape seq. */
    lto->incompleteEscapeSequence = 0;
  }

  return n_decoded_tot;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermSwitchToLineMode ( struct lterms lts)

Switches to line output mode.

Returns:
0 on success and -1 on error.

Definition at line 564 of file ltermOutput.c.

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

  LTERM_LOG(ltermSwitchToLineMode,40,("\n"));

  if (lto->outputMode == LTERM1_SCREEN_MODE) {
    /* Switching from screen mode to line mode */

    /* Switch to line input mode */
    ltermClearInputLine(lts);

    if (lts->restoreInputEcho) {
      /* Re-enable input echo */
      lts->disabledInputEcho = 0;
      lts->restoreInputEcho = 0;
    }

    /* Clear styleMask */
    lto->styleMask = 0;

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

    /* Copy bottom line to line output buffer ??? */
    lto->outputChars = lts->nCols;

    assert(lts->nCols < MAXCOL);

    for (j=0; j<lts->nCols; j++) {
      lto->outputLine[j] =  lto->screenChar[j];
      lto->outputStyle[j] = lto->screenStyle[j];
    }

  }

  lto->outputMode = LTERM2_LINE_MODE;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermSwitchToScreenMode ( struct lterms lts)

Switches to screen output mode.

Returns:
0 on success and -1 on error.

Definition at line 523 of file ltermOutput.c.

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

  LTERM_LOG(ltermSwitchToScreenMode,40,("\n"));

  if (lto->outputMode == LTERM2_LINE_MODE) {
    /* Switching from line mode to screen mode */

    /* Clear styleMask */
    lto->styleMask = 0;

    /* Clear screen */
    if (ltermClearOutputScreen(lts) != 0)
      return -1;

    /* Reset returned cursor location */
    lto->returnedCursorRow = -1;
    lto->returnedCursorCol = -1;

    /* Scrolling region */
    lto->topScrollRow = lts->nRows-1;
    lto->botScrollRow = 0;

    /* Disable input echo */
    lts->restoreInputEcho = !lts->disabledInputEcho;
    lts->disabledInputEcho = 1;

    /* Switch to raw input mode */
    ltermSwitchToRawMode(lts);

  }

  lto->outputMode = LTERM1_SCREEN_MODE;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermSwitchToStreamMode ( struct lterms lts,
int  streamOpcodes,
const UNICHAR streamTerminator 
)

Saves current output mode value and switches to stream output mode, with specified opcodes and terminator string.

Returns:
0 on success and -1 on error.

Definition at line 473 of file ltermOutput.c.

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

  LTERM_LOG(ltermSwitchToStreamMode,40,("streamOpcodes=0x%x\n",streamOpcodes));

  if (streamTerminator != NULL) {
    /* Save terminator string (may be null) */
    strLength = ucslen(streamTerminator);
    ucsncpy( lto->streamTerminator, streamTerminator, MAXSTREAMTERM);

    LTERM_LOGUNICODE(ltermSwitchToStreamMode,41,(streamTerminator,
                                                 (int) strLength));
  } else {
    /* Null terminator */
    strLength = 0;
    lto->streamTerminator[0] = U_NUL;
  }

  if (strLength > MAXSTREAMTERM-1) {
    LTERM_ERROR("ltermSwitchToStreamMode: Error - terminator string too long\n");
    return -1;
  }

  if (lts->options & LTERM_NONUL_FLAG) {
    /* No decoding of NUL characters */
    if (strLength == 0) {
      LTERM_ERROR("ltermSwitchToStreamMode: Error - null terminator string not allowed\n");
      return -1;
    }
  } else {
    /* Decoding NUL characters */
    if (strLength > 0) {
      LTERM_ERROR("ltermSwitchToStreamMode: Error - terminator string must be NUL\n");
      return -1;
    }
  }

  lto->savedOutputMode = lto->outputMode;
  lto->outputMode = LTERM0_STREAM_MODE;
  lto->streamOpcodes = streamOpcodes;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: