char *ckomouv = "OS/2 Mouse Support 5A(002), 5 Aug 94"; /* C K O M O U -- Kermit mouse support for OS/2 systems */ /* Author: Jeffrey Altman (p00118@psilink.com) Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New York. The C-Kermit software may not be, in whole or in part, licensed or sold for profit as a software product itself, nor may it be included in or distributed with commercial products or otherwise distributed by commercial concerns to their clients or customers without written permission of the Office of Kermit Development and Distribution, Columbia University. This copyright notice must not be removed, altered, or obscured. */ #include "ckcdeb.h" #ifdef OS2MOUSE #define INCL_NOPM #define INCL_VIO #define INCL_MOU #define INCL_ERRORS #define INCL_DOSPROCESS #define INCL_DOSSEMAPHORES #define INCL_DOSDEVIOCTL #define INCL_WINCLIPBOARD #include #undef COMMENT /* COMMENT is defined in os2.h */ HMOU hMouse = 0 ; NOPTRRECT SelectedArea = {65535,65535,65535,65535}; BOOL SelectionValid = 0 ; TID mouthread = 0 ; typedef struct ascreen_rec { /* Structure for saving screen info */ unsigned char ox; unsigned char oy; unsigned char att; char *scrncpy; } ascreen; ascreen mousescreen ; extern HMUX hmuxKeyStroke ; extern HMTX hmtxMouseSem = (HMTX) 0 ; extern int tnlm; extern int wherex; /* Screen column, 1-based */ extern int wherey; /* Screen row, 1-based */ extern int xsize; /* Screen width */ extern int ysize; /* Screen height */ #define THRDSTKSIZ 131072 /* Needed for Mouse Thread */ #define MAXCOL 132 /* Maximum screen columns */ #define MAXROW 255 /* Maximum screen rows */ /* Functions from ckocon.c */ void savescreen(ascreen *, int, int); int restorescreen(ascreen *); void reverserange( SHORT fromrow, SHORT fromcol, SHORT torow, SHORT tocol ); /* See ckocon.c for details on swapcolors macro */ #define swapcolors(x) (((x)&(unsigned)0x88)|(((x)&0x70)>>4)|(((x)&0x07)<<4)) /* Potential mouse events: MOUSE_MOTION MOUSE_MOTION_WITH_BN1_DOWN MOUSE_BN1_DOWN MOUSE_MOTION_WITH_BN2_DOWN MOUSE_BN2_DOWN MOUSE_MOTION_WITH_BN3_DOWN MOUSE_BN3_DOWN */ static BOOL ThreeButton = 0 ; /* 0 -two buttons, 1 - three buttons */ APIRET CopyVioToKbdBuffer( USHORT bRow, USHORT bCol, USHORT eRow, USHORT eCol ) { VIOMODEINFO VioModeInfo ; USHORT Length = 0 ; SHORT i, j ; BYTE Buffer[ MAXCOL * MAXROW ] ; USHORT tmpRow, tmpCol ; /* This code does not work for Hebrew and other BiDi languages */ memset( &VioModeInfo, 0, sizeof(VioModeInfo) ) ; VioModeInfo.cb = sizeof(VioModeInfo) ; VioGetMode( &VioModeInfo, NULL ) ; DosRequestMutexSem( hmuxKeyStroke, SEM_INDEFINITE_WAIT ) ; os2_mousehide() ; if ( bRow == eRow && bCol > eCol ) { tmpCol = bCol ; bCol = eCol ; eCol = tmpCol ; } else if ( bRow > eRow ) { tmpRow = bRow ; bRow = eRow ; eRow = tmpRow ; } if ( eRow - bRow == 0 ) { /* copy selected text to KbdBuf clipping spaces */ Length = eCol - bCol + 1 ; VioReadCharStr( Buffer, &Length, bRow, bCol, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } for ( i = 0 ; i < Length ; i++ ) { putkey( Buffer[i] ) ; } } else { /* partial first line */ Length = VioModeInfo.col - bCol ; VioReadCharStr( Buffer, &Length, bRow, bCol, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } for ( i = 0 ; i < Length ; i++ ) { putkey( Buffer[i] ) ; } putkey( '\r' ) ; if (tnlm) putkey( '\n' ) ; /* complete middle rows */ for ( j = bRow + 1 ; j < eRow ; j++ ) { Length = VioModeInfo.col ; VioReadCharStr( Buffer, &Length, j, 0, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } for ( i = 0 ; i < Length ; i++ ) { putkey( Buffer[i] ) ; } putkey( '\r' ) ; if (tnlm) putkey( '\n' ) ; } /* partial last line */ Length = eCol ; VioReadCharStr( Buffer, &Length, eRow, 0, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } for ( i = 0 ; i < Length ; i++ ) { putkey( Buffer[i] ) ; } } os2_mouseshow() ; DosReleaseMutexSem( hmuxKeyStroke ) ; } APIRET CopyClipboardToKbdBuffer( void ) { int i = 0 ; APIRET rc = -1 ; BYTE * hClipbrdData ; BYTE * pData = 0 ; BYTE * pClipboard ; if ( WinOpenClipbrd(0) ) { hClipbrdData = (BYTE *) WinQueryClipbrdData( 0, CF_TEXT ) ; if ( !DosGetSharedMem( hClipbrdData, PAG_READ ) ) { pData = strdup( hClipbrdData ) ; /* We must copy the text back to the Clipboard because the */ /* GetSharedMemory call screwed up the clipboard. We're not */ /* supposed to do things like that. */ if ( !DosAllocSharedMem( (PPVOID) &pClipboard, 0, strlen(pData)+1, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | OBJ_GETTABLE | OBJ_TILE ) ) { strcpy( pClipboard, pData ) ; WinSetClipbrdData( 0, (ULONG) pClipboard, CF_TEXT, CFI_POINTER ) ; } } WinCloseClipbrd( 0 ) ; if ( pData ) { DosRequestMutexSem( hmuxKeyStroke, SEM_INDEFINITE_WAIT ) ; while ( pData[i] != '\0' ) { if ( pData[i] != '\012' || ( pData[i] == '\012' && tnlm ) ) putkey( pData[i] ) ; i++ ; } DosReleaseMutexSem( hmuxKeyStroke ) ; rc = 0 ; } } return rc ; } APIRET CopyVioToClipboard( USHORT bRow, USHORT bCol, USHORT eRow, USHORT eCol ) { VIOMODEINFO VioModeInfo ; USHORT Length = 0, ClipBoardSz ; SHORT i, j ; BYTE Buffer[ MAXCOL * MAXROW ] ; USHORT tmpRow, tmpCol ; BYTE * pClipboard = 0 ; APIRET rc = 0 ; /* This code does not work for Hebrew and other BiDi languages */ memset( &VioModeInfo, 0, sizeof(VioModeInfo) ) ; VioModeInfo.cb = sizeof(VioModeInfo) ; VioGetMode( &VioModeInfo, NULL ) ; if ( bRow == eRow && bCol > eCol ) { tmpCol = bCol ; bCol = eCol ; eCol = tmpCol ; } else if ( bRow > eRow ) { tmpRow = bRow ; bRow = eRow ; eRow = tmpRow ; } /* Determine size of and allocate Clipboard */ if ( eRow - bRow == 0 ) { ClipBoardSz = eCol - bCol + 4 ; } else { ClipBoardSz = VioModeInfo.col - bCol + 2 ; for ( j = bRow + 1 ; j < eRow ; j++ ) ClipBoardSz += VioModeInfo.col + 2 ; ClipBoardSz += eCol + 4 ; } if ( rc = DosAllocSharedMem( (PPVOID) &pClipboard, 0, ClipBoardSz, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | OBJ_GETTABLE | OBJ_TILE ) ) { return -1 ; } pClipboard[0] = '\0' ; os2_mousehide() ; if ( eRow - bRow == 0 ) { /* copy selected text to KbdBuf clipping spaces */ Length = eCol - bCol + 1 ; VioReadCharStr( Buffer, &Length, bRow, bCol, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } strncat( pClipboard, Buffer, Length ) ; } else { /* partial first line */ Length = VioModeInfo.col - bCol ; VioReadCharStr( Buffer, &Length, bRow, bCol, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } strncat( pClipboard, Buffer, Length ) ; strncat( pClipboard, "\r\n", 2 ) ; /* complete middle rows */ for ( j = bRow + 1 ; j < eRow ; j++ ) { Length = VioModeInfo.col ; VioReadCharStr( Buffer, &Length, j, 0, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } strncat( pClipboard, Buffer, Length ) ; strncat( pClipboard, "\r\n", 2 ) ; } /* partial last line */ Length = eCol ; VioReadCharStr( Buffer, &Length, eRow, 0, NULL ) ; for ( i = Length - 1 ; i >= 0 ; i-- ) { if ( Buffer[i] == ' ' ) { Buffer[i] = '\0' ; Length-- ; } else break; } strncat( pClipboard, Buffer, Length ) ; } if ( WinOpenClipbrd( 0 ) ) { if ( !WinSetClipbrdData( 0, (ULONG) pClipboard, CF_TEXT, CFI_POINTER ) ) DosFreeMem( pClipboard ) ; WinCloseClipbrd( 0 ) ; } else { DosFreeMem( pClipboard ) ; } os2_mouseshow() ; return 0 ; } APIRET os2_mouseshow( void ) { APIRET rc = 0 ; NOPTRRECT PtrArea ; VIOMODEINFO ModeData ; if ( hMouse ) { ModeData.cb = sizeof(ModeData) ; VioGetMode( &ModeData, 0 ) ; PtrArea.row = ModeData.row - 1 ; PtrArea.col = 0 ; PtrArea.cRow = ModeData.row - 1; PtrArea.cCol = ModeData.col - 1 ; MouRemovePtr( &PtrArea, hMouse ) ; } return rc ; } APIRET os2_mousehide( void ) { APIRET rc = 0 ; NOPTRRECT PtrArea ; VIOMODEINFO ModeData ; if (hMouse) { ModeData.cb = sizeof(ModeData) ; VioGetMode( &ModeData, 0 ) ; PtrArea.row = 0 ; PtrArea.col = 0 ; PtrArea.cRow = ModeData.row - 1; PtrArea.cCol = ModeData.col - 1 ; MouRemovePtr( &PtrArea, hMouse ) ; } return rc ; } APIRET os2_mouseon( void ) { APIRET rc = 0 ; PTRLOC PtrPos ; NOPTRRECT PtrArea ; VIOMODEINFO ModeData ; USHORT ButtonCount ; USHORT EventMask ; if (!mouthread) { rc = MouOpen( 0, &hMouse ) ; debug(F101,"Mouse On","",rc) ; } if ( !rc ) { DosCreateMutexSem( 0, &hmtxMouseSem, 0, 0 ) ; rc = MouDrawPtr( hMouse ) ; ModeData.cb = sizeof(ModeData) ; VioGetMode( &ModeData, 0 ) ; PtrPos.row = ModeData.row - 1 ; PtrPos.col = 0 ; MouSetPtrPos( &PtrPos, hMouse ) ; PtrArea.row = ModeData.row - 1 ; PtrArea.col = 0 ; PtrArea.cRow = ModeData.row - 1; PtrArea.cCol = ModeData.col - 1 ; MouRemovePtr( &PtrArea, hMouse ) ; MouGetNumButtons( &ButtonCount, hMouse ) ; debug(F101,"os2_mouseon Button Count","",ButtonCount ) ; if ( ButtonCount == 3 ) { ThreeButton = 1 ; EventMask = MOUSE_MOTION | MOUSE_BN1_DOWN | MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN3_DOWN | MOUSE_MOTION_WITH_BN3_DOWN ; } else /* 2 buttons */ { ThreeButton = 0 ; EventMask = MOUSE_MOTION | MOUSE_BN1_DOWN | MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_MOTION_WITH_BN2_DOWN ; } MouSetEventMask( &EventMask, hMouse ) ; if (!mouthread) { mouthread = _beginthread( &os2_mouseevt, 0, THRDSTKSIZ, 0 ) ; } } return rc ; } static int selectiontype(void) { int rc ; if ( !SelectionValid || SelectedArea.row == SelectedArea.cRow && SelectedArea.col == SelectedArea.cCol ) rc = 0 ; else if ( SelectedArea.cRow > SelectedArea.row || SelectedArea.cRow == SelectedArea.row && SelectedArea.cCol > SelectedArea.col ) rc = 1 ; else rc = -1 ; debug(F101,"SelectionType","",rc) ; return rc ; } static int isselected( USHORT row, USHORT col ) { int rc ; if ( !SelectionValid ) rc = 0 ; else switch( selectiontype() ) { case 0: rc = ( SelectedArea.row == row && SelectedArea.col == col ) ? 1 : 0 ; break; case 1: if ( SelectedArea.row == SelectedArea.cRow && SelectedArea.row == row && col >= SelectedArea.col && col <= SelectedArea.cCol ) rc = 1 ; else if ( SelectedArea.row == row && SelectedArea.col <= col && SelectedArea.cCol >= col ) rc = 1 ; else if ( SelectedArea.row < row && SelectedArea.cRow > row ) rc = 1 ; else if ( SelectedArea.cRow == row && SelectedArea.cCol >= col ) rc = 1 ; else rc = 0 ; break; case -1: if ( SelectedArea.row == SelectedArea.cRow && SelectedArea.row == row && col <= SelectedArea.col && col >= SelectedArea.cCol ) rc = 1 ; else if ( SelectedArea.row == row && SelectedArea.col >= col && SelectedArea.cCol <= col ) rc = 1 ; else if ( SelectedArea.row > row && SelectedArea.cRow < row ) rc = 1 ; else if ( SelectedArea.cRow == row && SelectedArea.cCol <= col ) rc = 1 ; else rc = 0 ; break; default: rc = 0 ; } debug(F101,"isselected","",rc) ; return rc ; } void os2_mouseevt(void *pArgList) { APIRET rc ; MOUEVENTINFO MouseEventInfo ; USHORT ReadType = MOU_NOWAIT ; USHORT Vrow, Vcol, n ; BYTE cell[MAXCOL * 2] ; static int b1=0, b1time=0, b2=0, b2time=0, b3=0, b3time=0 ; static USHORT lastrow=0, lastcol=0, b1row = 0, b1col = 0, b2row = 0, b2col = 0 ; const DBCLICK = 1000 ; DosSetPriority( PRTYS_THREAD, PRTYC_NOCHANGE, PRTYD_MINIMUM, 0 ) ; while (hMouse) { memset( &MouseEventInfo, 0, sizeof( MOUEVENTINFO ) ) ; rc = MouReadEventQue( &MouseEventInfo, &ReadType, hMouse ) ; if ( rc == NO_ERROR && MouseEventInfo.time ) { char buffer[1024] ; sprintf(buffer, " Event: fs:%3x time:%10d row:%3d col:%3d", MouseEventInfo.fs, MouseEventInfo.time, MouseEventInfo.row, MouseEventInfo.col) ; debug(F110,"os2_mouseevt",buffer,0) ; VioGetCurPos( &Vrow, &Vcol, NULL ) ; if ( MouseEventInfo.row == ysize ) MouseEventInfo.row-- ; if ( MouseEventInfo.fs & MOUSE_BN1_DOWN ) { if ( b1 == 1 && MouseEventInfo.time - b1time < DBCLICK && MouseEventInfo.row == b1row && MouseEventInfo.col == b1col ) { /* Double Click */ b1 = 2 ; DosRequestMutexSem(hmuxKeyStroke,SEM_INDEFINITE_WAIT); for (; Vcol > MouseEventInfo.col; Vcol-- ) { putkey( 587 ) ; /* LEFT */ } for (; Vrow > MouseEventInfo.row; Vrow-- ) { putkey( 584 ) ; /* UP */ } for (; Vrow < MouseEventInfo.row; Vrow++ ) { putkey( 592 ) ; /* DOWN */ } for (; Vcol < MouseEventInfo.col; Vcol++ ) { putkey( 589 ) ; /* RIGHT */ } DosReleaseMutexSem( hmuxKeyStroke ) ; SelectionValid = 0 ; } else if ( b1 == 0 ) { /* Single Click */ b1 = 1 ; b1time = MouseEventInfo.time ; b1row = MouseEventInfo.row ; b1col = MouseEventInfo.col ; DosRequestMutexSem( hmtxMouseSem, SEM_INDEFINITE_WAIT ) ; savescreen(&mousescreen,wherex,wherey); SelectionValid = 1 ; SelectedArea.row = SelectedArea.cRow = MouseEventInfo.row ; SelectedArea.col = SelectedArea.cCol = MouseEventInfo.col ; n = 2 ; os2_mousehide() ; VioReadCellStr( cell, &n, MouseEventInfo.row, MouseEventInfo.col, 0 ); cell[1] = swapcolors(cell[1]) ; VioWrtCellStr( cell, n, MouseEventInfo.row, MouseEventInfo.col, 0 ) ; os2_mouseshow() ; } } else if ( MouseEventInfo.fs & MOUSE_MOTION_WITH_BN1_DOWN ) { if ( b1 == 1 && SelectionValid && ( lastrow != MouseEventInfo.row || lastcol != MouseEventInfo.col ) ) { if ( isselected( MouseEventInfo.row, MouseEventInfo.col ) ) { if ( selectiontype() > 0 ) { reverserange( SelectedArea.cRow, SelectedArea.cCol, MouseEventInfo.row, MouseEventInfo.col+1 ); } else if ( selectiontype() < 0 ) { reverserange( SelectedArea.cRow, SelectedArea.cCol, MouseEventInfo.row, MouseEventInfo.col-1 ); } } else { if ( selectiontype() > 0 ) if ( MouseEventInfo.row >= SelectedArea.cRow ) reverserange( SelectedArea.cRow, SelectedArea.cCol+1, MouseEventInfo.row, MouseEventInfo.col ); else { reverserange( SelectedArea.cRow, SelectedArea.cCol, SelectedArea.row, SelectedArea.col+1); reverserange( SelectedArea.row, SelectedArea.col-1, MouseEventInfo.row, MouseEventInfo.col); } else if ( selectiontype() < 0 ) if ( MouseEventInfo.row <= SelectedArea.cRow ) reverserange( SelectedArea.cRow, SelectedArea.cCol-1, MouseEventInfo.row, MouseEventInfo.col ); else { reverserange( SelectedArea.cRow, SelectedArea.cCol, SelectedArea.row, SelectedArea.col-1); reverserange( SelectedArea.row, SelectedArea.col+1, MouseEventInfo.row, MouseEventInfo.col); } else if ( MouseEventInfo.row < SelectedArea.cRow || MouseEventInfo.row == SelectedArea.cRow && MouseEventInfo.col < SelectedArea.cCol ) reverserange( SelectedArea.cRow, SelectedArea.cCol-1, MouseEventInfo.row, MouseEventInfo.col ); else if ( MouseEventInfo.row > SelectedArea.cRow || MouseEventInfo.row == SelectedArea.cRow && MouseEventInfo.col > SelectedArea.cCol ) reverserange( SelectedArea.cRow, SelectedArea.cCol+1, MouseEventInfo.row, MouseEventInfo.col ); } SelectedArea.cRow = MouseEventInfo.row ; SelectedArea.cCol = MouseEventInfo.col ; } } else { /* Button One Up */ if ( b1 == 1 ) { if ( MouseEventInfo.time - b1time > DBCLICK ) { b1 = 0 ; b1time = 0 ; b1row = 0 ; b1col = 0 ; } if ( SelectionValid ) { CopyVioToClipboard( SelectedArea.row, SelectedArea.col, SelectedArea.cRow, SelectedArea.cCol ) ; SelectionValid = 0 ; restorescreen(&mousescreen); DosReleaseMutexSem( hmtxMouseSem ) ; } } else if ( b1 == 2 ) { b1 = 0 ; b1time = 0 ; b1row = 0 ; b1col = 0 ; DosReleaseMutexSem( hmtxMouseSem ) ; } } if ( !ThreeButton && ( MouseEventInfo.fs & MOUSE_BN2_DOWN ) || ThreeButton && ( MouseEventInfo.fs & MOUSE_BN3_DOWN ) ) { if ( b2 == 1 && MouseEventInfo.time - b2time < DBCLICK && MouseEventInfo.col == b2col && MouseEventInfo.row == b2row ) { /* Double Click */ b2 = 2 ; if ( b1 == 0 ) { CopyClipboardToKbdBuffer() ; } } else if ( b2 == 0 ) { b2 = 1 ; b2time = MouseEventInfo.time ; b2row = MouseEventInfo.row ; b2col = MouseEventInfo.col ; if ( b1 == 1 ) { if ( SelectionValid ) { CopyVioToKbdBuffer(SelectedArea.row, SelectedArea.col, SelectedArea.cRow, SelectedArea.cCol ); SelectionValid = 0 ; restorescreen(&mousescreen) ; DosReleaseMutexSem( hmtxMouseSem ) ; } } } } else if ( !ThreeButton && ( MouseEventInfo.fs & MOUSE_MOTION_WITH_BN2_DOWN ) || ThreeButton && ( MouseEventInfo.fs & MOUSE_MOTION_WITH_BN3_DOWN ) ) { /* Do Nothing */ } else /* Button Two Up */ { if ( b2 == 1 ) { if ( MouseEventInfo.time - b2time > DBCLICK ) { b2time = b2 = 0 ; } } if ( b2 == 2 ) { b2 = 0 ; b2time = 0 ; } } lastcol = MouseEventInfo.col ; lastrow = MouseEventInfo.row ; } else /* No Mouse Event so release time slice */ { #ifdef COMMENT char buffer[1024] ; sprintf(buffer, "NoEvent: fs:%3x time:%10d row:%3d col:%3d", MouseEventInfo.fs, MouseEventInfo.time, MouseEventInfo.row, MouseEventInfo.col) ; debug(F110,"os2_mouseevt",buffer,0) ; #endif /* COMMENT */ DosSleep(1) ; } } _endthread(); } APIRET os2_mouseoff( void ) { APIRET rc = 0 ; if ( hMouse ) { rc = MouClose( hMouse ) ; debug(F101,"Mouse Off","",rc) ; hMouse = 0 ; DosWaitThread( &mouthread, DCWW_WAIT ) ; debug(F100,"os2_mouevt() thread dead","",0) ; mouthread = 0 ; DosCloseMutexSem( hmtxMouseSem ) ; hmtxMouseSem = (HMTX) 0 ; } return rc ; } #endif /* OS2MOUSE */