]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/LibC/Uefi/Devices/Console/daConsole.c
StdLib: Add multi-byte character support. The normal "narrow" character set is now...
[mirror_edk2.git] / StdLib / LibC / Uefi / Devices / Console / daConsole.c
index e9983e993399ca9aad6b2154cad85ad4c9e5393b..655b685214507acce6d899abd3be68ae01ec929b 100644 (file)
@@ -3,7 +3,7 @@
 \r
   Manipulates abstractions for stdin, stdout, stderr.\r
 \r
-  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available under\r
   the terms and conditions of the BSD License that accompanies this distribution.\r
   The full text of the license may be found at\r
@@ -52,27 +52,45 @@ static wchar_t       *ConReadBuf;
 static BOOLEAN        TtyCooked;\r
 static BOOLEAN        TtyEcho;\r
 \r
+/** Convert string from MBCS to WCS and translate \n to \r\n.\r
+\r
+    It is the caller's responsibility to ensure that dest is\r
+    large enough to hold the converted results.  It is guaranteed\r
+    that there will be fewer than n characters placed in dest.\r
+\r
+    @param  dest    WCS buffer to receive the converted string.\r
+    @param  buf     MBCS string to convert to WCS.\r
+    @param  n       Number of BYTES contained in buf.\r
+    @param  Cs      Pointer to the character state object for this stream\r
+\r
+    @return   The number of BYTES consumed from buf.\r
+**/\r
 ssize_t\r
-WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)\r
+WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs)\r
 {\r
-  UINTN   i;\r
-  wint_t  wc;\r
+  ssize_t i     = 0;\r
+  int     numB  = 0;\r
+  wchar_t wc[2];\r
 \r
-  for(i = 0; i < n; ++i) {\r
-    wc = btowc(*buf++);\r
-    if( wc == 0) {\r
+  while(n > 0) {\r
+    numB = (int)mbrtowc(wc, buf, MIN(MB_LEN_MAX,n), Cs);\r
+    if( numB == 0) {\r
       break;\r
     };\r
-    if(wc < 0) {\r
-      wc = BLOCKELEMENT_LIGHT_SHADE;\r
+    if(numB < 0) {\r
+      wc[0] = BLOCKELEMENT_LIGHT_SHADE;\r
     }\r
-    if(wc == L'\n') {\r
+    if(wc[0] == L'\n') {\r
       *dest++ = L'\r';\r
+      ++i;\r
     }\r
-    *dest++ = (CHAR16)wc;\r
+    *dest++ = (CHAR16)wc[0];\r
+    i += numB;\r
+    n -= numB;\r
+    buf += numB;\r
   }\r
   *dest = 0;\r
-  return (ssize_t)i;\r
+  return i;\r
 }\r
 \r
 static\r
@@ -105,7 +123,7 @@ da_ConSeek(
 {\r
   ConInstance                       *Stream;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *Proto;\r
-  XYoffset                           CursorPos;\r
+  XY_OFFSET                          CursorPos;\r
 \r
   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);\r
   // Quick check to see if Stream looks reasonable\r
@@ -140,7 +158,7 @@ da_ConSeek(
                               the string couldn't be displayed.\r
   @param[in]      Buffer      The WCS string to be displayed\r
 \r
-  @return   The number of characters written.\r
+  @return   The number of BYTES written.  Because of MBCS, this may be more than number of characters.\r
 */\r
 static\r
 ssize_t\r
@@ -155,8 +173,7 @@ da_ConWrite(
   EFI_STATUS                          Status;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;\r
   ConInstance                        *Stream;\r
-  ssize_t                             NumChar;\r
-  //XYoffset                            CursorPos;\r
+  ssize_t                             NumBytes;\r
 \r
   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);\r
   // Quick check to see if Stream looks reasonable\r
@@ -173,34 +190,21 @@ da_ConWrite(
   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;\r
 \r
   // Convert string from MBCS to WCS and translate \n to \r\n.\r
-  NumChar = WideTtyCvt(gMD->UString, (const char *)Buffer, BufferSize);\r
-  //if(NumChar > 0) {\r
-  //  BufferSize = (size_t)(NumChar * sizeof(CHAR16));\r
-  //}\r
-  BufferSize = NumChar;\r
-\r
-  //if( Position != NULL) {\r
-  //  CursorPos.Offset = (UINT64)*Position;\r
-\r
-  //  Status = Proto->SetCursorPosition(Proto,\r
-  //                                    (INTN)CursorPos.XYpos.Column,\r
-  //                                    (INTN)CursorPos.XYpos.Row);\r
-  //  if(RETURN_ERROR(Status)) {\r
-  //    return -1;\r
-  //  }\r
-  //}\r
+  NumBytes = WideTtyCvt(gMD->UString, (const char *)Buffer, (ssize_t)BufferSize, &Stream->CharState);\r
+  BufferSize = NumBytes;\r
+\r
 \r
   // Send the Unicode buffer to the console\r
   Status = Proto->OutputString( Proto, gMD->UString);\r
   // Depending on status, update BufferSize and return\r
   if(RETURN_ERROR(Status)) {\r
-    BufferSize = 0;    // We don't really know how many characters made it out\r
+    BufferSize = 0;     // We don't really know how many characters made it out\r
   }\r
   else {\r
-    //BufferSize = NumChar;\r
-    Stream->NumWritten += NumChar;\r
+    //BufferSize = NumBytes;\r
+    Stream->NumWritten += NumBytes;\r
   }\r
-  EFIerrno = Status;\r
+  EFIerrno = Status;      // Make error reason available to caller\r
   return BufferSize;\r
 }\r
 \r
@@ -342,7 +346,8 @@ da_ConStat(
     return -1;\r
   }\r
   // All of our parameters are correct, so fill in the information.\r
-  Buffer->st_blksize = 1;\r
+  Buffer->st_blksize  = 0;   // Character device, not a block device\r
+  Buffer->st_mode     = filp->f_iflags;\r
 \r
 // ConGetPosition\r
   if(Stream->InstanceNum == STDIN_FILENO) {\r
@@ -504,6 +509,7 @@ __Cons_construct(
 \r
     Stream->Cookie      = CON_COOKIE;\r
     Stream->InstanceNum = i;\r
+    Stream->CharState.A = 0;    // Start in the initial state\r
 \r
     switch(i) {\r
       case STDIN_FILENO:\r