Beispiel #1
0
 public static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC tm);
Beispiel #2
0
 internal static extern bool GetTextMetrics(HDC hdc, out TEXTMETRIC tm);
Beispiel #3
0
        internal static int LengthInBufferCells(string str, int offset, bool checkEscapeSequences)
        {
            Dbg.Assert(offset >= 0, "offset >= 0");
            Dbg.Assert(string.IsNullOrEmpty(str) || (offset < str.Length), "offset < str.Length");

            var escapeSequenceAdjustment = 0;
            if (checkEscapeSequences)
            {
                int i = 0;
                while (i < offset)
                {
                    ControlSequenceLength(str, ref i);
                }

                // If offset != i, we're in the middle of a sequence, which the caller should avoid,
                // but we'll tolerate.
                while (i < str.Length)
                {
                    escapeSequenceAdjustment += ControlSequenceLength(str, ref i);
                }
            }

            uint codePage = NativeMethods.GetConsoleOutputCP();
            if (!IsAvailableFarEastCodePage(codePage))
            {
                return str.Length - offset - escapeSequenceAdjustment;
            }

            HWND hwnd = (HWND)0;
            HDC hDC = (HDC)0;
            bool istmInitialized = false;
            TEXTMETRIC tm = new TEXTMETRIC(); ;
            int length = 0;
            try
            {
                int n = str.Length;
                for (int i = offset; i < n; i++)
                {
                    char c = str[i];
                    length += LengthInBufferCellsFE(c, ref hwnd, ref hDC, ref istmInitialized, ref tm);
                }
                return length - escapeSequenceAdjustment;
            }
            finally
            {
                if (hwnd != (IntPtr)0 && hDC != (IntPtr)0)
                {
                    NativeMethods.ReleaseDC(hwnd, hDC);
                }
            }
        }
Beispiel #4
0
 private static int LengthInBufferCells(char c, uint codePage)
 {
     if (!IsAvailableFarEastCodePage(codePage))
     {
         return 1;
     }
     HWND hwnd = (HWND)0;
     HDC hDC = (HDC)0;
     bool istmInitialized = false;
     TEXTMETRIC tm = new TEXTMETRIC(); ;
     try
     {
         return LengthInBufferCellsFE(c, ref hwnd, ref hDC, ref istmInitialized, ref tm);
     }
     finally
     {
         if (hwnd != (IntPtr)0 && hDC != (IntPtr)0)
         {
             NativeMethods.ReleaseDC(hwnd, hDC);
         }
     }
 }
Beispiel #5
0
        /// <summary>
        /// From IsConsoleFullWidth in \windows\core\ntcon\server\dbcs.c
        /// Precondition: the current code page needs to be a Far East code page.
        /// 
        /// char F8F8 makes this function return 1 while in CHT, CHS, and KOR it takes 2 cells.
        /// I don't think we should special-case this because that ought to be a bug outside of
        /// this code.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="hwnd">window handle</param>
        /// <param name="hDC">handle to DC; it is not released by this method</param>
        /// <param name="istmInitialized"></param>
        /// <param name="tm"></param>
        /// <returns></returns>
        private static int LengthInBufferCellsFE(char c, ref HWND hwnd, ref HDC hDC, ref bool istmInitialized, ref TEXTMETRIC tm)
        {
            if (0x20 <= c && c <= 0x7e)
            {
                /* ASCII */
                return 1;
            }
            else if (0x3041 <= c && c <= 0x3094)
            {
                /* Hiragana */
                return 2;
            }
            else if (0x30a1 <= c && c <= 0x30f6)
            {
                /* Katakana */
                return 2;
            }
            else if (0x3105 <= c && c <= 0x312c)
            {
                /* Bopomofo */
                return 2;
            }
            else if (0x3131 <= c && c <= 0x318e)
            {
                /* Hangul Elements */
                return 2;
            }
            else if (0xac00 <= c && c <= 0xd7a3)
            {
                /* Korean Hangul Syllables */
                return 2;
            }
            else if (0xff01 <= c && c <= 0xff5e)
            {
                /* Fullwidth ASCII variants */
                return 2;
            }
            else if (0xff61 <= c && c <= 0xff9f)
            {
                /* Halfwidth Katakana variants */
                return 1;
            }
            else if ((0xffa0 <= c && c <= 0xffbe) ||
                     (0xffc2 <= c && c <= 0xffc7) ||
                     (0xffca <= c && c <= 0xffcf) ||
                     (0xffd2 <= c && c <= 0xffd7) ||
                     (0xffda <= c && c <= 0xffdc))
            {
                /* Halfwidth Hangule variants */
                return 1;
            }
            else if (0xffe0 <= c && c <= 0xffe6)
            {
                /* Fullwidth symbol variants */
                return 2;
            }
            else if (0x4e00 <= c && c <= 0x9fa5)
            {
                /* Han Ideographic */
                return 2;
            }
            else if (0xf900 <= c && c <= 0xfa2d)
            {
                /* Han Compatibility Ideographs */
                return 2;
            }
            else
            {
                // GetTextMetrics / GetCharWidth32 exist in an extension API set 'ext-ms-win-gdi-font-l1-1-1.dll', which is not available in NanoServer.
#if !CORECLR
                /* Unknown character: need to use GDI*/
                if (hDC == (IntPtr)0)
                {
                    hwnd = NativeMethods.GetConsoleWindow();
                    if ((IntPtr)0 == hwnd)
                    {
                        int err = Marshal.GetLastWin32Error();
                        //Don't throw exception so that output can continue
                        tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the window handle to the console.",
                            err);
                        return 1;
                    }
                    hDC = NativeMethods.GetDC(hwnd);
                    if ((IntPtr)0 == hDC)
                    {
                        int err = Marshal.GetLastWin32Error();
                        //Don't throw exception so that output can continue
                        tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the Device Context of the console window.",
                            err);
                        return 1;
                    }
                }
                bool result = true;
                if (!istmInitialized)
                {
                    result = NativeMethods.GetTextMetrics(hDC, out tm);
                    if (!result)
                    {
                        int err = Marshal.GetLastWin32Error();
                        //Don't throw exception so that output can continue
                        tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the Text Metric of the console window's Device Context.",
                            err);
                        return 1;
                    }
                    istmInitialized = true;
                }
                int width;
                result = NativeMethods.GetCharWidth32(hDC, (uint)c, (uint)c, out width);
                if (!result)
                {
                    int err = Marshal.GetLastWin32Error();
                    //Don't throw exception so that output can continue
                    tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the width of a char.",
                        err);
                    return 1;
                }
                if (width >= tm.tmMaxCharWidth)
                {
                    return 2;
                }
#endif
            }
            tracer.WriteLine("failed to locate char {0}, return 1", (int)c);
            return 1;
        }
 public static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC tm);