A script that pastes the OS X clipboard into the DOSBox DOS emulator

With the help of Nigel Garvey and DJ Bazzie Wazzie, I’ve put together a script that pastes the contents of the OS X ciipboard into DOSBox, an open-source program that emulates an old IBM PC running DOS. I doubt many people will have much use for this, but the techniques offered by the experts here might be useful in other situations, so here it is.

Edit 1: Includes corrections from DJ Bazzie Wazzie’s post below.
Edit 2: Includes corrections from Nigel Garvey’s post also.
Edit 3: changes “name contains DOSBox” to “name begins with DOSBox”, so the script won’t detect itself if its name is something like “Paste into DOSBox”.

-- Pastes the OS X clipboard into DOSBox
-- By Edward Mendelson 3 July 2012
-- improved with corrections from DJ Bazzie Wazzie and Nigel Garvey, 4 July 2012

-- try to determine DOS codepage for DOSBox according to Mac locale:
set the codePage to "850" -- 850 for Europe
try
	set macLocale to do shell script "defaults read -g AppleLocale"
	if macLocale is in {"en_US", "en_CA"} then
		set the codePage to "437" -- 437 for North America
	end if
end try
-- if you get the wrong results, then set correct codepage by uncommenting next line
-- set the codePage to "437" -- either "437" or "850"

set appRunning to {}
tell application "System Events" to set appRunning to name of every process whose name begins with "DOSBox"
if appRunning is {} then
	tell me to activate
	display dialog "DOSBox not running." buttons {"OK"} with title "Paste into DOSBox" giving up after 5
	error number -128
end if

-- standard ASCII characters that for some unknown reason can't be typed
-- directly into DOSBox
set charList to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "'", "-", "="}
set codeList to {29, 18, 19, 20, 21, 23, 22, 26, 28, 25, 47, 39, 27, 24}

-- non-DOS characters (e.g. typographic quotes) to type in with shift down
set shiftList to {""", """}
set shiftCodeList to {39, 39}

-- codes to use for typing extended ASCII characters
-- DOS uses Alt-NumberPad keys for this 
-- (e.g. hold down Alt, type NumPad-1, NumPad-3, NumPad-0, release Alt, for é
set kpCodes to {82, 83, 84, 85, 86, 87, 88, 89, 91, 92}
-- Keypad key codes: KP0=82, KP1=83, KP2=84, KP3=85, KP4=86, KP5=87, KP6=88, KP7=89, KP8=91, KP9=92

try
	set getClip to the clipboard as text
on error
	set getClip to " "
end try
tell application "DOSBox" to activate
delay 0.1
tell application "System Events"
	repeat with i from 1 to count characters of getClip
		set thisChar to (character i of getClip)
		if thisChar is in charList then
			set codeItem to my listPosition(thisChar, charList)
			set keyCodeNum to item codeItem of codeList
			key code keyCodeNum
			-- next for characters that can't be typed directly
		else if thisChar is in shiftList then
			set codeItem to my listPosition(thisChar, shiftList)
			set keyCodeNum to item codeItem of shiftCodeList
			key code keyCodeNum using {shift down}
			-- next for extended ASCII characters
		else if (id of thisChar) is greater than 127 then
			set upperASCII to my getCharValueForDOS(thisChar, codePage)
			-- next lines by Nigel Garvey at MacScripter.net
			tell application "System Events"
				key down option
				key code (item (upperASCII div 100 + 1) of kpCodes)
				key code (item (upperASCII mod 100 div 10 + 1) of kpCodes)
				key code (item (upperASCII mod 10 + 1) of kpCodes)
				key up option
			end tell
		else
			keystroke (character i of getClip)
		end if
		delay 0.01
		tell application "DOSBox" to activate
	end repeat
end tell

on listPosition(thisItem, thisList)
	repeat with n from 1 to the count of thisList
		if item n of thisList is thisItem then return n
	end repeat
	return 0
end listPosition

on getCharValueForDOS(char, cPage)
	-- routine by DJ Bazzie Wazzie at MacScripter.net
	return (do shell script "/bin/echo -n " & quoted form of character 1 of char & " | iconv -f UTF8 -t CP" & cPage & " | od -A n -t u1") as integer
end getCharValueForDOS

The parts written by Nigel Garvey and DJ Bazzie Wazzie are very elegant; the rest (by me) is a mess. Any improvements will be gratefully received.

Great code and certainly useful, however you have made a small mistake.

if macLocale is "en_US" or "en_CA" then

should be:

if macLocale is "en_US" or macLocale is "en_CA" then

or

if macLocale is in  {"en_US", "en_CA"} then

Then appRunning code can be simply set by:

tell application "System Events" to set appRunning to name of every process whose name contains "DOSBox"

The example code you have from our previous discussion were wrong. Your own solution was correct and therefore you should stick with that.

Nice code and thanks!

Hi, Edward.

In addition to DJ’s comments, ‘ASCII number’ and ‘ASCII character’ are deprecated as from AS 2.0 (in Leopard). ‘ASCII number’ should now be ‘id of’. They don’t necessarily produce the same results above 127, but ‘id of’ should work in the context of your script.

Another thing you may like to consider is to set a variable at the top of the big repeat to character i of getClip and to replace every other instance of ‘character i of getClip’ in the repeat with the variable name. This way, each character would be extracted from the string just once instead of (in the worse case) four times.

Hi Nigel and DJ Bazzie Wazzie,

Many thanks for those corrections, which I’ve now incorporated in the first post. Basically everything I know about AppleScript (which isn’t much) was learned in these forums.

About the code that tests whether DOSBox is running. I went back and forth among various solutions because I found that - unpredictably - my script would launch a second instance of DOSBox. I think DJ Bazzie Wazzie is right about which code actually works, and I’ve put that back.

About the variable in place of (character i of getClip) - it was in the back of mind to do that, but so far back that I never thought enough about it. It’s a beginner’s error that I should have known not to make.

One pleasure of posting in this forum is that I get to see amazingly elegant solutions to problems that I could only solve in inefficient ways. Thank you again.