assert(j < lts->screenSize);
assert(j < (lts->nRows * lts->nCols));
int ltermProcessOutput(struct lterms *lts, int *opcodes, int *opvals,                       int *oprow){  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->screenSize);        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_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"));        }      }    }  }  LTERM_LOG(ltermProcessOutput,31,("returned opcodes=0x%X\n", *opcodes));  return 0;}