/*++ Copyright (c) 1989 Microsoft Corporation Module Name: violvb.c Abstract: This module contains the Vio LVB routines Author: Michael Jarus (mjarus) 28-Apr-1992 Environment: User Mode Only Revision History: --*/ #define WIN32_ONLY #include "os2ses.h" #include "trans.h" #include "vio.h" #include "os2win.h" #include #include #include #define GET_LVB_PTR( row, col ) &LVBBuffer[((row) * SesGrp->ScreenColNum + (col)) << SesGrp->VioLength2CellShift] #define GET_LVB_ATT_PTR( row, col ) &LVBBuffer[(((row) * SesGrp->ScreenColNum + (col)) << SesGrp->VioLength2CellShift) + 1] typedef struct _attr_3_bytes { UCHAR Attr[3]; } ATTR_3_BYTES, *PATTR_3_BYTES; #if DBG //#define TEST_VIO_LVB 1 BOOL Ow2VioLvbIgnoreTest = FALSE; #endif PUCHAR Ow2VioLvbTestBuff = NULL; DWORD VioLVBInit() { #if DBG #if TEST_VIO_LVB if((Ow2VioLvbTestBuff = HeapAlloc(HandleHeap, 0, SesGrp->MaxLVBsize)) == NULL) { ASSERT1( "VioLVBInit: unable to allocate from heap to test VIO-LVB", FALSE ); return(1L); } #endif #endif return(0L); } VOID VioLVBInitForSession() { #if DBG #if TEST_VIO_LVB ULONG Length = (ULONG)SesGrp->LVBsize; Ow2VioGetLVBBuf(&Length); #endif #endif } DWORD Ow2VioGetLVBBuf( IN PULONG Length ) { #if DBG if ((*Length >> SesGrp->VioLength2CellShift) != SesGrp->ScreenSize) KdPrint(("OS2SES(VioLVB-VioGetBuf): partial length %lu form %lu\n", *Length >> SesGrp->VioLength2CellShift, SesGrp->ScreenSize)); #endif SesGrp->LVBOn = TRUE; // start echo to LVB buffer return(Ow2VioReadCellStr( Length, 0, 0, LVBBuffer )); } DWORD Ow2LvbUpdateLVBBuffer() { if (SesGrp->LVBOn) { IN ULONG Length = SesGrp->LVBsize; return(Ow2VioGetLVBBuf(&Length)); } return(NO_ERROR); } DWORD Ow2VioShowLVBBuf( IN ULONG Length, IN ULONG Offset ) { DWORD Rc; ULONG VioMask = ~(ULONG)SesGrp->VioLengthMask; if ( Offset & VioMask ) { Length += Offset & VioMask; Offset = Offset & (ULONG)SesGrp->VioLengthMask; } if ( Length & VioMask ) { Length = (Length + SesGrp->BytesPerCell) & SesGrp->VioLengthMask; } if (( Length + Offset) > (ULONG)SesGrp->LVBsize) { Length = SesGrp->LVBsize - Offset; } Rc = Ow2VioWriteCellStr( Length, ((Offset >> SesGrp->VioLength2CellShift) / SesGrp->ScreenColNum), ((Offset >> SesGrp->VioLength2CellShift) % SesGrp->ScreenColNum), ((PBYTE)LVBBuffer) + Offset ); return(Rc); } #if DBG VOID VioLVBTestBuff(IN PVOID DestBuffer) { #if TEST_VIO_LVB if(!Ow2VioLvbIgnoreTest && memcmp( DestBuffer, LVBBuffer, SesGrp->LVBsize)) { KdPrint(("Ow2VioReadCellStr: diff buffer\n")); memmove( LVBBuffer, DestBuffer, SesGrp->LVBsize); } #else UNREFERENCED_PARAMETER(DestBuffer); #endif } VOID VioLVBTestScroll() { #if TEST_VIO_LVB ULONG Length = SesGrp->ScreenSize << SesGrp->VioLength2CellShift; ULONG LineLength = SesGrp->ScreenColNum << SesGrp->VioLength2CellShift; UCHAR *Buffer = &Ow2VioLvbTestBuff[0], *Ptr, *Ptr1, *Offset; ULONG i, j, k; if (Ow2VioLvbTestBuff) { Ow2VioLvbIgnoreTest = TRUE; Ow2VioReadCellStr( &Length, 0, 0, Ow2VioLvbTestBuff ); Ow2VioLvbIgnoreTest = FALSE; for ( i = 0, Offset = &LVBBuffer[0] ; i < (ULONG)SesGrp->ScreenRowNum ; i++, Buffer += LineLength, Offset += LineLength ) { if(memcmp( Buffer, Offset, LineLength)) { Ptr = Buffer; Ptr1 = Offset; for (j = 0 ; j < LineLength ; j++ ) { if (Ptr[j] != Ptr1[j]) { break; } } KdPrint(("VioScroll: diff buffer line %d, Pos %d\n", i, j)); KdPrint((" LVB: %2.2x%2.2x%2.2x%2.2x, ... %2.2x; Screen: %2.2x%2.2x%2.2x%2.2x, ... %2.2x\n", Ptr1[0], Ptr1[1], Ptr1[2], Ptr1[3], Ptr1[j], Ptr[0], Ptr[1], Ptr[2], Ptr[3], Ptr[j])); for ( j = 0, k = 0 ; j < 5 ; j++, k += 0x20 ) { Ptr = Offset + k; KdPrint((" LVB-%d: %2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x\n", j, Ptr[0], Ptr[1], Ptr[2], Ptr[3], Ptr[4], Ptr[5], Ptr[6], Ptr[7], Ptr[8], Ptr[9], Ptr[10], Ptr[11], Ptr[12], Ptr[13], Ptr[14], Ptr[15], Ptr[16], Ptr[17], Ptr[18], Ptr[19], Ptr[20], Ptr[21], Ptr[22], Ptr[23], Ptr[24], Ptr[25], Ptr[26], Ptr[27], Ptr[28], Ptr[29], Ptr[30], Ptr[31])); Ptr = Buffer + k; KdPrint((" Scr-%d: %2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x,%2.2x%2.2x%2.2x%2.2x\n", j, Ptr[0], Ptr[1], Ptr[2], Ptr[3], Ptr[4], Ptr[5], Ptr[6], Ptr[7], Ptr[8], Ptr[9], Ptr[10], Ptr[11], Ptr[12], Ptr[13], Ptr[14], Ptr[15], Ptr[16], Ptr[17], Ptr[18], Ptr[19], Ptr[20], Ptr[21], Ptr[22], Ptr[23], Ptr[24], Ptr[25], Ptr[26], Ptr[27], Ptr[28], Ptr[29], Ptr[30], Ptr[31])); } memmove( Offset, Buffer, LineLength); } } } #endif } #endif VOID VioLVBCopyStr( IN PUCHAR Sour, IN COORD Coord, IN ULONG Length) { if(SesGrp->LVBOn && Length) { register UCHAR *Ptr; register ULONG Offset = (ULONG)SesGrp->BytesPerCell; register ULONG Len = Length; register PUCHAR Sou = Sour; Ptr = GET_LVB_PTR( Coord.Y, Coord.X ); #ifdef DBCS // MSKK Oct.13.1993 V-AkihiS if (Offset == 2) { for (;Len-- ; ) { *Ptr = *Sou++; Ptr += Offset; } } else { for (;Len-- ; ) { *Ptr = *Sou; // copy character to lvb Ptr += Offset-1; // skip to 3rd byte attr if (Ow2NlsIsDBCSLeadByte(*Sou++, SesGrp->VioCP)) { *Ptr++ = OS2_COMMON_LVB_LEADING_BYTE; if (Len) { // // Copy trailing byte charater, and mark // this char as trailing byte // *Ptr = *Sou++; Ptr += Offset-1; // skip to 3rd byte attr *Ptr++ = OS2_COMMON_LVB_TRAILING_BYTE; Len--; } else { // // If last written character was a lead byte, // erase it. // *(Ptr-Offset) = ' '; *(Ptr-1) = OS2_COMMON_LVB_SBCS; } } else { // // Copy SBCS charater, and mark this char // as SBCS // *Ptr++ = OS2_COMMON_LVB_SBCS; } } } #else for (;Len-- ; ) { *Ptr = *Sou++; Ptr += Offset; } #endif } } VOID VioLVBCopyCellStr( IN PUCHAR Sour, IN COORD Coord, IN ULONG LengthInCell) { if(SesGrp->LVBOn && LengthInCell) { #ifdef DBCS // MSKK Oct.13.1993 V-AkihiS if (SesGrp->BytesPerCell == 2) { memmove( GET_LVB_PTR( Coord.Y, Coord.X ), Sour, LengthInCell << SesGrp->VioLength2CellShift); } else { register UCHAR *Ptr; register ULONG Len = LengthInCell; register PUCHAR Sou = Sour; Ptr = GET_LVB_PTR( Coord.Y, Coord.X ); for (;Len-- ; ) { if (Ow2NlsIsDBCSLeadByte(*Sou, SesGrp->VioCP)) { // // Copy leading byte charater, 1st attr and 2nd attr // and put leading byte attr to 3rd attr // *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = OS2_COMMON_LVB_LEADING_BYTE; Sou++; // skip source 3rd attr. if (Len) { // // Copy trailing byte charater, and mark // this char as trailing byte // *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = OS2_COMMON_LVB_TRAILING_BYTE; Sou++; // skip source 3rd attr. Len--; } else { // // If last written chell was a lead byte, // erase it. // *(Ptr-4) = ' '; *(Ptr-1) = OS2_COMMON_LVB_SBCS; } } else { // // Copy SBCS charater, and mark this char // as SBCS // *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = *Sou++; *Ptr++ = OS2_COMMON_LVB_SBCS; Sou++; // skip source 3rd attr. } } } #else memmove( GET_LVB_PTR( Coord.Y, Coord.X ), Sour, LengthInCell << SesGrp->VioLength2CellShift); #endif } } #ifdef DBCS // MSKK Oct.13.1993 V-AkihiS VOID VioLVBFillChar(IN PBYTE pChar, IN COORD Coord, IN ULONG LengthInCell) { if(SesGrp->LVBOn && LengthInCell) { register UCHAR *Ptr; register ULONG Offset = (ULONG)SesGrp->BytesPerCell; register ULONG Len = LengthInCell; register PBYTE pCha = pChar; Ptr = GET_LVB_PTR( Coord.Y, Coord.X ); if (Offset == 2) { if (Ow2NlsIsDBCSLeadByte(*pCha, SesGrp->VioCP)) { Len /= 2; for ( ;Len-- ; ) { *Ptr = *pCha; Ptr += Offset; *Ptr = *(pCha+1); Ptr += Offset; } } else { for ( ;Len-- ; ) { *Ptr = *pCha; Ptr += Offset; } } } else { if (Ow2NlsIsDBCSLeadByte(*pCha, SesGrp->VioCP)) { Len /= 2; for ( ;Len--; ) { *Ptr = *pCha; Ptr += Offset-1; *Ptr++ = OS2_COMMON_LVB_LEADING_BYTE; *Ptr = *(pCha+1); Ptr += Offset-1; *Ptr++ = OS2_COMMON_LVB_TRAILING_BYTE; } } else { for ( ;Len-- ; ) { *Ptr = *pCha; Ptr += Offset -1; *Ptr++ = OS2_COMMON_LVB_SBCS; } } } } } #else VOID VioLVBFillChar(IN BYTE Char, IN COORD Coord, IN ULONG LengthInCell) { if(SesGrp->LVBOn && LengthInCell) { register UCHAR *Ptr; register ULONG Offset = (ULONG)SesGrp->BytesPerCell; register ULONG Len = LengthInCell; register BYTE Cha = Char; Ptr = GET_LVB_PTR( Coord.Y, Coord.X ); for ( ;Len-- ; ) { *Ptr = Cha; Ptr += Offset; } } } #endif VOID VioLVBFillAtt( IN PBYTE pAttr, IN COORD Coord, IN ULONG LengthInCell) { if(SesGrp->LVBOn && LengthInCell) { if ( SesGrp->BytesPerCell == 2 ) { register PUCHAR Ptr; register ULONG Offset = (ULONG)SesGrp->BytesPerCell; register ULONG Len = LengthInCell; register BYTE Att = *pAttr; Ptr = GET_LVB_ATT_PTR( Coord.Y, Coord.X ); for ( ;Len-- ; ) { *Ptr = Att; Ptr += Offset; } } else { register PATTR_3_BYTES Ptr; register ULONG Offset = (ULONG)SesGrp->BytesPerCell; register ULONG Len = LengthInCell; register ATTR_3_BYTES Att = *(PATTR_3_BYTES)pAttr; Ptr = (PATTR_3_BYTES)GET_LVB_ATT_PTR( Coord.Y, Coord.X ); for ( ;Len-- ; ) { #ifdef DBCS // MSKK Jun.28.1992 KazuM // MSKK Oct.13.1993 V-AkihiS // // retain char type attribute in 3rd byte attriute. // Att.Attr[2] = Ptr->Attr[2]; *Ptr = Att; Ptr = (PATTR_3_BYTES)((PUCHAR)Ptr + Offset); #else *Ptr = Att; Ptr += Offset; #endif } } } } VOID VioLVBFillCell(IN PBYTE pCell, IN COORD Coord, IN ULONG LengthInCell) { UCHAR *Ptr; ULONG Pattern; if(SesGrp->LVBOn && LengthInCell) { Ptr = GET_LVB_PTR( Coord.Y, Coord.X ); #ifdef DBCS // MSKK Oct.14.1993 V-AkihiS if ( SesGrp->BytesPerCell == 4 ) { if (Ow2NlsIsDBCSLeadByte(pCell[0], SesGrp->VioCP)) { register ATTR_3_BYTES LeadAttr = *(PATTR_3_BYTES)(&pCell[1]); register ATTR_3_BYTES TrailAttr = *(PATTR_3_BYTES)(&pCell[5]); register ULONG Len = LengthInCell / 2; LeadAttr.Attr[2] = OS2_COMMON_LVB_LEADING_BYTE; TrailAttr.Attr[2] = OS2_COMMON_LVB_TRAILING_BYTE; for ( ; Len-- ; ) { // // Put leading byte cell // *Ptr++ = pCell[0]; *(PATTR_3_BYTES)Ptr = LeadAttr; Ptr += 3; // // Put trailing byte cell // *Ptr++ = pCell[4]; *(PATTR_3_BYTES)Ptr = TrailAttr; Ptr += 3; } } else { Pattern = (ULONG)((pCell[3] << 24) | (pCell[2] << 16) | (pCell[1] << 8) | (pCell[0])); RtlFillMemoryUlong( Ptr, LengthInCell << SesGrp->VioLength2CellShift, Pattern); } } else { if (Ow2NlsIsDBCSLeadByte(pCell[0], SesGrp->VioCP)) { Pattern = (ULONG)((pCell[3] << 24) | (pCell[2] << 16) | (pCell[1] << 8) | (pCell[0])); } else { Pattern = (ULONG)((pCell[1] << 24) | (pCell[0] << 16) | (pCell[1] << 8) | (pCell[0])); if (LengthInCell & 1) { *(Ptr++) = pCell[0]; *(Ptr++) = pCell[1]; LengthInCell-- ; } } RtlFillMemoryUlong( Ptr, LengthInCell << SesGrp->VioLength2CellShift, Pattern); } #else // for (;Length-- ; ) // { // *(Ptr++) = pCell[0]; // *(Ptr++) = pCell[1]; // } if ( SesGrp->BytesPerCell == 4 ) { Pattern = (ULONG)((pCell[3] << 24) | (pCell[2] << 16) | (pCell[1] << 8) | (pCell[0])); } else { Pattern = (ULONG)((pCell[1] << 24) | (pCell[0] << 16) | (pCell[1] << 8) | (pCell[0])); if ((ULONG)Ptr & 3) { LengthInCell--; *(Ptr++) = pCell[0]; *(Ptr++) = pCell[1]; } if (LengthInCell & 1) { LengthInCell-- ; *(Ptr + (LengthInCell << 1)) = pCell[0]; *(Ptr + (LengthInCell << 1) + 1) = pCell[1]; } } RtlFillMemoryUlong( Ptr, LengthInCell << SesGrp->VioLength2CellShift, Pattern); #endif } } VOID VioLVBScrollBuff(IN DWORD LineNum) { DWORD Size; ULONG Pattern; if (SesGrp->LVBOn && LineNum) { if ( LineNum > (DWORD)SesGrp->ScreenRowNum ) { LineNum = SesGrp->ScreenRowNum; } #ifdef DBCS // MSKK Oct.20.1993 V-AkihiS Size = SesGrp->BytesPerCell * SesGrp->ScreenColNum * LineNum; if (SesGrp->BytesPerCell == 2) { Pattern = (ULONG)((SesGrp->AnsiCellAttr[0] << 24) | (' ' << 16) | (SesGrp->AnsiCellAttr[0] << 8) | (' ')); } else { Pattern = (ULONG)((SesGrp->AnsiCellAttr[2] << 24) | (SesGrp->AnsiCellAttr[1] << 16) | (SesGrp->AnsiCellAttr[0] << 8) | (' ')); } #else Size = 2 * SesGrp->ScreenColNum * LineNum; Pattern = (ULONG)((SesGrp->AnsiCellAttr[0] << 24) | (' ' << 16) | (SesGrp->AnsiCellAttr[0] << 8) | (' ')); #endif RtlMoveMemory(LVBBuffer, LVBBuffer + Size, SesGrp->LVBsize - Size); #ifdef DBCS // MSKK Oct.20.1993 V-AkihiS if (SesGrp->BytesPerCell == 4) { Size = SesGrp->ScreenColNum * LineNum; } #endif RtlFillMemoryUlong(LVBBuffer + SesGrp->LVBsize - Size, Size, Pattern); } } PUCHAR Ow2LvbGetPtr( IN COORD Coord ) { return(GET_LVB_PTR( Coord.Y, Coord.X)); } VOID LVBUpdateTTYCharWithAttrAndCurPos( IN CHAR c, IN PCHAR * LVBPtr ) { PCHAR Ptr = *LVBPtr; USHORT i; if(SesGrp->LVBOn) { *Ptr++ = c; for ( i = 1 ; i < SesGrp->BytesPerCell ; i++ ) { *Ptr++ = SesGrp->AnsiCellAttr[i - 1]; } *LVBPtr = Ptr; } } #ifdef DBCS // MSKK Oct.13.1993 V-AkihiS /* states of the finite state machine */ #define NOCMD 1 /* type of crt state - most chars will go onto screen */ #define ESCED 2 /* we've seen an ESC, waiting for rest of CSI */ #define EQCMD 3 /* if '=' goto MODPARAMS else PARAMS */ #define PARAMS 4 /* we're building the parameter list for ansicmd */ #define MODPARAMS 5 /* we're building the parameter list for MODCMD */ #define MODCMD 6 /* we've seen "ESC[=Num" waiting for #h or #l (# in {0..7}) */ #define MODDBCS 7 /* we've seen DBCS lead-in char */ VOID LVBUpdateTTYCharWithAttrAndCurPosDBCS( IN CHAR c, IN PCHAR * LVBPtr, IN USHORT State ) { PUCHAR Ptr = *LVBPtr; if(SesGrp->LVBOn) { *Ptr++ = c; if (SesGrp->BytesPerCell == 2) { *Ptr++ = SesGrp->AnsiCellAttr[0]; } else { *Ptr++ = SesGrp->AnsiCellAttr[0]; *Ptr++ = SesGrp->AnsiCellAttr[1]; if (State == MODDBCS) { *Ptr++ = OS2_COMMON_LVB_TRAILING_BYTE; } else { *Ptr++ = OS2_COMMON_LVB_LEADING_BYTE; } } *LVBPtr = Ptr; } } #endif