// // Wait for keyboard input, when key is pressed // return the key. // int WaitForKey( void ) { int c; while( ( c = getchar()) == EOF) idle(); // idle for powersaving keybeep(); // make the beeping sound return c; }
uint GetString( uint FieldRow, uint FieldCol, uint length, uint displen, uint *cursor, uchar *pInbuf, uint InFlags, POPUPSHELL *pShell) { /***************************************************************************/ /* Diagram to explain local variables. */ /* */ /* 0 ... 10 ... 40 ... 200 */ /* */ /* +-------------------------------+ */ /* +----------| |---------------------+ */ /* | | Portion of the string shown | | */ /* | | in the screen. | | */ /* +----------| |---------------------+ */ /* +-------------------------------+ */ /* |<---- Display Length --------->| */ /* */ /* |<------------ length (length of the entire buffer) ------------>| */ /* */ /* In the above example: */ /* */ /* length ===> 200 */ /* DisplayLength ===> 30 */ /* DisplayOffset ===> 10 */ /* */ /***************************************************************************/ uint key; int n, i; ushort rc; int voff; uint IsInsertMode = 0, scratch, BufLen; uint DisplayOffset; uint CursorRow, CursorCol; int FirstKeyEntry = TRUE; /*910*/ uint flags = InFlags; /*910*/ int state = MOU_STATE_UP; /* assume this! */ /*910*/ int NextState = 0; /*910*/ BUTTON *pButtonDown = NULL; /*910*/ /***************************************************************************/ /* */ /* flags - Flags which indicate type of the field. */ /* (AUTOEXIT / HEXONLY / BINONLY) */ /***************************************************************************/ if(pShell) flags = pShell->Flags; /*910*/ /***************************************************************************/ /* - Set keyboard flush buffer flag to indiacte not to flush the keyboard */ /* buffer while we are in getstring. */ /* - Initialise the local variables. */ /***************************************************************************/ SetFlushBufferFlag( NOFLUSHNOW ); /*820*/ FieldDisplayLength = displen; DisplayOffset = 0; CursorRow = FieldRow; CursorCol = ( *cursor > displen ) ? FieldCol : FieldCol + *cursor; #ifdef MSH if(iview) { CursorRow+=RowStart; FieldRow+=RowStart; CursorCol+=ColStart; FieldCol+=ColStart; } #endif /***************************************************************************/ /* Allocate memory for the local buffer. */ /***************************************************************************/ Buffer = (uchar *)Talloc( (length+1) * sizeof( uchar ) ); memset( Buffer, '\0', length+1 ); if(!iview) { /***************************************************************************/ /* Adjust display length if the length specified by the caller goes out of */ /* the screen. */ /***************************************************************************/ if( FieldCol + FieldDisplayLength > VideoCols ) FieldDisplayLength = VideoCols - FieldCol; /***************************************************************************/ /* Check to see if the field would over lap some other window, if so adjust*/ /* the display length accordingly. */ /***************************************************************************/ if( FieldDisplayLength + FieldCol > BoundPtr[FieldRow] ) FieldDisplayLength = BoundPtr[FieldRow] - FieldCol; } else { #ifdef MSH if( FieldDisplayLength + FieldCol - ColStart> VideoWidth ) FieldDisplayLength = VideoWidth - FieldCol + ColStart; #endif }/* End if*/ /***************************************************************************/ /* RightScrollOffset is the amount of scrolling to be done when the user */ /* goes out of the display length. It is 2/3 rds of the display length. */ /***************************************************************************/ RightScrollOffset = (FieldDisplayLength * 2)/3; LeftScrollOffset = FieldDisplayLength - RightScrollOffset; FieldBase = (uchar *)Sel2Flat( HiFlat(VideoPtr) ) + ( voff = 2*(FieldRow*VideoCols + FieldCol) ); FieldType = flags; /***************************************************************************/ /* Depending on the type of the string copy the initial string to the local*/ /* buffer. Display the string. */ /***************************************************************************/ if( (FieldType & HEXONLY) || (FieldType & BINONLY) ) { for( i = 0; i < length; i++ ) Buffer[i] = FieldBase[i*2]; } else strcpy( Buffer, pInbuf ); DisplayField( DisplayOffset ); VioShowBuf( (ushort)voff,(ushort) (2*FieldDisplayLength), 0 ); VioSetCurType( &NormalCursor, 0 ); for(;;) { VioSetCurPos( (ushort)CursorRow, (ushort)CursorCol, 0 ); Event = GetEvent( SEM_INDEFINITE_WAIT ); switch( Event->Type ) { case TYPE_MOUSE_EVENT: /*910*/ { /*910*/ /******************************************************************910*/ /* Test for mouse event between the string brackets. 910*/ /******************************************************************910*/ if( ( Event->Row == (ushort)FieldRow ) && /*910*/ ( Event->Col >= (ushort)FieldCol ) && /*910*/ ( Event->Col <= ((ushort)FieldCol+(ushort)FieldDisplayLength-1)) ) /*910*/ { /*910*/ /*****************************************************************910*/ /* - If it's a button down event then set the cursor at the 910*/ /* end of the string or on the character that was clicked on. 910*/ /*****************************************************************910*/ if( Event->Value == EVENT_BUTTON_1_DOWN) /*910*/ { /*910*/ BufLen = strlen( Buffer ); /*910*/ if( (DisplayOffset + (Event->Col - FieldCol)) > BufLen ) /*910*/ { /*910*/ keybeep(); /*910*/ CursorCol = FieldCol + (BufLen - DisplayOffset); /*910*/ } /*910*/ else /*910*/ CursorCol = (uint)Event->Col; /*910*/ } /*910*/ /*****************************************************************910*/ /* - Ignore events between the brackets that are not button 910*/ /* down events. 910*/ /* - Any mouse event between []s turns off the erasure of a 910*/ /* cursor sensitive prompt. 910*/ /*****************************************************************910*/ FieldType &= ~CLEAR1ST; /*910*/ continue; /*910*/ } /*910*/ /*910*/ /**********************************************************************/ /* - handle strings that are not in the context of a popup. */ /**********************************************************************/ if(pShell == NULL ) /*910*/ { /*910*/ NextState = GetMouseState( Event ); /*910*/ if( (state == MOU_STATE_UP) && /*910*/ (NextState == MOU_STATE_DOWN) /*910*/ ) /*910*/ { /*910*/ key = LEFTMOUSECLICK; /*910*/ break; /*910*/ } /*910*/ /*910*/ state = NextState; /*910*/ continue; /*910*/ } /*910*/ /******************************************************************910*/ /* - Now, handle mouse events outside the []s within the context 910*/ /* of a popup. 910*/ /* 910*/ /* - Button events are valid on the release event. 910*/ /* 910*/ /* - Transitions from up to down "outside" the <>s and []s 910*/ /* are returned to the caller as a LEFTMOUSECLICK. 910*/ /* 910*/ /* ------------------------ 910*/ /* | | 910*/ /* | ----------- 910*/ /* | <------------| |<---------------- 910*/ /* | | ----------- | 910*/ /* | ---- ---- 910*/ /* | | |--- ---| |--- 910*/ /* | | UP | | BU,BUM BD,BDM | | DN | | 910*/ /* | | |<-- -->| |<-- 910*/ /* | ---- ---- 910*/ /* | | | 910*/ /* | | | 910*/ /* | | ----------- | 910*/ /* | ------------>| |----------------> 910*/ /* | ----------- 910*/ /* | | 910*/ /* | | 910*/ /* | BU - Button up event. | 910*/ /* | BUM - Button up move event. -(1) If BD or BDM event 910*/ /* | BD - Button down event. occurs in a button(<>s), 910*/ /* | BDM - Button down move event. then set pButtonDown 910*/ /* | to point to the BUTTON 910*/ /* | structure. This is 910*/ /* | effectively a "pending" 910*/ /* ----(1) If BU or BUM event button event. If the 910*/ /* && if the event occurs up event occurs within 910*/ /* in the same button as the same <>s, then we've 910*/ /* a "pending" button got ourselves a valid 910*/ /* then we have a button button event. 910*/ /* event. 910*/ /* (2) If BD or BDM do not 910*/ /* occur within a button, 910*/ /* then set pButtonDown=NULL 910*/ /* and go back to the 910*/ /* caller with a 910*/ /* LEFTMOUSECLICK. 910*/ /* 910*/ /******************************************************************910*/ NextState = GetMouseState( Event ); /*910*/ if( (state == MOU_STATE_DOWN) && /*910*/ (NextState == MOU_STATE_UP) && /*910*/ (pButtonDown != NULL) && /*910*/ (pButtonDown == GetButtonPtr(pShell,Event)) /*910*/ ) /*910*/ { /*910*/ key = pButtonDown->Key; /*910*/ break; /*910*/ } /*910*/ /*910*/ if( (state == MOU_STATE_UP) && /*910*/ (NextState == MOU_STATE_DOWN) /*910*/ ) /*910*/ { /*910*/ pButtonDown = GetButtonPtr( pShell,Event); /*910*/ if( pButtonDown == NULL ) /*910*/ { /*910*/ key = LEFTMOUSECLICK; /*910*/ break; /*910*/ } /*910*/ } /*910*/ /*910*/ state = NextState; /*910*/ continue; /*910*/ } case TYPE_KBD_EVENT: { key = Event->Value; break; } } if( (FieldType & CLEAR1ST) && (FirstKeyEntry == TRUE) ) /*910*/ FirstKeyEntry = FALSE; /*910*/ switch( key ) { case F1: case ESC: case ENTER: case UP: case DOWN: case A_ENTER: case MOUSECLICK: /***********************************************************************/ /* - these keys are specific to the watchpoint dialog. 910*/ /***********************************************************************/ case TYNEXT: /* watchpoint type button. 910*/ case SPNEXT: /* watchpoint scope button. 910*/ case SZNEXT: /* watchpoint size button. 910*/ case STNEXT: /* watchpoint status button. 910*/ { /*********************************************************************/ /* All the above keys cannot be proccessed by getstring, so return */ /* the key to the caller. */ /*********************************************************************/ rc = RCBREAK; break; } case C_HOME: { /*********************************************************************/ /* Control-Home takes you to the start of the string. */ /*********************************************************************/ DisplayOffset = 0; CursorCol = FieldCol; rc = RCREDRAW; break; } case C_END: { /*********************************************************************/ /* Control-End takes you to the end of the string (to the last char */ /* the user has types in). */ /*********************************************************************/ BufLen = strlen( Buffer ); if( BufLen > FieldDisplayLength ) { DisplayOffset = BufLen - FieldDisplayLength; CursorCol = FieldCol + FieldDisplayLength - 1; } else { DisplayOffset = 0; CursorCol = FieldCol + BufLen; } rc = RCREDRAW; break; } case TAB: case S_TAB: { /*********************************************************************/ /* If the user has keyed in a tab and the field type is AUTOEXIT, */ /* return to the caller. */ /*********************************************************************/ if( FieldType & AUTOEXIT ) rc = RCBREAK; else { keybeep(); rc = 0; } break; } case LEFT: { /*********************************************************************/ /* The user has pressed the left arrow key. */ /* - If the cursor is not in the starting column move the cursor */ /* one column to the left. */ /*********************************************************************/ if( CursorCol > FieldCol ) { CursorCol--; rc = 0; } else { /*******************************************************************/ /* If the cursor is in the starting column, a non zero value in the*/ /* display offset would indicate we have some characters to the */ /* left to be displayed (see diagram above). If you have enough */ /* characters to scroll to LeftScrollOffset amount, do so. If not */ /* scroll to the start of the string. */ /*******************************************************************/ if( DisplayOffset ) { if( (int)(DisplayOffset - LeftScrollOffset) >= 0 ) { DisplayOffset -= LeftScrollOffset; CursorCol += (LeftScrollOffset - 1); } else { CursorCol += DisplayOffset; DisplayOffset = 0; } rc = RCREDRAW; } else { if( FieldType & AUTOEXIT ) rc = RCBREAK; else { keybeep(); rc = 0; } } } break; } case RIGHT: { /*********************************************************************/ /* The user has pressed the right arrow key. */ /* - If the cursor is not in the ending column of display and not */ /* end of the string, move the cursor one column to the right. */ /*********************************************************************/ BufLen = strlen( Buffer ); if( CursorCol < ( FieldCol + FieldDisplayLength - 1 ) ) { if( (DisplayOffset + (CursorCol - FieldCol)) < BufLen ) { CursorCol++; rc = 0; } else { keybeep(); rc = 0; } } else { /*******************************************************************/ /* If the cursor is at the ending column of display, check to see */ /* if we are within the buffer length. If we have enough space to */ /* scroll by RightScrollOffset amount do so, if not scroll till the*/ /* end of the string. */ /*******************************************************************/ if( DisplayOffset + FieldDisplayLength < BufLen ) { DisplayOffset += (FieldDisplayLength - RightScrollOffset); if( (DisplayOffset + (CursorCol - FieldCol)) > BufLen ) CursorCol = FieldCol + (BufLen - DisplayOffset); else CursorCol = FieldCol + RightScrollOffset; rc = RCREDRAW; } else { /*****************************************************************/ /* If we reached the ending column and the end of the buffer, if */ /* the field type is AUTOEXIT return to the caller. */ /*****************************************************************/ if( FieldType & AUTOEXIT ) rc = RCBREAK; else { keybeep(); rc = 0; } } } break; } case HOME: { /*********************************************************************/ /* Home takes to the starting column of the string. */ /*********************************************************************/ CursorCol = FieldCol; break; } case END: { /*********************************************************************/ /* End takes you to the ending column of the string. If the string */ /* is not long enough till the ending column of the display, End */ /* takes you to the end of the string. */ /*********************************************************************/ CursorCol = FieldCol + FieldDisplayLength - 1; scratch = DisplayOffset + ( CursorCol - FieldCol ); BufLen = strlen( Buffer ); if( scratch > BufLen ) CursorCol = FieldCol + (BufLen - DisplayOffset); break; } case INS: { /*********************************************************************/ /* Insert key is pressed. This toggles the InsertMode flag. If the */ /* current length of the string is less than the buffer length, */ /* InsertMode could be allowed. Set the cusror type accordingly. */ /*********************************************************************/ if( IsInsertMode ) { IsInsertMode = 0; VioSetCurType( &NormalCursor, 0 ); } else { if( length != strlen( Buffer ) ) { IsInsertMode = 1 - IsInsertMode; IsInsertMode ? VioSetCurType( &InsertCursor, 0 ) : VioSetCurType( &NormalCursor, 0 ); } else /* Display proper error message... */ keybeep(); } break; } case DEL: { /*********************************************************************/ /* Delete the current character. The rest of the string is shifted */ /* left. */ /*********************************************************************/ scratch = DisplayOffset + ( CursorCol - FieldCol ); ( scratch < strlen( Buffer ) ) ? ShiftLeft( scratch ) : keybeep(); rc = RCREDRAW; break; } case BACKSPACE: { /*********************************************************************/ /* The previous character to the cursor is deleted. By default the */ /* string is shifted left by one character. But if the cursor is on */ /* the starting column then the string is shifted by LeftScrollOffset*/ /* amount. */ /*********************************************************************/ scratch = DisplayOffset + (CursorCol - FieldCol); if( scratch ) { ShiftLeft( scratch - 1 ); CursorCol--; if( CursorCol < FieldCol ) { if( (int)(DisplayOffset - LeftScrollOffset) >= 0 ) { DisplayOffset -= LeftScrollOffset; CursorCol += LeftScrollOffset; } else { CursorCol += (DisplayOffset + 1); DisplayOffset = 0; } } } else keybeep(); rc = RCREDRAW; break; } default: { /*********************************************************************/ /* Any other character key is pressed. Verify the validity of the */ /* character depending on the type of the string (HEX/BIN). */ /*********************************************************************/ key &= 0xFF; if( key != 0x15 ) if( (key < 0x20) || (key > 0x7E) ) { rc = RCBREAK; break; } if( FieldType & HEXONLY ) { if( (key < '0') || (key > '9') ) { key &= 0xDF; if( (key < 'A') || (key > 'F') ) { keybeep(); rc = 0; break; } } } if( FieldType & BINONLY ) { if( (key != '0') && (key != '1') ) { keybeep(); rc = 0; break; } } if( FieldType & CLEAR1ST ) /*910*/ { /*910*/ memset(Buffer,'\0',strlen(Buffer) ); /*910*/ *cursor = 0; /*910*/ CursorCol = (*cursor > displen)?FieldCol : FieldCol + *cursor; /*910*/ } /*910*/ /*********************************************************************/ /* Scratch gives you the exact number of characters so far typed in */ /* by the user. Accept the last character only if scratch is less */ /* than the total length of the string. */ /*********************************************************************/ scratch = DisplayOffset + ( CursorCol - FieldCol ); if( scratch < length ) { if( IsInsertMode ) { if( (strlen( Buffer ) + 1) > length ) { keybeep(); rc = 0; break; /* reject */ } else ShiftRight( scratch ); } Buffer[scratch] = ( uchar )key; /*******************************************************************/ /* Adjust the cursor position accordingly so that it stays ahead */ /* of the last character. */ /*******************************************************************/ if( CursorCol >= (FieldCol + FieldDisplayLength) ) { DisplayOffset += (FieldDisplayLength - RightScrollOffset - 1); CursorCol = FieldCol + RightScrollOffset + 2; } else CursorCol++; /*******************************************************************/ /* It the type of the field is AUTOEXIT return to the caller once */ /* the buffer is full. */ /*******************************************************************/ BufLen = strlen( Buffer ); if( (BufLen == length) && (FieldType & AUTOEXIT) && ((CursorCol - FieldCol) == FieldDisplayLength) ) rc = RCREDRAW + RCBREAK + RCDATAXT; else rc = RCREDRAW; break; } else { keybeep(); rc = 0; break; } } } /*************************************************************************/ /* - Turn off the clear field flag after any event. */ /*************************************************************************/ FieldType &= ~CLEAR1ST; /*910*/ if( rc & RCREDRAW ) { DisplayField( DisplayOffset ); VioShowBuf( (ushort)voff, (ushort)( 2 * FieldDisplayLength ), 0 ); } if( rc & RCBREAK ) break; } /* end of for loop to handle keystrks*/ VioSetCurType( &HiddenCursor, 0 ); /*************************************************************************/ /* - Copy the local buffer to the caller supplied buffer. */ /* - Free the local buffer. */ /* - Reset the keyboard buffer flush flag. */ /*************************************************************************/ for( n = 0; n < strlen( Buffer ); n++ ) *pInbuf++ = Buffer[n]; *pInbuf = 0; *cursor = CursorCol; Tfree( Buffer ); ResetFlushBufferFlag(); /*820*/ return( (rc & RCDATAXT) ? DATAKEY : key ); }