Text Editor Wars : Multi-Edit versus … Pizza?

In the late 80’s, my programming team was in search of a decent programmer’s text editor for MS-DOS. At the time, a number of editors seemed to have comparable features. Any missing features could often be added via the embedded macro language that each of these editors sported. What was it that helped to make the decision?

rsz_multi_edit2

The advertisement from American Cybernetics above ( excerpted from the late, great Computer Language magazine ) caught our eye. The ad compared their Multi-Edit product to … pizza.

What really sold us was their $10 trial diskette. It was not common for software companies to offer fully functional trial editions, so this was also not like what we had seen in the trade press. We tried the trial version for about a month. It had a nag screen, but it was otherwise fully functional. Then, we all voted unanimously that this was our choice. We bought copies for everyone.

The DOS version remains one of my favorite text editors.

Posted in Programming | Tagged | Leave a comment

My Journey Began with BASIC

Originally published on: Sun, 13 Mar 2011.

“It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration” – Edsger Dijkstra

My early days of computing began in the late 1970’s. I used to go in to the Radio Shack in the mall where they would let the patrons type stuff into their display-model TRS-80. You could tell that none of the patrons were skilled in any type of computer language as the screen was filled with a line of nonsense followed by a line indicating that a syntax-error had occurred.

I had wondered just exactly what one would have to type in to make the computer actually do something.

A short time later, my eldest brother had told us that he’d bought a TRS-80, so we went over to see it. He had a few interesting programs on cassette that he demonstrated. However, the program that captured my attention was one that he quickly typed in. It went something like this:

termites

It’s a relatively simple program. It clears the screen, displays text on the bottom line of the screen, then continuously plots points based on two random coordinates. All but the last line of the screen starts to fill with little rectangular blocks:

termites2

After he demonstrated more programs, I was left alone with the computer and was tinkering a bit. I tried to re-type the above program from memory, but I didn’t know the exact syntax. I was typing a lot of things in an English-like language such as:

20 X = A RANDOM NUMBER FROM 1 TO 10

While it didn’t work, it took me almost no time to learn how to edit and list a program by using line-numbers at the beginning of each line.

I tried all sorts of combinations and then began to consult the manual. My brother returned and re-typed the program. I saw my mistakes.

At that point in time, I decided that I was going to learn the BASIC programming language.


BASIC is an acronym for Beginner’s All-purpose Symbolic Instruction Code. A dialect of BASIC was available on just about any 8-bit era home-computer produced in the United States and the United Kingdom.

While not terribly expressive as compared to other programming-languages, BASIC had a few attractive features:

  • BASIC programs were compact enough to allow for fairly elaborate programs to be developed on computers with minimal Random Access Memory (RAM).
  • BASIC could be learned easily by hobbyists; it was an entry-level programming-language.
  • BASIC was interactive; one could stop a program at certain points, examine/change variables, restart the program at any line-number …etc.
  • BASIC editors were a part of the language and were easy to understand.
  • Early computers had no operating-systems. BASIC was the operating-environment.

BASIC began to get a bad reputation because of slow performance. This really isn’t due to any aspect of the language itself; the early implementations of BASIC were constrained by hardware that had small amounts of RAM. Early BASIC interpreters did not have the luxury of being able to cache important information such as target line-numbers or variable addresses. The interpreters used to continuously re-examine each line even in a series of lines that would be repeated throughout the program.

So, BASIC acquired a reputation for being slow.

BASIC was also taken to task for promoting “spaghetti code” due to the necessary use of the GOTO verb for flow-control.

Due to the amount of RAM available at the time, BASIC also limited the names of variables to one or two characters. Subroutines were numbered instead of being named. All variables were global in scope, limiting the ability to modularize and re-use code. Many cited these elements common to most BASIC’s as making programs unreadable.

To further paint a bleak picture, wise programmers began to use BASIC as a sort of object-code. They would take advantage of the behavior of the interpreter to speed up their programs at the expense of limiting the readability of the code.

Techniques used included:

  • Placement of all subroutines at the beginning of a program so that GOSUB would find them more quickly.
  • Packing lines together with no spaces between words to speed up the interpretation process.

In 1980, my dad received a TRS-80 pocket computer as a gift.

trs80pc1

At this time, my Geometry teacher had purchased a TRS-80 for students to use. He financed the computer by selling candy bars. The last portion of our school day was essentially a study-hall. My teacher used this time to teach a non-credit BASIC programming class.

I loved the class. One of the challenges was to write a program that would find all factors of an input integer. I wrote that program and others on the pocket computer. The pocket computer only had about 2K of RAM and had a single-line display, but I managed to write a couple of simple games for it using a random-number formula that was provided in the manual.

I decided to write an arcade-style game in BASIC for the desktop TRS-80 computer at school. I borrowed a manual and went about the seemingly simple task of animated a flying spaceship. I wanted to move it across the screen vertically.

I spent hours trying to figure out how to SET() and RESET() points on the 128 by 48 pixel viewing area in a way that would allow me to animate the spaceship. At this time, I knew very little about arrays or screen-memory or anything that might help me out. In fact, I knew very little about programming. I was trapped by the commands and simple control-flow available to me.

I asked my brother about how this sort of thing was done. He referred me to machine-language which is another story.

I gave up the project at the time and was content to continue with the classes at school.


In the latter part of 1982, I received my own TRS-80 Model I desktop computer.

trs80

The computer was purchased at an auction and came with a number of books on BASIC. I went through all of them. It was much easier to experiment now that I had a fairly powerful BASIC and 16K of RAM!!!

I began to buy ( and borrow ) issues of 80-Micro magazine. I typed in a number of the BASIC listings and studied many others. I read a lot about other languages, but I was very confused about them. I couldn’t understand why they didn’t have line-numbers by each line when the source-code was printed in the magazine. I had been limited to a line-oriented editor. I didn’t understand how one ran these programs, either. Did one simply have to type RUN at some prompt?

I spent a lot of time writing and debugging programs. Debugging was a skill that I learned because of BASIC. BASIC was easy enough for the neophyte to write, but debugging took patience.

At this time, I was taking a BASIC class in high-school using Apple II+ and Apple IIe computers. The Apples had high-resolution graphics and nifty BASIC primitives that allowed one to draw all over the screen.

I soon learned Z-80 and 6502 assembly-language and began to move outside of the BASIC box where I had been confined.


In 1983, I began working with Commodore PET and Commodore 64 computers in an independent-study course at my high-school.

commodore-64

I soon bought my own Commodore 64.

The C64’s BASIC was as spartan as it’s predecessors. This helped to ensure compatibility. Often, one could write BASIC programs that could run unchanged on Commodore’s VIC-20, 64, and PET computers. However, software became available for various computers that would add extensions to the BASIC language.

I had the opportunity to use Simons’ BASIC ( see the Wikipedia article here. )

simons

Among the 114 new commands added to BASIC was a set that added an ELSE verb to use with IF statements, named procedures, local variables, and other elements of structured-programming normally found in languages such as Pascal.

I began to understand the limitations of BASIC and turned to other languages like Pascal and C.

At this time, home-computers were evolving and BASIC implementations followed. BASIC implementations on these new computers often provided structured-programming support and optimizations to the interpreter for better execution.

It appeared, though, that many programmers who used computers such as the Commodore Amiga were turning to compiled languages such as C to better exploit the potential of their machines. Newer dialects of BASIC and BASIC compilers began to take over the landscape. Line-numbered / GOTO-laden BASIC was fading off into the sunset.


It’s difficult to argue with Dijkstra’s quote that appears at the beginning of this post. I cannot accurately state that I would be a better or worse programmer now if I had avoided BASIC altogether. Others have stated that the quote was supposed to be mildly in jest.

Dijkstra was a prominent figure in computer science, however. I do not take his words lightly. I would infer that it might be more difficult to teach someone who had only been exposed to line-numbered BASIC, but to suggest that they were beyond hope baffles me.

I look at BASIC as an entry-level vehicle to the art of programming. It was approachable. Back in “the day” many who had no intention of becoming programmers were conversant in BASIC. I would argue that BASIC inspired many. Like many of my generation, I moved on. I studied the contemporary languages and practices of the day and rarely went back to using BASIC. I look at BASIC as a necessary milestone; something that jump-started my entrance into programming. I learned much from BASIC. I learned why I need to avoid certain practices.

I have pondered what would have happened if I had been able to avoid using BASIC in those early days. Would I become “mentally mutilated beyond hope of regeneration” ? I don’t think so. I think that the path I took was the proper one, for me.

Posted in Programming | Tagged , , , , | Leave a comment

Display File, Function, and Line Number in Go (Golang)

Years ago, I used a macro in C and C++ programs to provide information on the current line of code being executed. I used this in error handlers and exception traps in addition to other information. Displaying the file name and line number of a given exception in large projects was often helpful in the speedy remediation of issues.

I also used this technique to home brew tracing function in the code. If problems arose in environments where diagnostic tools were not available, simple execution traces were often very valuable to the troubleshooting process.

While Go has facilities to trace the execution of a program, I wanted to be able to determine the file name and line number of the code currently being executed. The runtime package contains a function named Caller() that returns four values: the program counter, the file name, the line number, and a boolean indicating if the retrieval has been a success.

I found that the current function name can be extracted from the program counter return value by using the FuncForPC() function.

The full source code for whereami.go and the example functions ( in the src/ folder ) can be found at:

https://github.com/jimlawless/whereami

The WhereAmI() function looks like this:

func WhereAmI(depthList ...int) string {
	var depth int
	if depthList == nil {
		depth = 1
	} else {
		depth = depthList[0]
	}
	function, file, line, _ := runtime.Caller(depth)
	return fmt.Sprintf("File: %s  Function: %s Line: %d", chopPath(file), runtime.FuncForPC(function).Name(), line)
}

WhereAmI() is a variadic function that accepts any number of integer arguments. If no arguments are specified, we assume that the calling function wants to specify one level of lookup on the call stack.

Otherwise, parameter number zero would contain the integer representing the call stack depth that the calling function has supplied.

Note that the call in whereami_example1.go uses a simple reference to WhereAmI() as an argument to Printf().

// Copyright 2016 - by Jim Lawless
// License: MIT / X11
// See: http://www.mailsend-online.com/license2016.php
//
// This code may not conform to popular Go coding idioms

package main

import (
	"fmt"
	"github.com/jimlawless/whereami"
)

func main() {
	fmt.Printf("%s\n", whereami.WhereAmI())
}

The output of the Printf() invocation is:

File: whereami_example1.go  Function: main.main Line: 15

whereami_example2.go shows the use of the WhereAmI() call in main() and in a factorial function called fact().

whereami_example3.go contains a usage error. Since we have now wrapped our call to WhereAmI() in a function called trace(), the only information returned for WhereAmI() will indicate the call from the trace() function.

We correct this problem in whereami_example4.go by supplying a depth of 2 to the WhereAmI() function. This allows us to get information from trace()’s caller instead of trace() itself.

It occurs to me that I had failed to process the bool that is returned to determine if the runtime.Caller() function works correctly. I’ll have to fix that.

Posted in Programming | Tagged | Leave a comment

Java in a Windows EXE with launch4j

Originally published on: Sun, 16 Aug 2009 13:46:59 +0000

I noted today that a successful independently written / marketed ( MicroISV ) product had been built in Java. The redistributable files were available for both Windows and MacIntosh computers.

I emailed the author, asking what he used to build the installations for each. I’ll discuss the Mac software in a later post. For the Windows installation, he pointed me to a product called launch4j. ( See http://launch4j.sourceforge.net/ ).

Launch4j is an all-Java program that will bind a configurable Windows stub executable file to a Java jar file. The result is a jar embedded in a specially configured EXE.

When invoked, the EXE will execute the system’s appropriate JVM ( or will issue an error message if a compatible JVM hasn’t been found ) and will then execute the embedded jar file in this JVM.

Effectively, launch4j bottles up Java code into a Windows EXE.

Since launch4j is an all-Java program, one can actually build Windows EXE’s on various supported non-Windows platforms.

Let’s take a trivial sample Java program and turn it into an EXE with launch4j.

HeyGuys.java


// Display a simple message
// This code is in the public domain.

import javax.swing.*;

public class HeyGuys {
   public static void main(String[] args) {
      JOptionPane.showMessageDialog(null,"Hey, you guys!");
      System.exit(0);
   }
}

Enter the following to compile and execute the program:

javac HeyGuys.java 
java HeyGuys

The message:

heyguys

…should appear on the screen. Click OK.

Let’s take the file HeyGuys.class and put it in its own jar file. We first need to create a manifest file so that the jar will contain metadata to indicate which class should be executed via java.exe or javaw.exe.

Enter the following two lines in a file called manifest.mf:

Manifest-Version: 1.0
Main-Class: HeyGuys

Then, issue the following command:

jar -cfm heyguys.jar manifest.mf HeyGuys.class

Executing the above command should yield the file heyguys.jar.

Now, let’s try to execute the jar to see if we’ve packaged it up correctly.

java -jar heyguys.jar

You should see the same message window that was displayed earlier:

heyguys

Finally, let’s use launch4j to package up the jar into an EXE.

Although launch4j has a command-line interface, I first used the GUI. The first screen I filled in looked similar to this:

launch4j1

I tried to just save the EXE at that point, but I then needed to specify a minimum Java version on this tab:

launch4j2

After changing those values, launch4j wanted me to save those options in an XML file, so I just chose the name l4j.xml arbitrarily.

Launch4j then quickly packaged a small EXE.

If you run it on a version of Windows with Java 1.6.0 or above, you’ll see the message window. If you don’t have a 1.6.x JVM, you’ll be prompted to download one.

Note that launch4j is not an installer. Now that you have an EXE, you might want to build an installer around it with a product like Inno Setup or the NSIS installer system.

Also note that in addition to the bare options that I’ve chosen, a number of other options are available including the ability to set an icon and the ability to specify the JVM’s runtime parameters such has heap size.

The source code and EXE for the above sample program can be found here:

http://www.mailsend-online.com/wp/heyguys.zip

Posted in Programming | Tagged , | Leave a comment

Send GMail From the Windows Command-Line with MailWrench

Originally published on: Sun, 13 Feb 2011.

Google’s GMail service allows e-mail to be sent using an SMTPS ( SMTP over SSL ) interface. Sending GMail via the Windows command-line requires a command-line mailer with SMTPS support. My commercial MailWrench utility is one such program.

Update 25 July, 2012: MailWrench is now free, open source software. Please see the post at the following link:

https://lawlessguy.wordpress.com/2012/07/24/mailwrench-csharp-command-line-mailer-for-windows-is-now-free-software/

The GMail SMTPS service listens at port 587 on the server smtp.gmail.com. To configure MailWrench to send mail using GMail, create a text file that we’ll just name m.cfg and add the following configuration lines:

-ssl
-smtp smtp.gmail.com
-port 587
-id your_id@gmail.com
-password your_password

The MailWrench command-line you would then use to send a simple message would be something like the following:

MailWrench @m.cfg -to some_id@someserver.kom -msg "Hello!" -s "Testing!"

Note that any of the options specified in the file m.cfg could have been specified on the command-line itself. The “.cfg” files are intended to be used to contain options that rarely change when sending e-mails.

Since GMail does not allow arbitrary attachments, any file you attach must be one of the permissible attachment types ( word-processor documents, spreadsheets, images,audio, …etc. ) Your e-mail may not process properly if you send other file types.

To attach the image file test.png to the above e-mail, add the parameters -a test.png to the above command-line. The new command-line should look like the folllowing:

MailWrench @m.cfg -to some_id@someserver.kom -msg "Hello!" -s "Testing!" -a test.png
Posted in Programming | Tagged , , , | Leave a comment

WSH JavaScript Includes

Originally published on: Wed, 28 Apr 2010 00:09:54 +0000

I like to separate JavaScript functions into libraries that I can later reference in some other script.

It’s easy enough to reference these in HTML using the SRC attribute of the SCRIPT tag.

I the case of WSH, one can use a WSF document to dynamically construct a composite script via combinations of inline and/or external files. However, I prefer a more simple approach when I’m using WSH.

Please consider these two files:

one.js

   // MIT/X11 license. See includelib.js for full text of
   // license.
eval(new ActiveXObject("Scripting.FileSystemObject").
   OpenTextFile("inc.js",1).ReadAll());

display("Hello!");

inc.js

   // MIT/X11 license. See includelib.js for full text of
   // license.
display=function(x) {
   WScript.Echo(x);
}

The first couple of lines of one.js create a new FileSystemObject. Then, the dot operator is used to immediately refer to that object so that we can invoke OpenTextFile() to open a file called inc.js for mode 1 ( reading ).

Again, the dot operator is used to refer to the new object so that we can call the ReadAll() method to load the entire inc.js file into a string.

Finally, we call eval() to dynamically execute the contents of inc.js, effectively simulating an “include” operation available natively in other scripting languages.

In the inc.js file, I’ve chosen to use an alternate form of function definition that ensures that the named function will appear globally so that it can be referenced by other included modules.

We prove that we’ve invoked the included file which defines a function called display() by invoking this new function.

If you execute one.js via the following command-line:

cscript /nologo one.js

…you should see the output:

 Hello!

If you have a number of files to include, you might not want to keep creating FileSystemObject instances. We can create a library that encapsulates this behavior into a function and can then use the technique from one.js to dynamically evaluate that library.

includelib.js

// This single license text is applied to all examples one,js, 
// inc.js, includelib.js, and two.js.
// 
// License: MIT / X11
// Copyright (c) 2010 by James K. Lawless
// jimbo@radiks.net http://www.radiks.net/~jimbo
// http://www.mailsend-online.com
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

   var incfso=new ActiveXObject("Scripting.FileSystemObject"); 
   include=function(x) {
      eval(incfso.OpenTextFile(x,1).ReadAll());
   }

This library creates one global instance of FileSystemObject, incfso, for future reference.

By dynamically evaluating includelib.js, we now have a callable include() function. We can then include inc.js and can invoke the display method again.

two.js

   // MIT/X11 license. See includelib.js for full text of
   // license.

   // Use the short hack to load 
   // includelib.js
eval(new ActiveXObject("Scripting.FileSystemObject").
   OpenTextFile("includelib.js",1).ReadAll());

   // Now invoke include() function to bring in inc.js
include("inc.js");
display("Hello, again!");

When you execute two.js…

cscript /nologo two.js

…you should see the text:

Hello, again.
Posted in Programming | Tagged | Leave a comment

Embedding JavaScript in a Batch File

Originally published on: Fri, 07 Aug 2009 12:05:51 +0000

The program below is both a batch file and a JavaScript WSH console file. The dual nature of the file is achieved via JavaScript block comments and the strategy by which the command interpreter searches for target labels in a batch file.

Save the file below as hybrid.bat.

rem ( /*
@echo off
cscript /nologo /e:javascript hybrid.bat
goto end
*/ )

// by Jim Lawless
// This program sample is in the public domain

function rem() {
   WScript.StdOut.WriteLine("Hello, world!");
}

/*
:end */

The first line of code is benign for a batch file; the REM command is a single line remark, so it ignores all text after it.

The first line is constructed so that syntactically, it is also the beginning of a valid JavaScript function call for a function named rem().

Immediately after the first left-parenthesis in the call, a block-comment is used to mask the next few lines from the WSH JavaScript interpreter. Batch commands follow on the next three lines, ending with a goto.

The batch file itself invokes the WSH console interpreter cscript.exe passing in the name of the file ( hybrid.bat ) itself. After invocation of the script as a JavaScript file, the batch file portion attempts to transfer control to a label named end.

When the command processor attempts to transfer control to a label via the goto verb, each line of the batch file is examined sequentially until a matching label is found. Any syntax errors encountered ( the lines of JavaScript text ) are ignored.

Posted in Programming | Tagged | 2 Comments

Command Line Image Format Conversion in CSharp

Originally published on: Sat, 26 Sep 2009 14:44:24 +0000

I needed a quick-and-dirty command-line image format conversion utility. The .NET framework made the task pretty painless. I wrote the following utility that can convert between Windows Bitmap, JPEG, GIF, PNG, and TIFF images. ( TIFF may have a variety of subformats, so your mileage may vary when trying to convert to/from TIFF. )

imgconv.cs

// imgconv.cs - Simple command-line image file converter
//
// License: MIT / X11
// Copyright (c) 2009 by James K. Lawless
// jimbo@radiks.net http://www.radiks.net/~jimbo
// http://www.mailsend-online.com
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

using System ;
using System.Drawing;
using System.Drawing.Imaging;

namespace ImgConv
{
   public class ImgConv
   {
        [STAThread]
      public static void Main(string[] args)
      {
         ImageFormat fmt;
         string inputFile="",outputFile="";
         int i;
         fmt=ImageFormat.Jpeg;
         Console.WriteLine("\nimgconv by Jim Lawless - jimbo@radiks.net\n");

         for(i=0;i<args.Length;i++)
         {
            if(args[i].ToLower().Equals("-in"))
            {
               inputFile=args[i+1];
               i++;
            }
            else
            if(args[i].ToLower().Equals("-out"))
            {
               outputFile=args[i+1];
               i++;
            }
            else
            if(args[i].ToLower().Equals("-gif"))
            {
               fmt=ImageFormat.Gif;
            }
            else
            if(args[i].ToLower().Equals("-jpg"))
            {
               fmt=ImageFormat.Jpeg;
            }
            else
            if(args[i].ToLower().Equals("-png"))
            {
               fmt=ImageFormat.Png;
            }
            else
            if(args[i].ToLower().Equals("-bmp"))
            {
               fmt=ImageFormat.Bmp;
            }
            else
            if(args[i].ToLower().Equals("-tiff"))
            {
               fmt=ImageFormat.Tiff;
            }
            else
            {
               Console.WriteLine("Unknown option " + args[i]);
               Syntax();
               return;
            }
         }
         if( (inputFile=="")||(outputFile=="")) {
            Syntax();
            return;
         }
         Bitmap b=new Bitmap(inputFile);
         b.Save(outputFile,fmt);
      }
      public static void Syntax()
      {
         Console.WriteLine("Syntax:\timgconv.exe -in input_file_name -out    output_file_name [ -gif -png -tiff -jpg -bmp ]\n");
         Console.WriteLine("The default output format is -jpg.\n");
      }
   }
}
imgconv by Jim Lawless - jimbo@radiks.net

Syntax: imgconv.exe -in input_file_name -out output_file_name [ -gif -png -tiff -jpg -bmp ]

The default output format is -jpg.
To load a BMP file and save as a JPEG, issue the following command. ( The default output format is JPEG. You may optionally specify the -jpg parameter. )

imgconv -in file.bmp -out file.jpg

To load a JPEG file and save as a PNG, issue the following command.

imgconv -in file.jpg -out file.png -png

I haven’t tested this with Mono, yet.
The source and executable file for imgconv can be downloaded in a single archive at: http://www.mailsend-online.com/wp/imgconv.zip

Posted in Programming | Tagged | Leave a comment

A Simple Associative Array Library in C

Originally published on: Thu, 19 Nov 2009 02:35:02 +0000

I often need to use associative arrays when writing C code. You might be more familiar with these constructs under other names ( dictionaries, maps, hashmaps, hashes, …etc. ) I will use the term map in place of the words associative array.

A map is a collection of key / value pairs or name / value pairs. My implementation of a map structure allows strings as the only data that can be stored in the name and value.

Many implementations of maps use a hashed lookup to speed up execution. I have opted to use a simple forward-chained linked-list of map structures. When searching for an item in a map, the search will sequentially pass over every item in the list of map entries until a match is found. If no match is found, an empty string is returned.

This implementation is complete enough for my needs. See:

https://github.com/jimlawless/map_lib

http://www.mailsend-online.com/wp/map_lib.zip

The test program map_stuff.c loads and displays a map with name/value pairs. The names are all numbers. The values are words that sound like the numbers ( homonyms ).

The output from the map_stuff program is as follows:

Two Too
Four Fore
One Won

Two To
Four Fore
One Won

Eight 

Eight Ate

I did not provide any kind of iterator functions in the library. If I need to iterate through a given map, I will just use a for-loop and will use the ->nxt element to reach each successive entry.

Posted in Programming | Tagged | Leave a comment

Play MP3 Files with Python ( Windows )

Originally published on: Sun, 26 Jun 2011.

I’ve just read the book Grey Hat Python : Python Programming for Hackers and Reverse Engineers by Justin Seitz. The book introduced the Python ctypes library to me. The ctypes library, allows a Python program to access to lower-level features of the operating environment normally reserved for C programmers.

( The book itself was a great read that deserves its own post … after I’ve had time to tinker with all of the code. )

As an early experiment, I rewrote in Python the bulk of the command-line MP3 player I had originall written in C.  Please refer to the script below:

playmp3.py

# Copyright (c) 2011 by James K. Lawless
# jimbo@radiks.net http://www.mailsend-online.com
# License: MIT / X11
# See: http://www.mailsend-online.com/license.php
# for full license details.

from ctypes import *;

winmm = windll.winmm

def mciSend(s):
   i=winmm.mciSendStringA(s,0,0,0)
   if i<>0:
      print "Error %d in mciSendString %s" % ( i, s )

def playMP3(mp3Name):
   mciSend("Close All")
   mciSend("Open \"%s\" Type MPEGVideo Alias theMP3" % mp3Name)
   mciSend("Play theMP3 Wait")
   mciSend("Close theMP3")

playMP3("test.mp3")

The ZIP archive containing the above source can be downloaded from

http://www.mailsend-online.com/wp/playmp3.zip

Note that the above script does not play a script directly from the command-line; it exposes the function playMP3() which should allow one to write Python code to control the invocation of the given MP3 file through the Media Control Interface (MCI).

The script expects a file named test.mp3 to be present in the current directory. You can alter the last line of the script, substituting the name and location of a preferred MP3 file.

Please note that in the Python version of the code, I have omitted the call to the Win32 API function GetShortPathName(). Instead, I placed double-quotes around the name of the MP3 file in the MCI command-string to accommodate the occurrences of spaces in the filename and/or pathname.

Posted in Programming | Tagged | Leave a comment