{"id":7287,"date":"2025-12-13T00:01:27","date_gmt":"2025-12-13T08:01:27","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7287"},"modified":"2025-12-20T09:32:13","modified_gmt":"2025-12-20T17:32:13","slug":"dumping-the-screen-in-w-i-d-e-color","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7287","title":{"rendered":"Dumping the Screen in W-I-D-E Color"},"content":{"rendered":"<p>Updating the <em>hexdump<\/em> utility with color is good, but adding wide characters for output is even better. From <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7266\">last week&#8217;s Lesson<\/a>, I&#8217;m adding wide character output to generate codes for non-printing ASCII values 0 through 31 and 127.<br \/>\n<!--more--><br \/>\nI cover wide character output in a <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=2568\">series of posts<\/a> from 2017. The key is to set the locale, then use the wide character functions for input and output. Though these directions seem easy, it took me two tries to perfect the output.<\/p>\n<p>My first attempt uses wide character output functions, as well as &#8220;long&#8221; strings and character values:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_12_13-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2025_12_13-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;locale.h&gt;\r\n#include &lt;wchar.h&gt;\r\n\r\n#define RED \"\\e[31m\"\r\n#define NORMAL \"\\e[m\"\r\n\r\nint main()\r\n{\r\n    wchar_t chw;\r\n\r\n    <span class=\"comments\">\/* set the local for wide characters *\/<\/span>\r\n    setlocale(LC_CTYPE,\"UTF-8\");\r\n\r\n    for( chw=0; chw&lt;=127; chw++ )\r\n    {\r\n        wprintf(L\"%02X %03d \",chw,chw);\r\n        if( chw&lt;32 )\r\n            wprintf(L\"%s%lc%s\",RED,chw+L'@',NORMAL);\r\n        else if( chw==127 )\r\n            wprintf(L\"%s%lc%s\",RED,9249,NORMAL);\r\n        else\r\n            putwchar(chw);\r\n        putwchar(L'\\n');\r\n    }\r\n    return 0;\r\n}<\/pre>\n<p>The definitions for the ANSI <code>RED<\/code> and <code>NORMAL<\/code> codes don&#8217;t need to be long strings. I tried declaring them as such originally, but the output was weird. So they&#8217;re coded as standard ASCII strings.<\/p>\n<p>Wide character (<em>wchar_t<\/em>) variable <code>chw<\/code> is used for output and as the looping counter.<\/p>\n<p>The <em>setlocale()<\/em> function sets the character type as UTF-8: <code>setlocale(LC_CTYPE,\"UTF-8\");<\/code><\/p>\n<p>The <em>wprintf()<\/em> function outputs each line of text. The format string is prefixed with an <code>L<\/code> to indicate a wide string. For values 0 through 32, the character output is <code>chw+L'@'<\/code>. The <code>L<\/code> prefix sets a wide character, which is the value of <code>chw<\/code> plus <code>@<\/code>. For the value 127, Unicode character 9249 is output (U-2421 or &#9249;).<\/p>\n<p>The <em>putwchar()<\/em> function outputs single wide characters; the wide newline character is prefixed with an <code>L<\/code>: <code>L'\\n'<\/code><\/p>\n<p>Here&#8217;s the program&#8217;s truncated output:<\/p>\n<p><code>00 000 <span style=\"color:red;\">@<\/span><br \/>\n01 001 <span style=\"color:red;\">A<\/span><br \/>\n02 002 <span style=\"color:red;\">B<\/span><br \/>\n03 003 <span style=\"color:red;\">C<\/span><br \/>\n04 004 <span style=\"color:red;\">D<\/span><br \/>\n05 005 <span style=\"color:red;\">E<\/span><br \/>\n06 006 <span style=\"color:red;\">F<\/span><br \/>\n07 007 <span style=\"color:red;\">G<\/span><br \/>\n...<br \/>\n78 120 x<br \/>\n79 121 y<br \/>\n7A 122 z<br \/>\n7B 123 {<br \/>\n7C 124 |<br \/>\n7D 125 }<br \/>\n7E 126 ~<br \/>\n7F 127 <span style=\"color:red;\">DEL<\/span><\/code><\/p>\n<p>The control codes are output using their letter equivalents color-coded RED: <span style=\"color:red;\">@<\/span> for Ctrl+@, <span style=\"color:red;\">A<\/span> for Ctrl+A, and so on.<\/p>\n<p>Curiously, the program generates multiple characters for code U-2421: <span style=\"color:red;\">DEL<\/span> instead of &#9249;. This behavior is considered normal. In fact, I updated the code, replacing Line 18 with the following:<\/p>\n<p><code>wprintf(L\"%s%lc%s\",RED,chw+9216,NORMAL);<\/code><\/p>\n<p>The result of the expression <code>chw+9216<\/code> generates the following output (first 32 lines):<\/p>\n<p><code>00 000 <span style=\"color:red;\">NUL<\/span><br \/>\n01 001 <span style=\"color:red;\">SOH<\/span><br \/>\n02 002 <span style=\"color:red;\">STX<\/span><br \/>\n03 003 <span style=\"color:red;\">ETX<\/span><br \/>\n04 004 <span style=\"color:red;\">EOT<\/span><br \/>\n05 005 <span style=\"color:red;\">ENQ<\/span><br \/>\n06 006 <span style=\"color:red;\">ACK<\/span><br \/>\n07 007 <span style=\"color:red;\">BEL<\/span><br \/>\n08 008 <span style=\"color:red;\">BS<\/span><br \/>\n09 009 <span style=\"color:red;\">HT<\/span><br \/>\n0A 010 <span style=\"color:red;\">LF<\/span><br \/>\n0B 011 <span style=\"color:red;\">VT<\/span><br \/>\n0C 012 <span style=\"color:red;\">FF<\/span><br \/>\n0D 013 <span style=\"color:red;\">CR<\/span><br \/>\n0E 014 <span style=\"color:red;\">SO<\/span><br \/>\n0F 015 <span style=\"color:red;\">SI<\/span><br \/>\n10 016 <span style=\"color:red;\">DLE<\/span><br \/>\n11 017 <span style=\"color:red;\">DC1<\/span><br \/>\n12 018 <span style=\"color:red;\">DC2<\/span><br \/>\n13 019 <span style=\"color:red;\">DC3<\/span><br \/>\n14 020 <span style=\"color:red;\">DC4<\/span><br \/>\n15 021 <span style=\"color:red;\">NAK<\/span><br \/>\n16 022 <span style=\"color:red;\">SYN<\/span><br \/>\n17 023 <span style=\"color:red;\">ETB<\/span><br \/>\n18 024 <span style=\"color:red;\">CAN<\/span><br \/>\n19 025 <span style=\"color:red;\">EM<\/span><br \/>\n1A 026 <span style=\"color:red;\">SUB<\/span><br \/>\n1B 027 <span style=\"color:red;\">ESC<\/span><br \/>\n1C 028 <span style=\"color:red;\">FS<\/span><br \/>\n1D 029 <span style=\"color:red;\">GS<\/span><br \/>\n1E 030 <span style=\"color:red;\">RS<\/span><br \/>\n1F 031 <span style=\"color:red;\">US<\/span><\/code><\/p>\n<p>Individual characters are output instead of single Unicode characters. Despite their appearance, these are Unicode characters. The problem I discovered is with the <em>setlocale()<\/em> function. To fix the output, the <em>setlocale()<\/em> function must be updated to read:<\/p>\n<p><code>setlocale(LC_ALL,\"\");<\/code><\/p>\n<p>After making this change, the first 32 lines output now look like this:<\/p>\n<p><code>00 000 <span style=\"color:red;\">&#9216;<\/span><br \/>\n01 001 <span style=\"color:red;\">&#9217;<\/span><br \/>\n02 002 <span style=\"color:red;\">&#9218;<\/span><br \/>\n03 003 <span style=\"color:red;\">&#9219;<\/span><br \/>\n04 004 <span style=\"color:red;\">&#9220;<\/span><br \/>\n05 005 <span style=\"color:red;\">&#9221;<\/span><br \/>\n06 006 <span style=\"color:red;\">&#9222;<\/span><br \/>\n07 007 <span style=\"color:red;\">&#9223;<\/span><br \/>\n08 008 <span style=\"color:red;\">&#9224;<\/span><br \/>\n09 009 <span style=\"color:red;\">&#9225;<\/span><br \/>\n0A 010 <span style=\"color:red;\">&#9226;<\/span><br \/>\n0B 011 <span style=\"color:red;\">&#9227;<\/span><br \/>\n0C 012 <span style=\"color:red;\">&#9228;<\/span><br \/>\n0D 013 <span style=\"color:red;\">&#9229;<\/span><br \/>\n0E 014 <span style=\"color:red;\">&#9230;<\/span><br \/>\n0F 015 <span style=\"color:red;\">&#9231;<\/span><br \/>\n10 016 <span style=\"color:red;\">&#9232;<\/span><br \/>\n11 017 <span style=\"color:red;\">&#9233;<\/span><br \/>\n12 018 <span style=\"color:red;\">&#9234;<\/span><br \/>\n13 019 <span style=\"color:red;\">&#9235;<\/span><br \/>\n14 020 <span style=\"color:red;\">&#9236;<\/span><br \/>\n15 021 <span style=\"color:red;\">&#9237;<\/span><br \/>\n16 022 <span style=\"color:red;\">&#9238;<\/span><br \/>\n17 023 <span style=\"color:red;\">&#9239;<\/span><br \/>\n18 024 <span style=\"color:red;\">&#9240;<\/span><br \/>\n19 025 <span style=\"color:red;\">&#9241;<\/span><br \/>\n1A 026 <span style=\"color:red;\">&#9242;<\/span><br \/>\n1B 027 <span style=\"color:red;\">&#9243;<\/span><br \/>\n1C 028 <span style=\"color:red;\">&#9244;<\/span><br \/>\n1D 029 <span style=\"color:red;\">&#9245;<\/span><br \/>\n1E 030 <span style=\"color:red;\">&#9246;<\/span><br \/>\n1F 031 <span style=\"color:red;\">&#9247;<\/span><br \/>\n...<\/code><\/p>\n<p>The characters used for the control codes may not look exactly as shown above; the specific format depends on the terminal&#8217;s typeface. Regardless, the updated code is found <a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_12_13-Lesson-b.c\" target=\"_blank\">here on GitHub<\/a>.<\/p>\n<p>Now that I&#8217;ve figured out how to represent non-printing ASCII codes, I could update my improved <em>hexdump<\/em> utility, but I still need a way to represent values 128 through 255. I cover this task in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7301\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wide characters offer more variety when outputting &#8220;plain&#8221; text. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7287\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7287","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7287","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7287"}],"version-history":[{"count":12,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7287\/revisions"}],"predecessor-version":[{"id":7325,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7287\/revisions\/7325"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}