Printing labels with Zebra via raw EPL in Tcl

GhostScript is well and good; and Tcl’s canvas object can output to PostScript; but Zebra label printers use ZPL and – in this case – EPL.

set temp_f [open $::env(TMP)/label.ext w]

fconfigure $temp_f -translation lf

puts $temp_f \

close $temp_f

catch {exec print "/d:\\\\$::env(COMPUTERNAME)\\ZLP2844" \
  "$::env(TMP)\\label.ext"} result

puts stdout $result

Assuming the following:

  • Labeler is configured with correct driver and Print Test Page – including page size – is successful.
  • Labeler is shared and given a (preferably short) name.

I guess in this case, Zebra Setup Utility (from the official site) is the only way to get some form of IDE to test code between Tcl and EPL.

Setting up naive static IP on OpenBSD 5.7

After adding static IP to your account, your ISP sends you the following:

Gateway IP:
Usable range: ...
IP Subnet mask:
Primary DNS server:
Secondary DNS server:

Issue the following commands:

# echo > /etc/mygate
# echo inet > /etc/ [1]
# echo lookup file bind > /etc/resolv.conf
# echo nameserver >> /etc/resolv.conf
# echo nameserver >> /etc/resolv.conf
# echo > /etc/myname
# echo mycomp >> /etc/hosts
# reboot

Verify the following:

  • Your machine is connected to the modem – or router/modem combo – on the first Ethernet port.
  • Your machine is not connected to a “hotspot” device, if the ISP supplied you with more than one device that takes a coaxial cable.
  • You asked your ISP to “program” static IP, to set “bridge mode” on the modem/router, and to turn off the firewall.
  • You asked your ISP to verify the above, and rebooted your machine just to make sure.

Try the following:

# host

If you do not get “Path not found” or “Invalid argument” messages, and instead some information that appears to be network-related, congratulations: you now have a machine connected to a global packet firehose, and your education begins today.

[1] Your network card is named as /etc/, where “xxx” is a detected interface. Use ipconfig to display the list of interfaces, including lo0 (loopback), which is not the one you’re looking for.


I was asked to inherit a codebase and modify it without notifying the author. In my opinion, it would be courteous to at least do the latter! So I replied that I was unwilling, appealing to conscience, knowing an outlook raised in proprietary would have dulled any clarion argument to free software – its authors, in like parts patient, and brilliant, without whom I might have suffered greater and thankless toil – but there was agreement that it was a strange thing to do.

On the other, as a college graduate of the computer sciences, I could not refuse for lack of skill; what would Turing say, or my professors, if I claimed prior commitments, to code which was shorter than an operating system kernel, or less complex than self-driving cars?

My world is one foot in halfhearted cover-letters and the other in corporate protocols, where seat time is a metric and early clock-ins are punished. Now I am divided again, between the want of sharing code – and by virtue, ideas – versus willful omission.

ssconvert returns

There’s a race condition in Excel using PasteSpecial, and Copy(Destination) uses the clipboard [1] too: a lot of scheduled tasks running concurrently might mess with the others, leading to VBA errors that aren’t fit to be categorized under “set it and forget it.” The crucial element is converting worksheets to HTML, formatting and all, which is about as sweet as you’d expect. But when it fails, everything falls apart.

> ssconvert sheet.xlsx sheet.html

This works really well. Here are some pointers:

  • Take a cue from PivotTable design at a minimum: colored top row, unobtrusive borders, and bold headers.
  • Use setTimeout(), <meta … “no-cache”> tag, and sheet.html?cache=Math.random(1000000) to implement data refresh, as well as ensure the data is not the old stuff.

Now your company has transitioned from mailed reports to web dashboards. I hope you like frontend, because that’s what you’ve inherited.

[1] By clipboard, you can’t even rely on just one: Excel has its own set of clipboard(s), and Windows has a global one.

Automate TG70.ApexGridOleDB32

This is a table view that can be automated with AutoIt. The trick is to use Spy++ to look at the tree structure of the parent windows, and then navigate to it with AutoIt’s _WinAPI_* functions. Starting with Visual Studio 2013, Spy++ comes bundled with the SDK. Here are some starting steps:

  1. Enter a random string into the first field of the table.
  2. Use AutoIt window info to identify the application window.
  3. Search for the handle in Spy++.
  4. Use AutoIt’s _WinAPI_* functions to traverse the tree, using $GW_CHILD and $GW_HWNDNEXT.
  5. Use WinActivate($hwnd), Send(“data”), and Send(“{DOWN}”) calls to populate the first column.

Javascript – objects not ordered in

Elements in an object literal are not ordered on traversal, but placing them into an array lets you control them by index:

var o1 = { num: "one" };
var o2 = { num: "two" };
var o3 = { num: "three" };
var a = [];

a.push(o1); a.push(o2); a.push(o3);

for (var i = 0; i < a.length; i++) {
  var obj = a[i];

Info into and out of a Chromebook

Something about the security model for Chromebooks makes it really hard to read and write arbitrary files. That’s fine, because Google has to harden web APIs that act like desktop apps. So for pulling data from external sources, an XMLHttpRequest GET is fine; for pushing stuff out, FTP upload is okay.

All the information is processed as strings, so it can be as large as your tepid hopes. You can read and write to “local storage” using API, get() and set(), global variables between task-oriented windows. These you can hide and close, with an event attached on window closing to curate the next screen. Really, it’s like a wizard, a sequence of full-blown dialog boxes.

Once you can shuttle data among windows, you’re almost there. Javascript is asynchronous, so between one line calling a function with a callback and a second line with the same indentation, the callback might happen as if it were the third – or later – statement. It’s a trip, but not impossible to grasp.

Cheap blocking

A first iteration of blocking to make sure callbacks converge before continuing execution:

var gWait = true;

function waitForVar() {
  if (gWait) {
    setTimeout(waitForVar, 1000);
  } else {
    // FTP upload or other I/O
    // ...

function uploadResults() {
  var state = 0;
  // ... computation of domain reality ...
  if (state == 1) {"dogeAmount", function() {
      s += "I have " + dogeAmount + " coins. To the moon!";
      gWait = false;

A nice change of pace

Javascript callbacks are asynchronous, but it’s hard to appreciate the concept until you experience the first time output calls come out of order:

function getThenSetAndThenPrint() {{key1:val1,key2:val2}, function(){[key1, key2], function(objs) {
      var result = "";

      for (var p in objs) {
        result += obj + "=" + obj[p];
      console.log("finished setting vals");
  console.log("end of function");

And then you get output like

end of function
finished setting vals

Hello future hello

“The concept of end-user computing is based on the assumption that the user is self-sufficient. This self-sufficiency… implies an ability to do one’s own work from the time a problem is identified until it is solved.”

“… artificial intelligence (AI)… that the computer can be programmed to perform some of the same logical reasoning as a human… expert systems… not simply assist the manager in making a decision in the same way as the [decision support system] DSS has been programmed, but will be able to suggest better ways to make the decision.”

– “Management Information Systems” (1986)