<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Trifle on Illusion and Trifle</title><link>https://victorhge.github.io/categories/trifle/</link><description>Recent content in Trifle on Illusion and Trifle</description><generator>Hugo -- 0.156.0</generator><language>en</language><copyright>Source code here, licensed under GPLv3 ·</copyright><lastBuildDate>Thu, 12 Mar 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://victorhge.github.io/categories/trifle/index.xml" rel="self" type="application/rss+xml"/><item><title>X Macros</title><link>https://victorhge.github.io/posts/xmacro/</link><pubDate>Thu, 12 Mar 2026 00:00:00 +0800</pubDate><guid>https://victorhge.github.io/posts/xmacro/</guid><description>A simple technique for solving consistency problems in C/C++ projects</description><content:encoded><![CDATA[<blockquote>
<p>No problem can be solved at the same level of thinking that created it.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
&mdash; &ldquo;Albert Einstein&rdquo;</p>
</blockquote>
<h2 id="consistency-challenge">Consistency Challenge</h2>
<p>The first time I ran into X Macros was while debugging an out-of-bounds access issue.</p>
<p>Here is a simplified example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#75715e">// a.h
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">enum</span> {
</span></span><span style="display:flex;"><span>    SYS_OK,
</span></span><span style="display:flex;"><span>    SYS_ERR_TIMEOUT,
</span></span><span style="display:flex;"><span>    SYS_ERR_BUSY,
</span></span><span style="display:flex;"><span>    SYS_ERR_INVALID_ARG,
</span></span><span style="display:flex;"><span>    SYS_ERR_NOT_FOUND
</span></span><span style="display:flex;"><span>} SysState;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// a.c
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>state_desc[] <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    [SYS_OK] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;System OK&#34;</span>,
</span></span><span style="display:flex;"><span>    [SYS_ERR_TIMEOUT] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Timeout&#34;</span>,
</span></span><span style="display:flex;"><span>    [SYS_ERR_BUSY] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;System Busy&#34;</span>,
</span></span><span style="display:flex;"><span>    [SYS_ERR_INVALID_ARG] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Invalid Argument&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// SYS_ERR_NOT_FOUND is missing here
</span></span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;State = %s</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, state_desc[SYS_ERR_NOT_FOUND]);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The issue is easy to spot: <code>SYS_ERR_NOT_FOUND</code> was added to the enum,
but the string table was not updated.</p>
<p>When the program evaluates <code>state_desc[SYS_ERR_NOT_FOUND]</code>, it reads past the
end of the array and eventually crashes.</p>
<p>Of course, we could fix this by adding the missing entry to the string table.
But that only fixes this specific bug — it does not prevent the same type of
problem from happening again.</p>
<p>The underlying issue is that we are maintaining <strong>two pieces of information that
must always stay consistent</strong>:</p>
<ul>
<li>the enum definition</li>
<li>the string table</li>
</ul>
<p>As long as these are maintained separately and rely on manual synchronization,
mistakes like this are inevitable.</p>
<p>What we really need is a way to eliminate this class of problems entirely.</p>
<h2 id="x-macros">X Macros</h2>
<p>While looking for a solution, I came across an article by Randy Meyers
published in <em>Dr. Dobb&rsquo;s Journal</em> titled <strong>The New C: X Macros</strong> <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.
The article introduces a technique that uses the C preprocessor to generate
code from a single data definition.</p>
<p>This technique is commonly known as <strong>X Macros</strong>.</p>
<p>The idea is simple: maintain a single data list, and generate the necessary
code structures by redefining a macro.</p>
<p>Let&rsquo;s modify the previous example to see how this works.</p>
<p>First, define a <strong>Single source of truth</strong>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#75715e">#define SYS_STATE_LIST                         \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    X(SYS_OK,              &#34;System OK&#34;)        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    X(SYS_ERR_TIMEOUT,     &#34;Timeout&#34;)          \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    X(SYS_ERR_BUSY,        &#34;System Busy&#34;)      \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    X(SYS_ERR_INVALID_ARG, &#34;Invalid Argument&#34;) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    X(SYS_ERR_NOT_FOUND,   &#34;Not Found&#34;)
</span></span></span></code></pre></div><p>This list becomes the master definition of our data.
Each entry is wrapped inside a placeholder macro <code>X()</code>.</p>
<p>The name <code>X</code> is simply a convention. It has no special meaning and can be
replaced with any name.</p>
<p>Next, we define the macro <code>X</code> to generate the enum:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#75715e">#define X(name, desc) name,
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">enum</span> {
</span></span><span style="display:flex;"><span>    SYS_STATE_LIST
</span></span><span style="display:flex;"><span>} SysState;
</span></span><span style="display:flex;"><span><span style="color:#75715e">#undef X
</span></span></span></code></pre></div><p>Then we redefine <code>X</code> so that the same list generates the string table:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#75715e">#define X(name, desc) [name] = desc,
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>state_desc[] <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    SYS_STATE_LIST
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span><span style="color:#75715e">#undef X
</span></span></span></code></pre></div><p>If you come from dynamic languages such as Python or Java, this might look
somewhat like a lightweight form of reflection.</p>
<p>X Macros gather scattered information into a single data list. By redefining
and undefining <code>X</code> (<code>#undef</code>), the same data can be injected into multiple
code templates. Adding, removing, or reordering entries will not introduce
inconsistencies.</p>
<p>This technique works well in many situations where related data must stay
synchronized, for example:</p>
<ul>
<li>Managing error codes, states, or event types together with their descriptions</li>
<li>Generating command tables or protocol definitions</li>
<li>Serialization and deserialization</li>
<li>Configuration data initialization and access code generating</li>
</ul>
<h2 id="advanced-notes">Advanced Notes</h2>
<p>X Macros are powerful, but they do come with trade-offs. Macro-heavy code can
reduce readability and make debugging more difficult.</p>
<p>Some practical tips:</p>
<ul>
<li>
<p><strong>Improve readability</strong>: Andrew Lucas suggests passing the macro <code>X</code> as a
parameter to the data list to make the structure clearer <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
</li>
<li>
<p><strong>Large data sets</strong>: If the list becomes very long, you may hit compiler
line-length limits. Randy Meyers recommends placing the list in a separate<code>.def</code> or <code>.h</code> file and using <code>#include</code> to reuse it.</p>
</li>
<li>
<p><strong>Inspect preprocessed output</strong>: You can use <code>gcc -E</code> to view the expanded
source code. Many modern IDEs with language servers can also show this.</p>
</li>
<li>
<p><strong>Team communication</strong>: Not everyone is familiar with this technique. Good
comments and documentation help avoid confusion.</p>
</li>
<li>
<p><strong>Use it sparingly</strong>: Like most macro tricks, X Macros should be used
thoughtfully rather than everywhere.</p>
</li>
</ul>
<h2 id="summary">Summary</h2>
<p>X Macros are essentially a lightweight metaprogramming technique built on top
of the C/C++ preprocessor. In environments without reflection or code
generation tools, they provide a practical way to keep related definitions
synchronized.</p>
<p>By maintaining a <strong>Single Source of Truth</strong> and generating code through macro
expansion, X Macros eliminate the risk of inconsistent duplicated definitions.</p>
<p>The idea dates back to assembly programming in the 1960s. Even today, whenever
large amounts of structured data need to remain consistent, it remains a
surprisingly useful technique — and a valuable tool in the C/C++ programmer&rsquo;s
toolbox.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>AI translated.  I discovered this link when I tried to find the source of this quote:<a href="https://www.quora.com/Einstein-said-that-you-cannot-solve-a-problem-from-the-same-level-of-consciousness-that-created-it-What-did-he-mean-with-it-Can-you-use-a-concrete-example">https://www.quora.com/Einstein-said-that-you-cannot-solve-a-problem-from-the-same-level-of-consciousness-that-created-it-What-did-he-mean-with-it-Can-you-use-a-concrete-example</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Randy Meyers. &ldquo;The New C: X macros&rdquo;, Dr.Dobb&rsquo;s 2001, accessible at:<a href="https://jacobfilipp.com/DrDobbs/articles/CUJ/2001/0105/meyers/meyers.htm">https://jacobfilipp.com/DrDobbs/articles/CUJ/2001/0105/meyers/meyers.htm</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Andrew Lucas. <a href="https://www.embedded.com/reduce-c-language-coding-errors-with-x-macros-part-1/">&ldquo;Reduce C-language coding errors with X macros&rdquo;</a>, Embedded.com, 2013.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Splitting Ctrl+Space</title><link>https://victorhge.github.io/posts/ctrl_space/</link><pubDate>Mon, 02 Mar 2026 00:00:00 +0800</pubDate><guid>https://victorhge.github.io/posts/ctrl_space/</guid><description>&lt;p&gt;Emacs comes with numerous default keybindings, which inevitably conflict with
system-level shortcuts. For Emacs beginners, resolving these conflicts can be a
significant challenge.&lt;/p&gt;
&lt;p&gt;One of the most common conflicts is with the command &lt;code&gt;set-mark-command&lt;/code&gt;, which
default binding is &lt;code&gt;C-SPC~(Ctrl+Space)&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;. On Windows, &lt;code&gt;Ctrl+Space&lt;/code&gt; is
often used to toggle between English and Chinese input methods, which can make&lt;code&gt;Ctrl+Space&lt;/code&gt; unusable for marking in Emacs.&lt;/p&gt;
&lt;p&gt;To resolve this issue, you can either use the alternative binding for&lt;code&gt;set-mark-command&lt;/code&gt;, &lt;code&gt;C-@&lt;/code&gt;, or disable the &lt;code&gt;Ctrl+Space&lt;/code&gt; functionality in
Windows. Additionally, since the spacebar can
be operated easily with either thumb, there is a &amp;ldquo;third option&amp;rdquo;: you can
configure the &lt;code&gt;Ctrl+Space&lt;/code&gt; so that one side &lt;code&gt;Ctrl+Space&lt;/code&gt; is reserved for
Windows, while the other side &lt;code&gt;Ctrl+Space&lt;/code&gt; is available for Emacs or other
applications. This is the solution I adopted because it allows me to
maintain my habit of using both thumbs for operation.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Emacs comes with numerous default keybindings, which inevitably conflict with
system-level shortcuts.  For Emacs beginners, resolving these conflicts can be a
significant challenge.</p>
<p>One of the most common conflicts is with the command <code>set-mark-command</code>, which
default binding is <code>C-SPC~(Ctrl+Space)</code><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.  On Windows, <code>Ctrl+Space</code> is
often used to toggle between English and Chinese input methods, which can make<code>Ctrl+Space</code> unusable for marking in Emacs.</p>
<p>To resolve this issue, you can either use the alternative binding for<code>set-mark-command</code>, <code>C-@</code>, or disable the <code>Ctrl+Space</code> functionality in
Windows.  Additionally, since the spacebar can
be operated easily with either thumb, there is a &ldquo;third option&rdquo;: you can
configure the <code>Ctrl+Space</code> so that one side <code>Ctrl+Space</code> is reserved for
Windows, while the other side <code>Ctrl+Space</code> is available for Emacs or other
applications.  This is the solution I adopted because it allows me to
maintain my habit of using both thumbs for operation.</p>
<p>In the latest version of Windows 11, you can achieve this as follows:</p>
<ol>
<li>
<p>Go to <code>Settings &gt; Time &amp; Language &gt; Language &amp; region &gt; Options &gt; Microsoft Pinyin &gt; Keys</code>, and uncheck the <code>Ctrl + Space</code> box while leaving <code>Shift</code>
checked.<img loading="lazy" src="/ox-hugo/disable_Ctrl+Space.png"></p>
</li>
<li>
<p>Open PowerToys (install it if you don&rsquo;t already have it). In the <code>Keyboard Manager</code> section, add a key remapping: map <code>Ctrl(Left) + Space</code> to <code>Shift</code> or<code>Win(Left) + Space</code>.<img loading="lazy" src="/ox-hugo/remap_shortcuts.png"></p>
</li>
</ol>
<p>For older versions of Windows, where there&rsquo;s a UI bug preventing such
changes <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, you can solve this by manually editing the registry:</p>
<ol>
<li>Navigate to <code>HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000010</code>. Modify the value of <code>Key Modifiers</code> to <code>02 80 00 00</code>, or <code>02 40 00 00</code> <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</li>
<li>If you want to apply this change for all new users, make the same
modification under <code>HKEY_USERS\.DEFAULT\Control Panel\Input Method\Hot Keys\00000010</code>.</li>
</ol>
<p>After making these changes, restart your computer to take effect.</p>
<p>It seems that only <code>Ctrl+Space</code> can be “split,” as other key combinations are
naturally easier to reach with one hand. For example, <code>Ctrl+a</code> inherently implies<code>Right Ctrl+a</code>.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Emacs uses unique convention for keybinngs, where <code>C-SPC</code> is shorthand for<code>Ctrl+Space</code>.  This article adopts the common convention for now.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://superuser.com/questions/327479/ctrl-space-always-toggles-chinese-ime-windows-7">https://superuser.com/questions/327479/ctrl-space-always-toggles-chinese-ime-windows-7</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>02 indicates Ctrl, 80 indicates the left side, and 40 indicates the right side.<a href="https://learn.microsoft.com/en-us/windows/win32/tsf/tf-mod--constants">https://learn.microsoft.com/en-us/windows/win32/tsf/tf-mod--constants</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Swapping Ctrl and Alt Keys</title><link>https://victorhge.github.io/posts/swap_ctrl_alt/</link><pubDate>Wed, 25 Feb 2026 20:59:00 +0800</pubDate><guid>https://victorhge.github.io/posts/swap_ctrl_alt/</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://victorhge.github.io/ox-hugo/lisp-machine-keyboard-2.jpg"/&gt;
&lt;/figure&gt;
&lt;p&gt;This is an essential configuration for all the computers I use, all because of
Emacs.&lt;/p&gt;
&lt;p&gt;Emacs was originally developed as a set of macros for the TECO editor (&lt;a href="https://blog.djmnet.org/2008/08/05/origin-of-emacs/"&gt;Editing
MACroS&lt;/a&gt;). At that time, the keyboard layout used by the developers placed the
Ctrl key next to the spacebar&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;, making it convenient for operation with
the thumbs. For some reason, standard keyboards that became widespread with
personal computers moved the Ctrl key to the outermost position, which forces
usage with the pinky finger. This design easily fatigues the pinky.&lt;/p&gt;</description><content:encoded><![CDATA[<figure>
    <img loading="lazy" src="/ox-hugo/lisp-machine-keyboard-2.jpg"/> 
</figure>

<p>This is an essential configuration for all the computers I use, all because of
Emacs.</p>
<p>Emacs was originally developed as a set of macros for the TECO editor (<a href="https://blog.djmnet.org/2008/08/05/origin-of-emacs/">Editing
MACroS</a>). At that time, the keyboard layout used by the developers placed the
Ctrl key next to the spacebar<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, making it convenient for operation with
the thumbs. For some reason, standard keyboards that became widespread with
personal computers moved the Ctrl key to the outermost position, which forces
usage with the pinky finger. This design easily fatigues the pinky.</p>
<p>Therefore, I choose to swap the Ctrl and Alt keys, returning the Ctrl key
to a thumb-operable position, alleviating pinky strain and significantly
improving efficiency.</p>
<p>Here’s how I do it:</p>
<ul>
<li>Windows: Using <a href="https://github.com/randyrants/sharpkeys">SharpKeys</a> for key remapping.</li>
<li>Linux (GNOME desktop): GNOME Tweak Tool makes this easy to configure<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</li>
</ul>
<p>This is a &ldquo;once-you-use-it-you-can&rsquo;t-go-back&rdquo; configuration.  It also has a&lsquo;hidden feature&rsquo; - driving others crazy when they try to use my keyboard.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Knight Keyboard <a href="http://xahlee.info/kbd/knight_keyboard.html">http://xahlee.info/kbd/knight_keyboard.html</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>GNOME Treak Tool <a href="https://askubuntu.com/questions/885045/how-to-swap-ctrl-and-alt-keys-in-ubuntu-16-04/885047">https://askubuntu.com/questions/885045/how-to-swap-ctrl-and-alt-keys-in-ubuntu-16-04/885047</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>