Removed variables that had no effect on code behavior. Fifo.c::FIFO_Dequeue: Replaced instances of "Self->ElementSize" with preexisting variable "SizeOfElement". IIOutilities.c::IIO_GetInChar: Fixed variable of wrong, but compatible, type and made updating of housekeeping variables dependent upon successful completion of reading from the buffer. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> Reviewed by: Daryl McDaniel <daryl.mcdaniel@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16276 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			208 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Write to an Interactive I/O Output device.
 | |
| 
 | |
|   The functions assume that isatty() is TRUE at the time they are called.
 | |
|   Since the UEFI console is a WIDE character device, these functions do all
 | |
|   processing using wide characters.
 | |
| 
 | |
|   It is the responsibility of the caller, or higher level function, to perform
 | |
|   any necessary translation between wide and narrow characters.
 | |
| 
 | |
|   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials are licensed and made available
 | |
|   under the terms and conditions of the BSD License which accompanies this
 | |
|   distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php.
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| **/
 | |
| #include  <Uefi.h>
 | |
| 
 | |
| #include  <LibConfig.h>
 | |
| 
 | |
| #include  <assert.h>
 | |
| #include  <errno.h>
 | |
| #include  <sys/termios.h>
 | |
| #include  <Device/IIO.h>
 | |
| 
 | |
| static wchar_t  Spaces[] = L"                ";   // Spaces for expanding TABs
 | |
| 
 | |
| #define MAX_TAB_WIDTH     ((int)(sizeof(Spaces) / sizeof(wchar_t)) - 1)
 | |
| 
 | |
| #define MAX_EXPANSION     3
 | |
| 
 | |
| /** Process and buffer one character for output.
 | |
| 
 | |
|     @param[in]    filp      Pointer to a file descriptor structure.
 | |
|     @param[out]   OBuf      Pointer to the Output Buffer FIFO.
 | |
|     @param[in]    InCh      The wide character to process.
 | |
| 
 | |
|     @retval   <0    An error occurred.  Reason is in errno.
 | |
|                       * EINVAL  The pointer to the IIO object is NULL.
 | |
|                       * ENOSPC  The OBuf FIFO is full.
 | |
| 
 | |
|     @retval    0    A character was input but not placed in the output buffer.
 | |
| 
 | |
|     @retval   >0    The number of characters buffered.  Normally 1, or 2.
 | |
|                     If a character is discarded because of flag settings, a
 | |
|                     1 will be returned.
 | |
| **/
 | |
| ssize_t
 | |
| IIO_WriteOne(struct __filedes *filp, cFIFO *OBuf, wchar_t InCh)
 | |
| {
 | |
|   cIIO               *This;
 | |
|   struct termios     *Termio;
 | |
|   tcflag_t            OFlag;
 | |
|   ssize_t             RetVal;
 | |
|   wchar_t             wc[MAX_EXPANSION];        // Sub-buffer for conversions
 | |
|   wchar_t            *wcb;          // Pointer to either wc or spaces
 | |
|   int                 numW    = 0;  // Wide characters placed in OBuf
 | |
|   INT32               TabWidth;     // Each TAB expands into this number of spaces
 | |
|   UINT32              CurColumn;    // Current cursor column on the screen
 | |
|   UINT32              CurRow;       // Current cursor row on the screen
 | |
|   UINT32              PrevColumn;   // Previous column.  Used to detect wrapping.
 | |
|   UINT32              AdjColumn;    // Current cursor column on the screen
 | |
| 
 | |
|   RetVal    = -1;
 | |
|   wcb       = wc;
 | |
|   This      = filp->devdata;
 | |
|   if((This != NULL) && (OBuf->FreeSpace(OBuf, AsElements) >= MAX_EXPANSION)) {
 | |
|     Termio    = &This->Termio;
 | |
|     OFlag     = Termio->c_oflag;
 | |
|     TabWidth  = (INT32)This->Termio.c_cc[VTABLEN];
 | |
|     if(TabWidth > MAX_TAB_WIDTH) {
 | |
|       TabWidth = MAX_TAB_WIDTH;
 | |
|     }
 | |
|     CurColumn = This->CurrentXY.Column;
 | |
|     CurRow    = This->CurrentXY.Row;
 | |
| 
 | |
|     numW      = 1;          // The majority of characters buffer one character
 | |
|     AdjColumn = 0;
 | |
|     if(OFlag & OPOST) {
 | |
|       /* Perform output processing */
 | |
|       switch(InCh) {
 | |
|         case CHAR_TAB:                //{{
 | |
|           if(OFlag & OXTABS) {
 | |
|             if(TabWidth > 0) {
 | |
|               int   SpaceIndex;
 | |
| 
 | |
|               SpaceIndex = CurColumn % TabWidth;    // Number of spaces after a Tab Stop
 | |
|               numW = TabWidth - SpaceIndex;         // Number of spaces to the next Tab Stop
 | |
|               SpaceIndex = MAX_TAB_WIDTH - numW;    // Index into the Spaces array
 | |
|               wcb = &Spaces[SpaceIndex];            // Point to the appropriate number of spaces
 | |
|             }
 | |
|             else {
 | |
|               wc[0] = L' ';
 | |
|             }
 | |
|             AdjColumn = numW;
 | |
|           }
 | |
|           else {
 | |
|             wc[0] = InCh;     // Send the TAB itself - assumes that it does not move cursor.
 | |
|           }
 | |
|           break;                      //}}
 | |
| 
 | |
|         case CHAR_CARRIAGE_RETURN:    //{{
 | |
|           if((OFlag & OCRNL) == 0) {
 | |
|             if((OFlag & ONLRET) == 0) {
 | |
|               numW = 0;   /* Discard the CR */
 | |
|               // Cursor doesn't move
 | |
|             }
 | |
|             else {
 | |
|               wc[0]     = CHAR_CARRIAGE_RETURN;
 | |
|               CurColumn = 0;
 | |
|             }
 | |
|             break;
 | |
|           }
 | |
|           else {
 | |
|             InCh = CHAR_LINEFEED;
 | |
|           }                           //}}
 | |
|           // Fall through to the NL case
 | |
|         case CHAR_LINEFEED:           //{{
 | |
|           if(OFlag & ONLCR) {
 | |
|             wc[0] = CHAR_CARRIAGE_RETURN;
 | |
|             wc[1] = CHAR_LINEFEED;
 | |
|             numW  = 2;
 | |
|             CurColumn = 0;
 | |
|           }
 | |
|           break;                      //}}
 | |
| 
 | |
|         case CHAR_BACKSPACE:          //{{
 | |
|           if(CurColumn > 0) {
 | |
|             wc[0] = CHAR_BACKSPACE;
 | |
|             CurColumn = (UINT32)ModuloDecrement(CurColumn, (UINT32)This->MaxColumn);
 | |
|           }
 | |
|           else {
 | |
|             numW = 0;   // Discard the backspace if in column 0
 | |
|           }
 | |
|           break;                      //}}
 | |
| 
 | |
|         case CHAR_EOT:                //{{
 | |
|           if(OFlag & ONOEOT) {
 | |
|             numW = 0;             // Discard the EOT character
 | |
|             // Cursor doesn't move
 | |
|             break;
 | |
|           }                           //}}
 | |
|           // Fall through to default in order to potentially output "^D"
 | |
|         default:                      //{{
 | |
|           if((InCh >= 0) && (InCh < L' ')) {
 | |
|             // InCh contains a control character
 | |
|             if(OFlag & OCTRL) {
 | |
|               wc[1]     = InCh + L'@';
 | |
|               wc[0]     = L'^';
 | |
|               numW      = 2;
 | |
|               AdjColumn = 2;
 | |
|             }
 | |
|             else {
 | |
|               numW = 0;   // Discard.  Not a UEFI supported control character.
 | |
|             }
 | |
|           }
 | |
|           else {
 | |
|             // Regular printing character
 | |
|             wc[0]     = InCh;
 | |
|             AdjColumn = 1;
 | |
|           }
 | |
|           break;                      //}}
 | |
|       }
 | |
|       if(numW < MAX_EXPANSION) {
 | |
|         wc[numW] = 0;             // Terminate the sub-buffer
 | |
|       }
 | |
|       if(AdjColumn != 0) {
 | |
|         // Adjust the cursor position
 | |
|         PrevColumn = CurColumn;
 | |
|         CurColumn = ModuloAdd(PrevColumn, AdjColumn, (UINT32)This->MaxColumn);
 | |
|         if(CurColumn < PrevColumn) {
 | |
|           // We must have wrapped, so we are on the next Row
 | |
|           ++CurRow;
 | |
|           if(CurRow >= This->MaxRow) {
 | |
|             // The screen has scrolled so need to adjust Initial location.
 | |
|             --This->InitialXY.Row;        // Initial row has moved up one
 | |
|             CurRow = (UINT32)(This->MaxRow - 1);    // We stay on the bottom row
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       This->CurrentXY.Column  = CurColumn;
 | |
|       This->CurrentXY.Row     = CurRow;
 | |
|     }
 | |
|     else {
 | |
|       // Output processing disabled -- RAW output mode
 | |
|       wc[0] = InCh;
 | |
|       wc[1] = 0;
 | |
|     }
 | |
|     // Put the character(s) into the output buffer
 | |
|     if(numW > 0) {
 | |
|       (void)OBuf->Write(OBuf, (const void *)wcb, (size_t)numW);
 | |
|     }
 | |
|     RetVal = numW;
 | |
|   }
 | |
|   else {
 | |
|     if(This == NULL) {
 | |
|       errno = EINVAL;
 | |
|     }
 | |
|     else {
 | |
|       errno = ENOSPC;
 | |
|     }
 | |
|   }
 | |
|   return RetVal;
 | |
| }
 |