Working with the limitations of CmdFont

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Working with the limitations of CmdFont

#1 Post by thefeduke » 24 Nov 2017 00:45

The most recent incarnation of this utility was
posted wrote:Rem Start http://www.dostips.com/forum/viewtopic. ... 820#p53820
Rem Posted: Wed Sep 06, 2017 11:50 am by aGerman
Rem Post subject: Automated setup of DOS command window
on behalf of penpen.

I am OK with the set function only supporting Raster fonts, but I like the information provided with the get function and wanted to exploit it in a batch script. It it even displays limited information for non-raster fonts.
Sample Output wrote:0::Terminal::4x6
1::Terminal::6x8
2::Terminal::8x8
3::Terminal::16x8
4::Terminal::5x12
5::Terminal::7x12
6::Terminal::8x12
7::Terminal::16x12
8::Terminal::12x16
9::Terminal::10x18
-::Consolas::20::CURRENT
I can see it but do not seem to be able to access it in batch. The output won't pipe and redirects to an empty file. Would this be because of the language used to write it or the method used for the display? Is there some way to work around this?

In the meantime, I used Antonio's Window.exe Auxiliary program to produce

Code: Select all

C:\Users\Zyltch\~Scripts~>fontdims 0

'Illegible' input argument '0' overrides default to 0 value.
0::Terminal::4x6
1::Terminal::6x8
2::Terminal::8x8
3::Terminal::16x8
4::Terminal::5x12
5::Terminal::7x12
6::Terminal::8x12
7::Terminal::16x12
8::Terminal::12x16
9::Terminal::10x18
-::Consolas::20::CURRENT

Font Size: (9 x 20) pixels.
but I still don't know how to find the name of the current font. Even this falls short. My eyes have long since been unable to read a 4x6 font to see the result. I'll even argue that the font did not get small by itself, so, if I set it, I don't need to display it, but . . .

The front-end of the script that displayed the dimensions is:

Code: Select all

@echo off &setlocal EnableDelayedExpansion
::  Forked from FontSizes.bat: Wed Oct 17, 2017

Rem Adjust Illegible value to suit screen size and resolution
Rem and optical acuity of the user: [Ease-of-Use if not eagle-eyed]
    Set "Illegible=%~1"
    If Defined Illegible (
        Set /A "Illegible=%~1"
        Echo.&Echo.'Illegible' input argument '%~1' overrides default to !Illegible! value.
    ) Else Set /A "Illegible=0"
Rem Default value:   0 - Value of 0 is to bypass readable pop-up.
Rem Suggested value: 7 - Value greater than 19 activates pop-up in most cases.

Rem Non-critical external batch executable dependency is available at
Rem Start http://www.dostips.com/forum/viewtopic.php?p=53820#p53820
Rem Posted: Wed Sep 06, 2017 11:50 am by aGerman     
Rem Post subject: Automated setup of DOS command window
    Call cmdfont get

Rem Critical external batch executable dependency
    ver>Nul
    Where window.exe>nul 2>nul
    If ERRORLEVEL 1 (Echo.
        Echo.Window.exe is critical to this batch script and is available at
        Echo.Start http://www.dostips.com/forum/viewtopic.php?f=3^&t=3428
        Exit /B
    )

Rem Start http://www.dostips.com/forum/viewtopic.php?f=3&t=3428
    Window Size
    Call :UnsignedCoords %ErrorLevel% WinSizeH WinSizeV
    Window GSize
    Call :UnsignedCoords %ErrorLevel% GsizeH GsizeV

Rem Do the math for active font dimensions
    Set /A "FontH=GsizeH/WinSizeH, FontV=GsizeV/WinSizeV"

Rem No need to continue if the results are legible in the current font
    If %fontV% GTR %Illegible% (Echo.
        Echo.Font Size: ^(%FontH% x %FontV%^) pixels.
        Exit /B
    ) Else GoTo :More-readable


Rem The only Subroutine required above is sheltered after the GOTO

Rem This cloned batch subroutine separates into two 16-bits numbers
Rem the 32-bits value returned by some Registry queries and Aux programs
:UnsignedCoords 32bits Horizontal= Vertical=
Set /A "%2=%1&0xFFFF, %3=(%1>>16)&0xFFFF"
Exit /B

Rem Start https://stackoverflow.com/a/19188162/1012053
Rem    _     _   _         _                       _
Rem   /_\   | | | |     __| |  ___   _,_    ___   | |
Rem  / _ \  | | | |    / _  | / _ \ |   \  / -_)  |_|
Rem /_/ \_\ |_| |_|    \__,_| \___/ |_||_| \___)  (_)
Rem
Rem This batch script can be complete at this point.





Rem If the output is not readable,
Rem it may be viewed by temporarily adjusting to a
Rem larger font size using Window Properties or other means.

Rem The following code may also show the results, but will never be
Rem reached if the Illegible value is adjusted to a very low value

:More-readable
I am still packaging the back-end that creates a pop-up that is readable and does not disturb the original window.

John A.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Working with the limitations of CmdFont

#2 Post by penpen » 24 Nov 2017 09:55

thefeduke wrote: can see it but do not seem to be able to access it in batch. The output won't pipe and redirects to an empty file. Would this be because of the language used to write it or the method used for the display? Is there some way to work around this?
CmdFont:
It seems that whenever the stdout is redirected, GetCurrentConsoleFontEx detects that the stdout filehandle is invalid ... .
This shouldn't happen - or better it doesn't happen in my c++ program, which is litterally the same...
maybe there is an unexpected side effect with the pinvoke - which i will do after i finished my c++ program:
Actually i'm testing how to get a full list of the console fonts;
i have installed some extra fonts which aren't listed by my c++ program, but are selectable in cmd.exe properties dialog (which is a very annoying task).

The programm then exits in the following part of the code:

Code: Select all

            case GET:
                {
                    CONSOLE_FONT_INFOEX infoex = new CONSOLE_FONT_INFOEX () { cbSize = (ULONG)Marshal.SizeOf(typeof(CONSOLE_FONT_INFOEX)) };
                    if (GetCurrentConsoleFontEx (GetStdHandle (Constants.STD_OUTPUT_HANDLE), Constants.FALSE, ref infoex) == 0) {
                        return 1;
                    }
(So no output is generated.)

It should be "fixed" by commenting out the return statement:

Code: Select all

            case GET:
                {
                    CONSOLE_FONT_INFOEX infoex = new CONSOLE_FONT_INFOEX () { cbSize = (ULONG)Marshal.SizeOf(typeof(CONSOLE_FONT_INFOEX)) };
                    if (GetCurrentConsoleFontEx (GetStdHandle (Constants.STD_OUTPUT_HANDLE), Constants.FALSE, ref infoex) == 0) {
//                        return 1;
                    }
Note: Obviously, because of this you cannot trust the '"::CURRENT"-line'.


penpen

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Working with the limitations of CmdFont

#3 Post by aGerman » 24 Nov 2017 15:14

That's weird :? I was able to work around this bug using CreateFile instead of GetStdHandle.
I updated the file in the linked thread to have an interim solution as long as penpen is working on the new version.

Steffen

thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Re: Working with the limitations of CmdFont

#4 Post by thefeduke » 25 Nov 2017 01:06

penpen wrote:Actually i'm testing how to get a full list of the console fonts
Thank you for your insightful explanation.
Steffen, your temporary fix suits my needs just fine. By adding this with the new module:

Code: Select all

    For /F "usebackq tokens=1-3* delims=:" %%A in (`cmdfont`) do (
        If /I "%%~D" EQU "Current" Set "Font=%%~B" 
    )
my output looks like

Code: Select all

0::Terminal::4x6
1::Terminal::6x8
2::Terminal::8x8
3::Terminal::16x8
4::Terminal::5x12
5::Terminal::7x12
6::Terminal::8x12
7::Terminal::16x12
8::Terminal::12x16
9::Terminal::10x18
-::Lucida Console::20::CURRENT

Font 'Lucida Console' Size: (12 x 20) pixels.
giving me the three elements I wanted; Height and width from the Window calculation and name and height from CmdFont. Seeing the same height is a sort of reasonableness test. Thank you,

John A.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Working with the limitations of CmdFont

#5 Post by aGerman » 25 Nov 2017 05:01

I was not expecting that it didn't even work in the first place :oops: As penpen said the same program code in C or C++ would work flawlessly. Of course I've chosen the colon as token separator in order that you are able to process the output in a FOR /F loop.

Code: Select all

@echo off &setlocal

REM find the index for font size 8x12 and change the font
for /f "delims=:" %%i in ('cmdfont get^|findstr /e "::8x12"') do cmdfont set %%i

REM find the currently used font
for /f "tokens=1-4 delims=:" %%i in ('cmdfont get') do if "%%l" neq "" (
  echo index %%i
  echo name  %%j
  echo size  %%k
)

pause
Unfortunately the used API functions don't return the character width for fonts other than Terminal (raster font). That's the reason why I only output the height in that case.

Steffen

thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Re: Working with the limitations of CmdFont

#6 Post by thefeduke » 25 Nov 2017 10:48

aGerman wrote: Unfortunately the used API functions don't return the character width for fonts other than Terminal (raster font). That's the reason why I only output the height in that case.
Wonderful. So we have Raster font support for 'CmdFont set' and pretty good results for 'CmdFont get' with quite usable output. This fills in the missing piece:

Code: Select all

@echo off &setlocal 

Rem Get window dimensions in characters and pixels
    Window Size
    Call :UnsignedCoords %ErrorLevel% WinSizeH WinSizeV
    Window GSize
    Call :UnsignedCoords %ErrorLevel% GsizeH GsizeV

Rem Do the math for active font dimensions
    Set /A "FontH=GsizeH/WinSizeH, FontV=GsizeV/WinSizeV"

REM find the current font name
    For /F "tokens=2 delims=:" %%F in ('cmdfont') do Set "Font=%%~F"

    Echo.&Echo.Active font '%Font%' size: ^(%FontH% x %FontV%^) pixels.

    Exit /B

Rem This cloned batch subroutine separates into two 16-bits numbers
Rem the 32-bits value returned by some Registry queries and Aux programs
:UnsignedCoords 32bits Horizontal= Vertical=
Set /A "%2=%1&0xFFFF, %3=(%1>>16)&0xFFFF"
Exit /B

It does not appear to be fussy about the font:
C:\Users\Yanci\~Scripts~>fontactive

Active font 'SimSun-ExtB' size: (9 x 18) pixels.
John A.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Working with the limitations of CmdFont

#7 Post by aGerman » 25 Nov 2017 11:50

My settings are Consolas with font size 12 (which should have a width of 6 px and a height of 12 px according to what the settings menu shows).
Using the new Win10 console the script displays:
Active font 'Consolas' size: (5 x 12) pixels.
It's even worse if I use the legacy console:
Active font 'Consolas' size: (4 x 9) pixels.

To be honest I think that the script displays the real font size because the text is much smaller in the legacy console even if the font settings are the same.

Steffen

thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Re: Working with the limitations of CmdFont

#8 Post by thefeduke » 25 Nov 2017 18:56

Steffen, your results surprise me. I set to that size Consolas font and matched the Properties values. I reran after pasting from my own post.

If you add a few SET commands for Gs, Wins and cF, the math will be revealed. Here is part of a more complex earlier attempt that I found too destructive to the window status :

Code: Select all

@ECHO Off
setlocal

    Window Size 80 30
    Call :UnsignedCoords %ErrorLevel% WSH WSV
    Window gSize show
    Call :UnsignedCoords %ErrorLevel% GSH GSV

    Window Size 79 29
    Call :UnsignedCoords %ErrorLevel% WSH2 WSV2 
    Window gSize show
    Call :UnsignedCoords %ErrorLevel% GSH2 GSV2 

Rem Calculate some Screen dimensions
    Set /a "diffH=GSH-GSH2, diffV=GSV-GSV2"
    Echo.Font Dimesions: (%diffH% x %diffV%) pixels

    Call cmdfont get

Exit /B

Rem This cloned batch subroutine separates into two 16-bits numbers
Rem the 32-bits value returned by some Registry queries and Aux programs
:UnsignedCoords 32bits Horizontal= Vertical=
Set /A "%2=%1&0xFFFF, %3=(%1>>16)&0xFFFF"
Exit /B

This is more direct and should match one or the other to see what I should work on. Thanks for your time.

John A.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Working with the limitations of CmdFont

#9 Post by misol101 » 26 Nov 2017 01:10

Not sure exactly what you are trying to do, but just wanted to point out that cmdwiz savefont/setfont can be used to set (or rather, "restore") any console font/size, not just raster fonts.

Also, the pixel sizes reported for raster font 0,1 and 5 are incorrect in Windows 10 unless "legacy console mode" is on, as I wrote about here: http://www.dostips.com/forum/viewtopic.php?f=3&t=8018

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Working with the limitations of CmdFont

#10 Post by aGerman » 26 Nov 2017 04:45

John, it's as misol101 said. At the image you see the new Win10 console (left) and the legacy console (right).
fontsize.png
fontsize.png (37.72 KiB) Viewed 11745 times
This time the calculation of the font seems to be okay which most likely depends on rounding errors. However the legacy console shows 5 x 10 even if the settings are still the same. But the image also shows that the legacy console is smaller than the new console. Also the text is smaller. That's the reason why I said that the script calculates the real size of the characters as they are displayed in the window. In other words Windows doesn't respect the settings. That's not a problem of your script or of your calculation.

Steffen

Post Reply