示例#1
0
int8_t Screen::init( char *userInputBuffer_p, uint8_t *switchToSession_p ) {

  // This always works:
  unsigned char mode = *((unsigned char far *)MK_FP( 0x40, 0x49 ));

  if ( mode == 7 ) {
    colorCard = 0;
    screenBase = (uint8_t far *)MK_FP( 0xb000, 0 );
  }
  else {
    colorCard = 1;
    screenBase = (uint8_t far *)MK_FP( 0xb800, 0 );
  }

  // Call int 10, ah=12 for EGA/VGA config

  union REGS inregs, outregs;
  struct SREGS segregs;

  inregs.h.ah = 0x12;
  inregs.h.bl = 0x10;
  int86x( 0x10, &inregs, &outregs, &segregs );

  if ( outregs.h.bl == 0x10 ) {
    // Failed.  Must be MDA or CGA
    rows = 25;
  }
  else {
    rows = *((unsigned char far *)MK_FP( 0x40, 0x84 )) + 1;
  }

  separatorRow = rows - INPUT_ROWS - 1;
  outputRows = rows - (INPUT_ROWS + 1);

  separatorRowAddr = screenBase + ( separatorRow * BYTES_PER_ROW );
  inputAreaStart = separatorRowAddr + BYTES_PER_ROW;

  cur_y = cur_x = 0;
  cur_y2 = separatorRow + 1;

  input_len = 0;

  userInputBuffer = userInputBuffer_p;
  switchToSession = switchToSession_p;

  insertMode = 1;

  // Draw initial screen
  fillUsingWord( screenBase, 7<<8|32, rows * 80 );
  fillUsingWord( separatorRowAddr, 7<<8|196, 80 );

  return 0;
}
示例#2
0
void Screen::scrollInternal( void ) {

    if ( scrollRegion_top == 0 && scrollRegion_bottom == (terminalLines - 1) ) {

        // Classic scrolling behavior - lines at the top get pushed into to
        // scroll buffer.

        topOffset += BYTES_PER_LINE;
        if ( topOffset == bufferSize ) topOffset = 0;

        // Clear the newly opened line in the virtual buffer.
        // In theory we could do this with the clear method but that has far
        // higher overhead because it is general purpose.

        uint16_t far *tmp = (uint16_t *)(buffer + ScrOffset( 0, cursor_y ));

        uint16_t fillWord = (curAttr<<8) | 0x20;
        fillUsingWord( tmp, fillWord, 80 );

    }

    else {

        // They are using a scroll region - do not add to our private
        // backscroll buffer.

        delLine( scrollRegion_top );

    }

    // Stop updating the real screen - scrolling is slow.
    updateRealScreen = 0;
    virtualUpdated = 1;

}
示例#3
0
void Screen::clearConsole( void ) {
#ifdef __TURBOC__
    textattr( 7 );
    clrscr( );
#else
    //uint16_t len = ScreenRows*80 + ScreenCols;
    uint16_t len = ScreenRows*80;
    fillUsingWord( (uint16_t far *)Screen_base, (7<<8|32), len );
#endif
}
示例#4
0
void Screen::clearInputArea( void ) {

  fillUsingWord( inputAreaStart, (7<<8|32), INPUT_ROWS * screenCols );

  input_len = 0;
  cur_y = cur_x = 0;
  cur_y2 = separatorRow + 1;

  // Put the cursor back in the right spot to be pretty.
  gotoxy( cur_x, cur_y2 );

}
示例#5
0
void Screen::repaintInputArea( uint16_t offset, char far *buffer, uint16_t len ) {

  uint8_t far *target = inputAreaStart + offset*2;

  for ( uint16_t i=0; i < len; i++ ) {
    *target = *buffer;
    buffer++;
    target += 2;
  }

  fillUsingWord( target, (7<<8|32), (SCBUFFER_MAX_INPUT_LEN-offset)*2 );

}
示例#6
0
void Screen::repaintInputArea( uint16_t offset, char far *buffer, uint16_t len ) {

  uint8_t far *target = inputAreaStart + offset*2;

  for ( uint16_t i=0; i < len; i++ ) {

    if ( *buffer < 32 ) {
      *target = 254;
    }
    else {
      *target = *buffer;
    }

    buffer++;
    target += 2;
  }

  // Clear out to the end of the input area.
  fillUsingWord( target, (7<<8|32), (SCBUFFER_MAX_INPUT_LEN-offset)*2 );

}
示例#7
0
void Screen::clear( uint16_t top_x, uint16_t top_y, uint16_t bot_x, uint16_t bot_y ) {

    uint16_t far *start = (uint16_t far *)(buffer + ScrOffset( top_x, top_y ));
    uint16_t far *end = (uint16_t far *)(buffer + ScrOffset( bot_x, bot_y ));

    // Add the +1 at the end because we need to clear the last byte inclusive,
    // not just up to the last byte.

    uint16_t chars = (bot_y*80+bot_x) - (top_y*80+top_x) + 1;
    uint16_t bytes = chars << 1;

    uint16_t fillWord = (curAttr<<8) | 0x20;

    if ( start <= end ) {

        // Contiguous storage
        //
        // for ( uint16_t i=0; i < bytes; i=i+2 ) { *start++ = fillWord; }

#ifdef __TURBOC__
        asm {
            push es;
            push di;
            cld;
            mov ax, fillWord;
            les di, start;
            mov cx, chars;
            rep stosw;
            pop di;
            pop es;
        }
#else
        //for ( uint16_t i=0; i < bytes; i=i+2 ) { *start++ = fillWord; }
        fillUsingWord( start, fillWord, chars );
#endif

    }
    else {
示例#8
0
void Session::puts( uint8_t attr, const char *str ) {

  // Indicate that we need repainting.
  was_updated = 1;

  // We are never going to add more than a few hundred bytes
  // at a time.  Start by normalizing a pointer into the buffer,
  // then convert the normalized pointer back to a far pointer.
  // This avoids the overhead of huge pointer arithmetic on every
  // character.

  uint16_t far *current = virtBuffer;
  uint16_t offset = output_y * BYTES_PER_ROW + (output_x<<1);
  addToPtr( current, offset, uint16_t far * );

  // At this point current pointing at the next location to be written to.
  // (AddToPtr macro normalized the pointer.)


  while ( *str ) {

    if ( *str == '\n' ) {

      // Newline processing - drop to the start of the next line

      str++;
      current += 80-output_x;
      output_y++;
      output_x=0;
    }
    else {

      // Normal character: write it and advance one position

      *current = (attr<<8|*str);
      current++;
      str++;
      output_x++;

      // Did we wrap around the right edge?
      if ( output_x == 80 ) {
        output_y++;
        output_x=0;
      }
    }

    // If after processing that character we are on a new line then
    // we need to check to see if we wrapped around the end of the buffer,
    // clear the new line, and if we have backscroll capability draw the
    // divider.

    // Fix me: the divider should only be drawn once outside of the loop.


    if ( output_x==0 ) {

      if ( output_y == virtBufferRows ) {
        // Wrapped around the end of the buffer.
        output_y = 0;
        current = virtBuffer;
      }

      // Clear new line.  (It was probably used before.)
      fillUsingWord( current, 0, 80 );


      // Put a divider on the next line in case the backscroll buffer
      // is being displayed while it is being modified.

      if ( virtBufferRows > (Screen::outputRows+1) ) {

        // Tmp is already at the start of the line, but we need to be
        // sure that it wasn't supposed to wrap to the start of the buffer.

        // Skip past open line
        uint16_t *tmp = current + 80;

        if ( (output_y + 1) == virtBufferRows ) {
          tmp = (uint16_t far *)virtBuffer;
        }

        fillUsingWord( tmp, 0x0FCD, 80 );

      }

    }

  } // end for


}
示例#9
0
int8_t Screen::init( char *userInputBuffer_p, uint8_t *switchToSession_p ) {


  // This always works: What is our current video mode?
  unsigned char mode = *((unsigned char far *)MK_FP( 0x40, 0x49 ));

  if ( mode == 7 ) {
    colorMode = false;
    screenBase = (uint8_t far *)MK_FP( 0xb000, 0 );
  }
  else {
    colorMode = true;
    screenBase = (uint8_t far *)MK_FP( 0xb800, 0 );
  }


  // Next, find out if we are on an EGA or VGA card
  //
  // If EGA or better is installed then BL gets set to 00 to 03, which is
  // a memory size.  If it comes back the same at the input (0x10) then
  // EGA or better is not installed

  bool isCGAorMDA;

  if ( getEgaMemSize( ) == 0x10 ) {
    // Failed.  Must be MDA or CGA
    screenCols = 80;
    screenRows = 25;
    isCGAorMDA = true;
  }
  else {
    screenCols = *((unsigned char far *)MK_FP( 0x40, 0x4A ));
    screenRows = *((unsigned char far *)MK_FP( 0x40, 0x84 )) + 1;
    isCGAorMDA = false;
  }


  // If we are on a CGA or MDA then do this port voodoo to disable blinking.
  // Otherwise, use the nice interrupt to do it instead.  This is to enable
  // the high bit background colors.

  if ( isCGAorMDA ) {

    uint16_t portBase = *((uint16_t far *)(MK_FP( 0x40, 0x63 ))) + 4;

    uint8_t modeSelectVal = *((uint8_t far *)(MK_FP( 0x40, 0x65 )));
    modeSelectVal = modeSelectVal & 0xDF;

    outp( portBase, modeSelectVal );

  }
  else {

    turnOffEgaBlink( );

  }


  separatorRow = screenRows - INPUT_ROWS - 1;
  outputRows = screenRows - (INPUT_ROWS + 1);

  separatorRowAddr = screenBase + ( separatorRow * (screenCols<<1) );
  inputAreaStart = separatorRowAddr + (screenCols<<1);

  cur_y = cur_x = 0;
  cur_y2 = separatorRow + 1;

  input_len = 0;


  // Storage areas provided by our caller

  userInputBuffer = userInputBuffer_p;
  switchToSession = switchToSession_p;


  insertMode = true;
  eatNextChar = false;
  colorPopup = false;


  // Draw initial screen

  fillUsingWord( screenBase, 7<<8|32, screenRows * screenCols );
  fillUsingWord( separatorRowAddr, 7<<8|196, screenCols );

  return 0;
}