<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Digital technology &#8211; Henry Poon&#039;s Blog</title>
	<atom:link href="https://blog.henrypoon.com/blog/tag/digital-technology/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.henrypoon.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 Oct 2022 22:11:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
<site xmlns="com-wordpress:feed-additions:1">83044199</site>	<item>
		<title>Jenkins pipeline for Spring with beta and prod stages and deployment rollback</title>
		<link>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/</link>
					<comments>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Thu, 09 Mar 2017 08:04:51 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Apache Ant]]></category>
		<category><![CDATA[Apache Maven]]></category>
		<category><![CDATA[Build automation]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Compiling tools]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Const]]></category>
		<category><![CDATA[Continuous integration]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Hole]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java enterprise platform]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Rolling]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Scripting languages]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[URL]]></category>
		<category><![CDATA[Variable]]></category>
		<category><![CDATA[Z]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">https://blog.henrypoon.com/?p=2614</guid>

					<description><![CDATA[In the past couple of days, I&#8217;ve been experimenting a bit with the Jenkins pipeline plugin to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In the past couple of days, I&#8217;ve been experimenting a bit with the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin" target="_blank" rel="noopener">Jenkins pipeline plugin</a> to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time to Google my way through how to do everything, so I figure I just lay it all out here in case it helps other people do the same thing.</p>



<p class="wp-block-paragraph">The nice thing about all of this is that I can push a code change to git, and Jenkins can build it, run through all the tests and then deploy to production automatically.</p>



<h1 class="wp-block-heading">Layout of a pipeline script</h1>



<p class="wp-block-paragraph">Pipeline scripts are written in <a rel="noopener" href="http://www.groovy-lang.org/" target="_blank">Groovy</a>, which is a variant of Java. In general, a pipeline script is laid out like this:</p>



<pre class="wp-block-code"><code lang="python" class="language-python">node {
    def SOME_CONSTANT = "whatever"
    ...

    stage('some stage name like Build') {
        // Stuff to do as a part of this stage
    }

    stage('another stage') {
        // More stuff
    }

    ...
}</code></pre>



<p class="wp-block-paragraph">Each stage represents a stage in the pipeline (e.g. building, beta deployment, prod deployment etc.)</p>



<h1 class="wp-block-heading">Defining some constants</h1>



<p class="wp-block-paragraph">First, a list of constants can be defined that can be used throughout the pipeline so that if the pipeline script gets reused somewhere, only these constants have to be changed. I&#8217;m not aware of anything that lets me reuse a pipeline in Jenkins without copying and pasting the code somewhere else so for now I&#8217;ll have to live with copying and pasting.</p>



<p class="wp-block-paragraph">My project uses Maven so I got Jenkins to download its own copy of Maven that it can use to execute builds and have defined it as a constant. The name I&#8217;ve given it in the Jenkins Global Tool Configuration is &#8220;Maven 3.3.9&#8221; exactly. My project also uses Tomcat so there are some Tomcat specific things in there that may or may not be relevant to your use case.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def MAVEN_HOME = tool 'Maven 3.3.9'
    def WORKSPACE = pwd()

    def PROJECT_NAME = "name-of-project"
    def WAR_PATH_RELATIVE = "App/target/${PROJECT_NAME}.war"
    def WAR_PATH_FULL = "${WORKSPACE}/${WAR_PATH_RELATIVE}"
    def TOMCAT_CTX_PATH_BETA = "Tomcat-context-path-for-the-beta-stage"
    def TOMCAT_CTX_PATH_PROD = "Tomcat-context-path-for-the-prod-stage"
    def GIT_REPO_URL = "URL-to-git-repo-ending-in-.git"</code></pre>



<h1 class="wp-block-heading">Preparation Stage</h1>



<p class="wp-block-paragraph">First, the code has to be retrieved from the repository before it gets built. Jenkins allows storing username/password pairs so that they can be referenced without having to write out the password in plaintext. Jenkins uses a &#8220;credential ID&#8221; for this.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Preparation') {
        git branch: "master",
        credentialsId: "credentials-ID-stored-in-Jenkins-that-can-access-the-git-repo",
        url: "${GIT_REPO_URL}"
    }</code></pre>



<h1 class="wp-block-heading">Build Stage</h1>



<p class="wp-block-paragraph">Next, the code must be built and unit tested. &#8220;mvn clean install&#8221; will do just that (depending on what you want, you can always put in a different maven goal). The junit command is just there to take the resulting XML that gets generated during the build process and posts a graph of how many tests were run for each build.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Build') {
        sh "'${MAVEN_HOME}/bin/mvn' clean install"
        junit '**/target/surefire-reports/TEST-*.xml'
    }
</code></pre>



<h1 class="wp-block-heading">Beta Stage</h1>



<p class="wp-block-paragraph">Once the build succeeds, you&#8217;ll want to deploy it to a beta environment, so integration tests can happen. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (more on that later)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and fail the build</li><li>If the deployment succeeds, run the integration tests (the command to do this may differ based on use case)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Beta') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_BETA,
                        env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_BETA} but context failed to start")) {
                    echo "----- Beta deployment log -----"
                    echo output
                    echo "-------------------------------"
                    currentBuild.result = 'FAILURE'
                    error "Beta stage deployment failure"
                }
            }

        echo "Running integration tests"
        sh "'${MAVEN_HOME}/bin/mvn' -Dtest=*IT test"
        junit '**/target/surefire-reports/TEST-*.xml'
    }</code></pre>



<p class="wp-block-paragraph">The deploy method is what takes care of the actual deployment to Tomcat, which is how the Jenkins build tells Tomcat about the newly built war file. The deploy method is below (be sure to change the server IP and port). Alternatively, I could have built my project as an embedded jar file, but that has a different challenge in figuring out how to get Jenkins to tell the OS to execute the newly built jar file as a particular user.</p>



<ol class="wp-block-list"><li>Based on the Tomcat context path, decide whether a beta or production deployment is happening</li><li>Make a copy of the build war file and add .prod or .beta to the end of it so as to keep the original</li><li>Set the Spring profile to use on the newly copied war file (more on that later)</li><li>Call the curl command to do the actual deployment to Tomcat (more on that later)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">def deploy(warPathFull, tomcatCtxPath, username, password) {
    def envSuffix = ""
    def isBeta = tomcatCtxPath.contains("beta")
    if (isBeta) {
        envSuffix = "beta"
    } else {
        envSuffix = "prod"
    }
    sh script: "cp ${warPathFull} ${warPathFull}.${envSuffix}" 
    setSpringProfile(warPathFull, isBeta)
    def output = sh script: "curl --upload-file '${warPathFull}.${envSuffix}' " +
            "'http://${username}:${password}@localhost:8081/manager/text/deploy" + 
            "?path=/${tomcatCtxPath}&amp;update=true'", returnStdout: true
    return output
}</code></pre>



<p class="wp-block-paragraph">In the case of my project, I&#8217;m building a single war file that does not have a Spring profile (beta/prod) defined. This means that I have to manually define this before I deploy the app to Tomcat since there are some things that differ between beta and prod like database URL&#8217;s. To do this, I wrote a method that opens the war file like a zip (jar/war files are zip files) and adds a line to my application.properties to define a Spring profile.</p>



<p class="wp-block-paragraph">Admittedly, doing this zip file manipulation seems kind of hacky. Alternatively, I could have defined my build such that I had a separate beta build and a prod build to avoid modifying the zip file, but the drawback is that I&#8217;d then have to build my code twice.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def setSpringProfile(warPathFull, isBeta) {
    def zipFileFullPath = warPathFull + "." + (isBeta ? "beta" : "prod")
    def zipIn = new File(zipFileFullPath)
    def zip = new ZipFile(zipIn)
    def zipTemp = File.createTempFile("temp_${System.nanoTime()}", 'zip')
    zipTemp.deleteOnExit()
    def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
    def toModify = "WEB-INF/classes/application.properties"

    for(e in zip.entries()) {
        if(!e.name.equalsIgnoreCase(toModify)) {
            zos.putNextEntry(e)
            zos &lt;&lt; zip.getInputStream(e).bytes
        } else {
            zos.putNextEntry(new ZipEntry(toModify))
            zos &lt;&lt; zip.getInputStream(e).bytes
            zos &lt;&lt; ("\nspring.profiles.active=" + (isBeta ? "beta" : "prod")).bytes
        }
        zos.closeEntry()
    }

    zos.close()
    zipIn.delete()
    zipTemp.renameTo(zipIn)
}</code></pre>



<p class="wp-block-paragraph">A curl command to Tomcat is what actually does the deployment. To deploy a file to Tomcat, do the following below. This will deploy the war file to Tomcat and instantly run it, thus it will be accessible at the given context path.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">curl --upload-file 'path-to-war-file' http://username:password@server-address:port/manager/text/deploy?path=/tomcat-context-path&amp;update=true</code></pre>



<h1 class="wp-block-heading">Prod Stage</h1>



<p class="wp-block-paragraph">The same kind of stuff happens in the prod stage as in the beta stage with a few exceptions. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (except this time it is prod)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and roll back the deployment</li><li>If the deployment succeeds, save the build files, and then the pipeline is finished. Alternatively, smoke tests can be run at this point, but I did not implement this in my project</li></ol>



<p class="wp-block-paragraph">Rollback is important because if the deployment fails, you don&#8217;t want to be stuck with a broken environment. Since build artifacts are saved on successful deployments, these same artifacts can be brought back if future deployments fail. This means they can be redeployed so that the code can be fixed before another deployment happens.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Prod') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_PROD} but context failed to start")) {
                    echo "Prod stage deployment failure, rolling back deployment"
                    echo "----- Prod deployment log -----"
                    echo output
                    echo "-------------------------------"
                    step([$class: 'CopyArtifact',
                            filter: "${WAR_PATH_RELATIVE}",
                            fingerprintArtifacts: true,
                            projectName: "${PROJECT_NAME}",
                            target: "${WAR_PATH_RELATIVE}.rollback"])
                    deploy(WAR_PATH_FULL + ".rollback/" + WAR_PATH_RELATIVE,
                            TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                    currentBuild.result = 'FAILURE'
                    error "Prod deployment rolled back"
                } else {
                    archiveArtifacts artifacts: "${WAR_PATH_RELATIVE}*", fingerprint: true
                }
            }
    }
</code></pre>



<p class="wp-block-paragraph">At the end you get to have something like this:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="600" height="882" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2017/03/JenkinsPipeline.png?resize=600%2C882&#038;ssl=1" alt="" class="wp-image-2638"/></figure>
</div>


<p class="wp-block-paragraph">That pretty much sums up the whole Jenkins pipeline that I&#8217;ve been using lately for Spring projects!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2614</post-id>	</item>
		<item>
		<title>Groovy/Grails unable to resolve class &#8211; even if the class is in the same package</title>
		<link>https://blog.henrypoon.com/blog/2015/01/26/groovygrails-unable-to-resolve-class-even-if-the-class-is-in-the-same-package/</link>
					<comments>https://blog.henrypoon.com/blog/2015/01/26/groovygrails-unable-to-resolve-class-even-if-the-class-is-in-the-same-package/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 27 Jan 2015 06:44:33 +0000</pubDate>
				<category><![CDATA[gaming]]></category>
		<category><![CDATA[Apache Groovy]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Cross-platform software]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[Integrated development environments]]></category>
		<category><![CDATA[ise]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Java platform]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Writing]]></category>
		<guid isPermaLink="false">https://www.henrypoon.com/blog/?p=2019</guid>

					<description><![CDATA[The Problem Every now and then I get this annoying problem in GGTS (Grails/Groovy Tool Suite &#8211; Version 3.6.2.RELEASE at the time of this writing), where the IDE just complains about how it can&#8217;t resolve a class. &#160;The weird thing is that the file that the IDE is complaining about is in the same package [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>The Problem</h1>
<p>Every now and then I get this annoying problem in GGTS (Grails/Groovy Tool Suite &#8211; Version 3.6.2.RELEASE at the time of this writing), where the IDE just complains about how it can&#8217;t resolve a class. &nbsp;The weird thing is that the file that the IDE is complaining about is in the same package as the class that I&#8217;m trying to use. &nbsp;It built before, and the source hadn&#8217;t changed &#8211; so clearly this should not be happening.</p>
<h1>The Fix</h1>
<p>Hitting the Clean button on the Eclipse side (Project -&gt; Clean) seems to make the errors go away.</p>
<p>This apparently has been a problem since June 2010 (forum post reference <a href="http://forum.spring.io/forum/spring-projects/springsource-tool-suite/83417-groovy-unable-to-resolve-class-although-same-package-again" target="_blank" rel="noopener noreferrer">here</a>), so I&#8217;m surprised that it is still an issue in the current version.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2015/01/26/groovygrails-unable-to-resolve-class-even-if-the-class-is-in-the-same-package/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2019</post-id>	</item>
		<item>
		<title>Disabling Mouse Acceleration in Ubuntu</title>
		<link>https://blog.henrypoon.com/blog/2015/01/25/disabling-mouse-acceleration-in-ubuntu/</link>
					<comments>https://blog.henrypoon.com/blog/2015/01/25/disabling-mouse-acceleration-in-ubuntu/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Sun, 25 Jan 2015 08:31:32 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[AWK]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computer mice]]></category>
		<category><![CDATA[Computer mouse]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Counter-Strike]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[DirectInput]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mass]]></category>
		<category><![CDATA[mouse acceleration]]></category>
		<category><![CDATA[Plan]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Programming languages]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Sleep]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Trac]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Windows]]></category>
		<guid isPermaLink="false">https://www.henrypoon.com/blog/?p=1955</guid>

					<description><![CDATA[I&#8217;ve been quite accustomed to disabling mouse acceleration on my Windows machine (thanks to playing massive amounts of Counter-Strike back in the day), but now that I&#8217;ve started to use Linux a bit more, I&#8217;ve found that disabling mouse acceleration was not as easy as in Windows. Script I&#8217;ve managed to produce a script to [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I&#8217;ve been quite accustomed to disabling mouse acceleration on my Windows machine (thanks to playing massive amounts of Counter-Strike back in the day), but now that I&#8217;ve started to use Linux a bit more, I&#8217;ve found that disabling mouse acceleration was not as easy as in Windows.</p>



<h1 class="wp-block-heading">Script</h1>



<p class="wp-block-paragraph">I&#8217;ve managed to produce a script to disable mouse acceleration (works for me on Ubuntu 14.04).  However, this script needs to be run every time the computer boots because the settings don&#8217;t stay.  Here is the script:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">#wait for the desktop to settle
sleep 5

#gets the hardware id's of all mice plugged into the system
hardwareIds=$(xinput | grep -i mouse | awk '{print substr($(NF-3),4)}')

#turn off mouse acceleration
for i in $hardwareIds
do
xinput set-prop ${i} 'Device Accel Profile' -1
xinput set-prop ${i} 'Device Accel Velocity Scaling' 1
done</code></pre>



<h1 class="wp-block-heading">Explanation</h1>



<p class="wp-block-paragraph">The script works by extracting the hardware id&#8217;s of the mice that are connected to the system and then applying properties to them that disable mouse acceleration for that device.  The extraction of the mouse hardware id&#8217;s are done with this:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">#gets the hardware id's of all mice plugged into the system
hardwareIds=$(xinput | grep -i mouse | awk '{print substr($(NF-3),4)}')</code></pre>



<p class="wp-block-paragraph">Calling xinput in the Terminal will list all the connected input devices, which is grepped (case insensitively) for the word &#8220;mouse&#8221;, which gives something like this on my machine:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>⎜ ↳ Logitech G500s Laser Gaming Mouse id=14 [slave pointer (2)]<br>⎜ ↳ Logitech G500s Laser Gaming Mouse id=15 [slave pointer (2)]</p></blockquote>



<p class="wp-block-paragraph">The call to awk extracts the hardware id&nbsp;from those two lines (14, 15 in the above case) and stores them in an array that is iterated through when setting the mouse properties.</p>



<h1 class="wp-block-heading">Reference</h1>



<p class="wp-block-paragraph">This is the website that showed me how to disable mouse acceleration to begin with:&nbsp;<a href="http://ubuntuforums.org/showthread.php?t=1734400" target="_blank" rel="noopener noreferrer">http://ubuntuforums.org/showthread.php?t=1734400</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2015/01/25/disabling-mouse-acceleration-in-ubuntu/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1955</post-id>	</item>
		<item>
		<title>Proof of the Farthest-in-Future Optimal Caching Algorithm</title>
		<link>https://blog.henrypoon.com/blog/2014/02/02/proof-of-the-farthest-in-future-optimal-caching-algorithm/</link>
					<comments>https://blog.henrypoon.com/blog/2014/02/02/proof-of-the-farthest-in-future-optimal-caching-algorithm/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Sun, 02 Feb 2014 23:19:13 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[All That]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Cache replacement policies]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Comment]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computer architecture]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Contents]]></category>
		<category><![CDATA[CPU cache]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[farthest-first]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[greedy algorithms]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[optimal caching]]></category>
		<category><![CDATA[Outside]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[tuna]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/proof-of-the-farthest-in-future-optimal-caching-algorithm</guid>

					<description><![CDATA[This topic came up in one of my lectures and I found it a little challenging to understand the proof so I thought I&#8217;d write it down as best as I could explain it so that I could understand it better and possibly help other people understand it better. &#160;Feel free to comment/ask questions/correct me, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This topic came up in one of my lectures and I found it a little challenging to understand the proof so I thought I&#8217;d write it down as best as I could explain it so that I could understand it better and possibly help other people understand it better. &nbsp;Feel free to comment/ask questions/correct me, etc.</p>
<p>In a computer, there are various methods of storing information. &nbsp;Information can be stored in the processor cache, RAM, hard disk, etc. &nbsp;It can be faster to request information from a storage medium that is smaller. &nbsp;However, this smaller storage medium cannot fit all the possible information that can be requested. &nbsp;So the idea is to insert a portion of the data into the faster, smaller medium (the <strong>cache</strong>) and the rest into the slower, larger medium (<strong>main memory)</strong>.</p>
<p>If a request is made and the data is not available in the faster, smaller medium first, then the data will be read from the slower, larger medium &#8211; this is what is known as a <strong>cache miss</strong>.</p>
<p>Given that all the data cannot possibly live in the cache, there must be a way to minimize the amount of times that the data must be read from the main memory.</p>
<h1>Optimal Caching &#8211; Farthest-in-Future</h1>
<h2>The Algorithm</h2>
<p>The idea is that there is an algorithm that minimizes the amount of cache misses that occur for a set of requests. &nbsp;The <em>Farthest-in-Future Algorithm&nbsp;</em>evicts the item in the cache that is not requested until the farthest in the future. &nbsp;For example, given the following cache with items &#8220;a&#8221; through &#8220;f&#8221;.</p>
<table>
<tbody>
<tr>
<td>Cache Items</td>
<td>a b c d e f</td>
</tr>
<tr>
<td>Future Queries</td>
<td>g a b c e d a b b f</td>
</tr>
</tbody>
</table>
<p><span style="line-height:1.5em;">It is clear that &#8220;g&#8221; does not exist in the set of cache items and so when &#8220;g&#8221; is requested, a cache miss will result. An item will be evicted because &#8220;g&#8221; is not in the cache. &nbsp;According to the </span><em style="line-height:1.5em;">Farthest-in-Future Algorithm</em><span style="line-height:1.5em;">, element &#8220;f&#8221; will be evicted since it is the one that will be used furthest in the future.</span></p>
<h2>Definitions</h2>
<p><strong>Cache Miss</strong> &#8211; Occurs when it is necessary to bring in an item from the main memory into the cache</p>
<p><strong>Schedule</strong>&nbsp;&#8211; A list that contains, for each, request, which item is brought into the cache, and which item is evicted</p>
<p><strong>Reduced Schedule</strong> &#8211; a schedule that only brings in an item when there is a request for that item &#8211; so a non-reduced schedule would bring an item into the cache outside of a request for that item</p>
<h2>Theorem</h2>
<p>To be shown:</p>
<blockquote><p><em>Farthest-in-Future</em> is the optimal algorithm that minimizes the number of cache misses.</p></blockquote>
<p>To prove this, let&#8217;s say there is a schedule SFF&nbsp;that follows the&nbsp;<em>Farthest-in-Future Algorithm</em>&nbsp;and that there is a schedule optimal S<sup><em></sup>&nbsp;that has a minimum number of cache misses. It can be shown that it is possible to transform&nbsp;S<sup></em></sup>&nbsp;into SFF&nbsp;by performing a series of evictions without increasing the number of cache misses. &nbsp;Since&nbsp;S<sup>*</sup>&nbsp;is already optimal, and the number of cache misses did not increase, then SFF&nbsp;must be optimal.</p>
<p>To perform one transformation, the statement below can be used. &nbsp;Right now, it isn&#8217;t all that clear why this is necessary, but it should become clearer further on.</p>
<blockquote><p>Let S&nbsp;be a reduced schedule that is the same as SFF&nbsp;for the first j requests, then there is a reduced schedule S&#8217;&nbsp;that is the same as SFF&nbsp;for the first j+1 requests, and incurs no more misses than S</p></blockquote>
<h2>Proof</h2>
<p>Let&#8217;s say the cache at the start looks like this. &nbsp;S and SFF&nbsp;have the exact same contents (this is what was defined in the previous section).</p>
<table>
<tbody>
<tr>
<td>S</td>
<td>a b c d</td>
</tr>
<tr>
<td>SFF</td>
<td>a b c d</td>
</tr>
</tbody>
</table>
<p><span style="line-height:1.5em;">Given a schedule S, it can be shown that any request can be made, and the resulting schedule would be equal to the ideal algorithm and does not increase the number of cache misses. &nbsp;Essentially, we want S = S&#8217; = SFF&nbsp;after a request is made and that the number of cache misses have not increased. &nbsp;If this can be shown for all different scenarios that items are requested, then&nbsp;</span><em style="line-height:1.5em;">Farthest-in-Future</em><span style="line-height:1.5em;"> is the ideal algorithm.</span></p>
<h3>Case 1: Item Is Already in the Cache</h3>
<p>Now let&#8217;s say the next item to be requested is item &#8220;d&#8221;. &nbsp;It is clear that this item exists in both caches and no evictions are necessary. &nbsp;Since no evictions are necessary, SFF&nbsp;does not change. &nbsp;It was specified in a prior section that there is a schedule S&#8217; that equals SFF, which incurs no more misses than S.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>a b c d</td>
<td>Read&nbsp;d</td>
</tr>
<tr>
<td>S</td>
<td>a b c d</td>
<td>Read&nbsp;d</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>a b c d</td>
<td>Read&nbsp;d</td>
</tr>
</tbody>
</table>
<p>Here, S = S&#8217; because no changes had to be made to the cache and there were no cache misses. &nbsp;After the request for item &#8220;d&#8221;, S = S&#8217;, each with zero cache misses, which is a valid outcome.</p>
<h3>Case 2: Item Is Not in the Cache, S and SFF&nbsp;Evict the Same Item</h3>
<p>Let&#8217;s say the next item to be requested is item &#8220;e&#8221;. &nbsp;Neither cache has this item, so an eviction will have to be made. &nbsp;Let&#8217;s also say SFF&nbsp;and S both choose to evict item &#8220;a&#8221; to make room for &#8220;e&#8221;. &nbsp;It was specified in a prior section that there is a schedule S&#8217; that equals SFF, which incurs no more misses than S.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>b c d e</td>
<td>Evict a; Read e</td>
</tr>
<tr>
<td>S</td>
<td>b c d e</td>
<td>Evict a; Read e</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>b c d e</td>
<td>Evict a; Read e</td>
</tr>
</tbody>
</table>
<p>Here S = S&#8217; because S and SFF&nbsp;both evicted the same item. &nbsp;Both S and S&#8217; each have one cache miss (no increase relative to one another), which is a valid outcome.</p>
<h3>Case 3: Item Is Not in the Cache, S and SFF&nbsp;Each Evict A Different Item</h3>
<p>This is where the proof can become more confusing (as if it isn&#8217;t already). &nbsp;Let&#8217;s say the next item to be requested is &#8220;e&#8221;. &nbsp;Let&#8217;s also say that the ideal algorithm, SFF, evicts &#8220;a&#8221; and S evicts &#8220;b&#8221;.&nbsp;It was specified in a prior section that there is a schedule S&#8217; that equals SFF, which incurs no more misses than S. This means that in order to get S&#8217; = SFF, S&#8217; should evict &#8220;a&#8221; in order to match with SFF.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>b c d e</td>
<td>Evict a; Insert&nbsp;e</td>
</tr>
<tr>
<td>S</td>
<td>a c d e</td>
<td>Evict b; Insert&nbsp;e</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>b c d e</td>
<td>Evict a; Insert&nbsp;e</td>
</tr>
</tbody>
</table>
<p>Here, S does not agree with&nbsp;S&#8217; = SFF. &nbsp;Essentially, these two schedules behave the same, so long as future requests do not request items &#8220;a&#8221; or &#8220;b&#8221;. &nbsp;This shows that there is a schedule S&#8217; that equals SFF, but it is not known whether or not S&#8217; has no more cache misses than S, since &#8220;a&#8221; or &#8220;b&#8221; can be requested in the future, which can determine whether S or S&#8217; has more cache misses. &nbsp;From this point onward, S and S&#8217; behave the same until one of the following happens:</p>
<h4>Case 3a: Item Is in SFF, But Not S; S Evicts &#8220;a&#8221;</h4>
<p>Let&#8217;s say eventually item &#8220;b&#8221; gets requested. &nbsp;In this case, S&#8217; and SFF do not need to change. &nbsp;All S has to do is evict &#8220;a&#8221; to make room for &#8220;b&#8221;. &nbsp;In this case, S has two total cache misses (from request &#8220;e&#8221; and &#8220;b&#8221;), while SFF and S&#8217; each have only one cache miss, thus fulfilling the cache miss requirement.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>b c d e</td>
<td>Insert&nbsp;b</td>
</tr>
<tr>
<td>S</td>
<td>b c d e</td>
<td>Evict a; Insert&nbsp;b</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>b c d e</td>
<td>Insert&nbsp;b</td>
</tr>
</tbody>
</table>
<h4>Case 3b: Item Is Neither in SFF Nor S</h4>
<p>Let&#8217;s say eventually item &#8220;f&#8221; gets requested. &nbsp;S&#8217;, SFF, and S all need to make an eviction. S&#8217; and SFF can evict &#8220;b&#8221; to make room for &#8220;f&#8221;, and S can evict &#8220;a&#8221; to make room for &#8220;f&#8221;. &nbsp;In this case, each schedule as two cache misses, thus fulfilling the cache miss requirement.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>c d e f</td>
<td>Evict b; Insert&nbsp;f</td>
</tr>
<tr>
<td>S</td>
<td>c d e f</td>
<td>Evict a; Insert&nbsp;f</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>c d e f</td>
<td>Evict b; Insert&nbsp;f</td>
</tr>
</tbody>
</table>
<h4>Case 3c: Item Is in SFF, But Not S; S Evicts Item Not Equal to &#8220;a&#8221;</h4>
<p>Let&#8217;s say eventually item &#8220;b&#8221; gets requested and S evicts an item that isn&#8217;t &#8220;a&#8221;, say &#8220;c&#8221;. &nbsp;Now, SFF and S&#8217; both already have &#8220;b&#8221; in the cache. &nbsp;In order to synchronize S and S&#8217; to make them comparable to see how many cache misses each have, S&#8217; and SFF will evict &#8220;c&#8221; to make room for &#8220;a&#8221;.</p>
<table>
<tbody>
<tr>
<td>SFF</td>
<td>a b d e</td>
<td>Evict c; Insert a</td>
</tr>
<tr>
<td>S</td>
<td>a b d e</td>
<td>Evict c; Insert&nbsp;b</td>
</tr>
<tr>
<td>S&#8217;</td>
<td>a b d e</td>
<td>Evict c; Insert&nbsp;a</td>
</tr>
</tbody>
</table>
<p>Since &#8220;a&#8221; is being brought into the cache without a request for &#8220;a&#8221;, this makes S&#8217; and SFF no longer a reduced schedule. &nbsp;However, the proof calls for S&#8217; and SFF being a reduced schedule. &nbsp;Fortunately, it is possible to transform an unreduced schedule into a reduced one. &nbsp;In this case, each schedule has two cache misses, thus fulfilling the cache miss requirement.</p>
<h4>Case 3d: Item Is Not in SFF, But in S</h4>
<p>The only item that is in S and not SFF is item &#8220;a&#8221;. &nbsp;SFF had evicted it initially at the beginning of Case 3. &nbsp;Since SFF had evicted it, it must have been the item that would be requested furthest into the future. &nbsp;Therefore, it is not possible for item &#8220;a&#8221; to be requested before other items.</p>
<p>&nbsp;</p>
<p>After going through all possible eviction decisions that the schedules can do, it was shown that for each scenario, there was indeed a schedule S&#8217; = SFF, where the cache misses incurred in S&#8217; no more than S.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2014/02/02/proof-of-the-farthest-in-future-optimal-caching-algorithm/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1799</post-id>	</item>
		<item>
		<title>Removing the annoying Windows language hotkeys “Ctrl+Space”, “Shift+Space” etc. that toggles the full-width/half-width characters on the Chinese IME</title>
		<link>https://blog.henrypoon.com/blog/2012/01/03/removing-the-annoying-windows-language-hotkeys-ctrlspace-shiftspace-etc-that-toggles-the-full-widthhalf-width-characters-on-the-chinese-ime/</link>
					<comments>https://blog.henrypoon.com/blog/2012/01/03/removing-the-annoying-windows-language-hotkeys-ctrlspace-shiftspace-etc-that-toggles-the-full-widthhalf-width-characters-on-the-chinese-ime/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 03 Jan 2012 23:04:52 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[Click]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Control Panel]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[Family]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Hex]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[Input method]]></category>
		<category><![CDATA[Installation]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Keyboard shortcut]]></category>
		<category><![CDATA[Language]]></category>
		<category><![CDATA[Lie]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[Page]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[UNC]]></category>
		<category><![CDATA[User interface techniques]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows Registry]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/removing-the-annoying-windows-language-hotkeys-%e2%80%9cctrlspace%e2%80%9d-%e2%80%9cshiftspace%e2%80%9d-etc-that-toggles-the-full-widthhalf-width-characters-on-the-chinese-ime</guid>

					<description><![CDATA[There is a bug in Windows that prevents switching the hotkey of some of the language bar features.  The user is unable to change any of the hotkeys in the Advanced Key Settings page.  Some of the changed hotkeys revert to what they were before when the user tries to apply the changes.  Two keys [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">There is a bug in Windows that prevents switching the hotkey of some of the language bar features.  The user is unable to change any of the hotkeys in the Advanced Key Settings page.  Some of the changed hotkeys revert to what they were before when the user tries to apply the changes.  Two keys in particular, the “Ctrl+Space” and the “Shift+Space” key combinations are the most annoying.</p>



<p class="wp-block-paragraph">These two keys toggle the full-width (double-byte), and the half-width (single-byte&#8221;) character sets when typing with the Chinese IME.&nbsp; Full-width characters look like “ｔｈｉｓ “ while half-width is what people are normally used to.&nbsp; The default key combinations are easy to press by accident in situations such as capitalizing a title.&nbsp; Therefore, it is beneficial to remove this hotkey.</p>



<h1 class="wp-block-heading">Solution</h1>



<p class="wp-block-paragraph">Because changing the key settings manually through Windows does not work, one must go through the registry.&nbsp; The following fix applies to the current user that is logged in.&nbsp; Apply the following registry keys and then restart the computer.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Windows Registry Editor Version 5.00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys]</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000010]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000011]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000012]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000070]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000071]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000072]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000201]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000202]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p><p>[HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000203]<br>&#8220;Virtual Key&#8221;=hex:ff,00,00,00<br>&#8220;Key Modifiers&#8221;=hex:00,c0,00,00<br>&#8220;Target IME&#8221;=hex:00,00,00,00</p></blockquote>



<p class="wp-block-paragraph">In the registry, one can also navigate to “HKEY_CURRENT_USERControl PanelInput MethodHot Keys” and see a list of folders with names that have eight numbers in them with leading zeroes.&nbsp; Each folder here represents a particular hotkey related to an IME.&nbsp; Clicking on one of these folders will show data for these keys.</p>



<p class="wp-block-paragraph">Setting “Key Modifiers” to “00 c0 00 00” removes the use of the Ctrl and Alt key for the hotkey.<br>Setting “Virtual Key” to “ff 00 00 00” sets the key to nothing.<br>The key “Target IME” can be left as is.</p>



<p class="wp-block-paragraph">In the case of the “Shift+Space” hotkey, “Shift” is the key modifier and “Space” is the virtual key.</p>



<p class="wp-block-paragraph">It is unclear which folder corresponds to the key that toggles the character shape, therefore this fix is a blanket approach.</p>



<h1 class="wp-block-heading">If the Above Still Fails</h1>



<p class="wp-block-paragraph">Try combining the fix with an installation of Microsoft Office IME 2010, which can be downloaded here: <a href="http://www.microsoft.com/downloads/zh-tw/details.aspx?FamilyID=60984ecd-9575-411a-bd38-2294f17c4131&amp;displaylang=zh-tw" target="_blank" rel="noreferrer noopener">http://www.microsoft.com/downloads/zh-tw/details.aspx?FamilyID=60984ecd-9575-411a-bd38-2294f17c4131&amp;displaylang=zh-tw</a>.  Despite the name, it does not require Microsoft Office to be installed. After installing, apply the registry keys and restart.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2012/01/03/removing-the-annoying-windows-language-hotkeys-ctrlspace-shiftspace-etc-that-toggles-the-full-widthhalf-width-characters-on-the-chinese-ime/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1305</post-id>	</item>
		<item>
		<title>Running non-Unicode programs with multiple languages in Windows</title>
		<link>https://blog.henrypoon.com/blog/2011/12/30/running-non-unicode-programs-with-multiple-languages-in-windows/</link>
					<comments>https://blog.henrypoon.com/blog/2011/12/30/running-non-unicode-programs-with-multiple-languages-in-windows/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Fri, 30 Dec 2011 23:32:41 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[AppLocale]]></category>
		<category><![CDATA[Arial Unicode MS]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[Character encoding]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[Family]]></category>
		<category><![CDATA[Find]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[ise]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Language]]></category>
		<category><![CDATA[Languages]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Mojibake]]></category>
		<category><![CDATA[Question mark]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Struct]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[Unicode input]]></category>
		<category><![CDATA[UTF-8]]></category>
		<category><![CDATA[Variable]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows XP]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/running-non-unicode-programs-with-multiple-languages-in-windows</guid>

					<description><![CDATA[For those who are multi-lingual, they may find a need to install programs on their computer that are localised in different languages.&#160; While it is easy to go into the Windows language options and set a particular language for non-Unicode programs, this method does not work if more than one needs to run different non-Unicode [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">For those who are multi-lingual, they may find a need to install programs on their computer that are localised in different languages.&nbsp; While it is easy to go into the Windows language options and set a particular language for non-Unicode programs, this method does not work if more than one needs to run different non-Unicode programs in different languages.&nbsp; That means, if one uses Traditional Chinese as the non-Unicode language, programs using Simplified Chinese will not display properly!</p>



<p class="wp-block-paragraph">The following solution is proposed:</p>



<h1 class="wp-block-heading">Use Microsoft AppLocale</h1>



<p class="wp-block-paragraph">Microsoft AppLocale allows running a program using a particular language without changing the Windows language setting.&nbsp; That means, one can change between multiple languages on-the-fly for each program.</p>



<p class="wp-block-paragraph">According to Microsoft:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Unicode based platforms, such as Windows XP, emulate the language environment required to run non-Unicode applications by internally converting application&#8217;s non-Unicode text data to Unicode using a system-wide variable commonly called the system local (or language for non-Unicode applications). The language of the non-Unicode applications should be of the same script or family as the one defined by the system locale. Failing to meet this condition results in display of garbage characters in the UI of the application.</p></blockquote>



<p class="wp-block-paragraph">Download link</p>



<p class="wp-block-paragraph">Once downloaded, install and run it.&nbsp; Follow the instructions and choose what program that is to be run at the wanted language.&nbsp; If the correct language was chosen, the application should show the correct characters.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2011/12/30/running-non-unicode-programs-with-multiple-languages-in-windows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1284</post-id>	</item>
		<item>
		<title>Diagnosing the Source of Internet Connectivity Problems</title>
		<link>https://blog.henrypoon.com/blog/2010/12/30/diagnosing-the-source-of-internet-connectivity-problems/</link>
					<comments>https://blog.henrypoon.com/blog/2010/12/30/diagnosing-the-source-of-internet-connectivity-problems/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Thu, 30 Dec 2010 08:05:26 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[APT]]></category>
		<category><![CDATA[Broadband]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computer network]]></category>
		<category><![CDATA[Computer networking]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Dia]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Information and communications technology]]></category>
		<category><![CDATA[Internet access]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Light]]></category>
		<category><![CDATA[Logical link control]]></category>
		<category><![CDATA[Modem]]></category>
		<category><![CDATA[Net]]></category>
		<category><![CDATA[Networking hardware]]></category>
		<category><![CDATA[Over]]></category>
		<category><![CDATA[Router]]></category>
		<category><![CDATA[Server appliance]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Telecommunications]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Windows]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/diagnosing-the-source-of-internet-connectivity-problems</guid>

					<description><![CDATA[I created a nice little flowchart for people to diagnose their Internet connectivity problems.&#160; It’s pretty general and covers the most common problems.&#160; I tried to avoid lots of specific information since many Internet connectivity problems are not as straightforward as just following a flowchart. I didn’t really go into specifics as to what kind [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I created a nice little flowchart for people to diagnose their Internet connectivity problems.&nbsp; It’s pretty general and covers the most common problems.&nbsp; I tried to avoid lots of specific information since many Internet connectivity problems are not as straightforward as just following a flowchart.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2011/12/internetdiagnosisflowchart2.png" target="_blank" rel="noreferrer noopener"><img data-recalc-dims="1" decoding="async" width="789" height="617" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2011/12/internetdiagnosisflowchart2.png?resize=789%2C617" alt="" class="wp-image-1280" title="InternetDiagnosisFlowchart" srcset="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2011/12/internetdiagnosisflowchart2.png?w=789&amp;ssl=1 789w, https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2011/12/internetdiagnosisflowchart2.png?resize=300%2C235&amp;ssl=1 300w" sizes="(max-width: 789px) 100vw, 789px" /></a></figure>
</div>


<p class="wp-block-paragraph">I didn’t really go into specifics as to what kind of modem lights to look for because all modems are different.&nbsp; But they almost always will have an “Online” light.&nbsp; If that is off, then there is clearly a problem.</p>



<p class="wp-block-paragraph">Router lights are usually just a power light, the WAN and LAN lights.&nbsp; If the WAN light is off, it means the router has no access to the Internet.</p>



<p class="wp-block-paragraph">Each network adapter on the computer can be disabled and enabled by accessing “Network Connections” in Windows.&nbsp; That can be accessed by typing the name without the quotes in the address bar in any open Explorer window.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/12/30/diagnosing-the-source-of-internet-connectivity-problems/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">557</post-id>	</item>
		<item>
		<title>Installing RXTX for Serial Communication with Java</title>
		<link>https://blog.henrypoon.com/blog/2010/12/25/installing-rxtx-for-serial-communication-with-java/</link>
					<comments>https://blog.henrypoon.com/blog/2010/12/25/installing-rxtx-for-serial-communication-with-java/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Sun, 26 Dec 2010 05:41:03 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[64-bit computers]]></category>
		<category><![CDATA[64-bit computing]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Comment]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Computing platforms]]></category>
		<category><![CDATA[Cross-platform software]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Directory]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Installation]]></category>
		<category><![CDATA[ise]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java platform]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MATLAB]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[Operating systems]]></category>
		<category><![CDATA[Page]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Program Files]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming languages]]></category>
		<category><![CDATA[RAR]]></category>
		<category><![CDATA[Serial]]></category>
		<category><![CDATA[Serial communication]]></category>
		<category><![CDATA[Solaris]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Struct]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[tuna]]></category>
		<category><![CDATA[UNIX System V]]></category>
		<category><![CDATA[Wiki]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[X86]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/installing-rxtx-for-serial-communication-with-java</guid>

					<description><![CDATA[Java supports communication to serial ports, but not with its default installation.&#160; It requires an installation of an external library.&#160; Currently, two options exist for achieving serial communication: RXTX JavaComm Unfortunately, the current version of JavaComm does not support Windows, and only supports Solaris SPARC, Solaris x86, and Linux x86.&#160; Since I use none of [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Java supports communication to serial ports, but not with its default installation.&nbsp; It requires an installation of an external library.&nbsp; Currently, two options exist for achieving serial communication:</p>



<ul class="wp-block-list"><li><a href="http://rxtx.qbang.org/wiki/index.php/Main_Page" target="_blank" rel="noreferrer noopener">RXTX</a></li><li><a rel="noopener noreferrer" href="http://www.oracle.com/technetwork/java/index-jsp-141752.html" target="_blank">JavaComm</a></li></ul>



<p class="wp-block-paragraph">Unfortunately, the current version of JavaComm does not support Windows, and only supports Solaris SPARC, Solaris x86, and Linux x86.&nbsp; Since I use none of those operating systems, this article will only discuss how to install RXTX in Windows.</p>



<p class="wp-block-paragraph">UPDATE: 12 Sept 2011 – Thanks to a comment from Kurt Zoglmann, there are instructions on how to do this with a Mac!  I never tried this myself because I don’t have a Mac, but the procedures stated there look good to me (see <a href="#comments">comments</a>).</p>



<p class="wp-block-paragraph">A 32 and 64 bit version of the library exists. &nbsp; I&#8217;ve updated this article from when it was first published to include the new locations for where to download the libraries, but I have not gone through the installation of the libraries again, so I&#8217;m not surprised if the rest of the content on this page is outdated too.</p>



<p class="wp-block-paragraph">32-bit version: <a rel="noopener noreferrer" href="http://rxtx.qbang.org/wiki/index.php/Download" target="_blank">http://rxtx.qbang.org/wiki/index.php/Download</a><br>64-bit version: <a rel="noopener noreferrer" href="http://fizzed.com/oss/rxtx-for-java" target="_blank">http://fizzed.com/oss/rxtx-for-java</a></p>



<p class="wp-block-paragraph">To install the libraries (instructions from <a href="http://www.jcontrol.org/download/readme_rxtx_en.html" target="_blank" rel="noopener noreferrer">JControl</a>):</p>



<ol class="wp-block-list"><li>Copy rxtxSerial.dll to %JAVA_HOME%\bin, (%JAVA_HOME% is the folder where JRE is installed on your system; e.g. c:\Program Files\Java\j2re1.4.1_01)</li><li>Copy RXTXcomm.jar to %JAVA_HOME%\lib\ext</li></ol>



<p class="wp-block-paragraph">Once installed, the IDE will need to know where to look for these installed files.&nbsp; Even though the files exist in the JRE directory, each project needs to know about these files.&nbsp; More information on <a href="http://rxtx.qbang.org/wiki/index.php/Using_RXTX" target="_blank" rel="noopener noreferrer">this website</a>.</p>



<p class="wp-block-paragraph">In order to start coding with this library, import gnu.io.*.  For more information about Java Serial Programming, look <a href="http://henrypoon.wordpress.com/2010/10/11/java-serial-programming/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p class="wp-block-paragraph">Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/12/25/installing-rxtx-for-serial-communication-with-java/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">543</post-id>	</item>
		<item>
		<title>Getting Rid of that Awful “Content Preparation Progress” in Adobe Reader</title>
		<link>https://blog.henrypoon.com/blog/2010/10/26/getting-rid-of-that-awful-content-preparation-progress-in-adobe-reader/</link>
					<comments>https://blog.henrypoon.com/blog/2010/10/26/getting-rid-of-that-awful-content-preparation-progress-in-adobe-reader/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Wed, 27 Oct 2010 03:33:19 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Adobe Acrobat]]></category>
		<category><![CDATA[Adobe Acrobat version history]]></category>
		<category><![CDATA[Adobe Flash Player]]></category>
		<category><![CDATA[Adobe Inc.]]></category>
		<category><![CDATA[Adobe software]]></category>
		<category><![CDATA[Application software]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Comment]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[Final]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Graphics file formats]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Language]]></category>
		<category><![CDATA[Page]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Program Files]]></category>
		<category><![CDATA[RAID]]></category>
		<category><![CDATA[RAR]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Technical communication tools]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Vol]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/getting-rid-of-that-awful-%e2%80%9ccontent-preparation-progress%e2%80%9d-in-adobe-reader</guid>

					<description><![CDATA[That dreaded message appears every time I open a PDF.&#160; It has bothered me for the longest time, and I’ve finally taken the time to get rid of it.&#160; Before, every time I opened a PDF, Adobe Reader would process each page before it would let me scroll around.&#160; It was very annoying.&#160; Anyway, here [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>That dreaded message appears every time I open a PDF.&nbsp; It has bothered me for the longest time, and I’ve finally taken the time to get rid of it.&nbsp; Before, every time I opened a PDF, Adobe Reader would process each page before it would let me scroll around.&nbsp; It was very annoying.&nbsp; Anyway, here is the solution:</p>
<p>UPDATE 12/08/10: One of the comments (thanks to Jørgen)&nbsp;provided an even better solution for getting rid of this annoying process. &nbsp;It involves removing the plugins from Adobe Reader completely.</p>
<blockquote><p>…Program Files…AdobeReader 9.0Readerplug_ins<br />
there are 3 files you should delete (or maybe just rar them so you still got them in case something goes wrong)<br />
Accessibility.api, MakeAccessible.api, ReadOutLoud.api<br />
(if that gives troubles, just delete the files with the same name and .xxx where xxx stands for a certain language too)</p>
<p>OR – if you’re afraid Adobe won&#8217;t work or you’ll need the files later – rename the extension to .api_</p></blockquote>
<p>Below is the original solution that I had. &nbsp;It changes the settings so that the program will process each page as you read. &nbsp;It&#8217;s not as good as the previous solution that completely disables it though.</p>
<ol>
<li>Go to Adobe Reader’s Preferences (Edit &gt; Preferences)</li>
<li>Go to the Reading tab</li>
<li>In Screen Reader Options, choose Only read the currently visible pages</li>
</ol>
<p>Doing this pretty much tells Adobe to do the reading as you scroll through the pages.&nbsp; Although this can still be annoying, but it’s way better waiting through that screen for larger PDF’s.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/10/26/getting-rid-of-that-awful-content-preparation-progress-in-adobe-reader/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">433</post-id>	</item>
		<item>
		<title>Undervolting the Processor</title>
		<link>https://blog.henrypoon.com/blog/2010/08/16/undervolting-the-processor/</link>
					<comments>https://blog.henrypoon.com/blog/2010/08/16/undervolting-the-processor/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Mon, 16 Aug 2010 10:41:15 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[APT]]></category>
		<category><![CDATA[Central processing unit]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Dynamic voltage scaling]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Electromagnetism]]></category>
		<category><![CDATA[Energy conservation]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Health]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Laptop]]></category>
		<category><![CDATA[Lie]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Over]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Speed]]></category>
		<category><![CDATA[Vol]]></category>
		<category><![CDATA[Voltage]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/undervolting-the-processor</guid>

					<description><![CDATA[I’ve always been annoyed at my laptop idling at around 80 degrees Celcius (according to RealTemp), which is totally unhealthy for the computer. Today I decided to do something about it.&#160; I looked at how to undervolt my processor.&#160; The process on the laptop is an Intel Core 2 Duo T5250, which runs at 1.5 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I’ve always been annoyed at my laptop idling at around 80 degrees Celcius (according to RealTemp), which is totally unhealthy for the computer. Today I decided to do something about it.&nbsp; I looked at how to undervolt my processor.&nbsp; The process on the laptop is an Intel Core 2 Duo T5250, which runs at 1.5 Ghz.&nbsp; It supports voltages between 0.95 V and 1.25 V.&nbsp; I followed a guide (link at the end) on how to undervolt the processor and in the process I learned quite a bit.</p>
<p>According to the writer of the guide, undervolting simply reduces the voltage applied to the processor.&nbsp; Since all processors have a different voltage requirement, they all use one standardized value which is most likely higher than the amount that the processor itself requires.&nbsp; By reducing this excess voltage, the power dissipated by the processor will decrease, and thus reduce heat and increase battery life.&nbsp; It should also be noted that this process will not impact performance since the performance of a processor is governed by its clock speed.</p>
<p>By doing this, I’ve reduced the temperature of my laptop by about 12-15 degrees Celcius.&nbsp; The laptop’s keyboard and touchpad are no longer warm to the touch and the side heat vent no longer feels like burning.&nbsp; Definitely a major improvement!</p>
<p>Link: <a href="http://forum.notebookreview.com/hardware-components-aftermarket-upgrades/235824-undervolting-guide.html" target="_blank" rel="noopener noreferrer">http://forum.notebookreview.com/hardware-components-aftermarket-upgrades/235824-undervolting-guide.html</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/08/16/undervolting-the-processor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">414</post-id>	</item>
	</channel>
</rss>
