--Applescript direct

-- Script that improves on the TeXShop default macro called "Encoding",
-- i.e., %!TEX encoding =  #INS#
-- by letting the user choose which encoding she/he wants to use,
-- deleting the first old (if any) encoding command,
-- inserting the command at the beginning of the document, and
-- restoring the original selection.
-- Ramon Figueroa-Centeno (March 10, 2009)
-- http://www2.hawaii.edu/~ramonf

-- History: 
-- 1.1: March 18, 2009
-- Added missing encodings.
-- 1.2: March 28, 2009
-- Added code to respect first lines that start with "%&"

-- If you wish you can change this so that your favorite encoding is the default choice
property default_encoding : "MacOSRoman"

tell application "TeXShop"
	
	-- Get a sorted list of the TeXShop encodings
	tell me
		set encodings to {"MacOSRoman", "IsoLatin", "IsoLatin2", "IsoLatin5", "IsoLatin9", "IsoLatinGreek", "Mac Central European Roman", "MacJapanese", "DOSJapanese", "SJIS_X0213", "EUC_JP", "JISJapanese", "MacKorean", "UTF-8 Unicode", "Standard Unicode", "Mac Cyrillic", "DOS Cyrillic", "DOS Russian", "WindowsCentralEurRoman", "Windows Cyrillic", "KOI8_R", "Mac Chinese Traditional", "Mac Chinese Simplified", "DOS Chinese Traditional", "DOS Chinese Simplified", "GBK", "GB 2312", "GB 18030"}
		set encodings to sort(encodings)
	end tell
	
	-- Figure out which is the index of the "default_encoding" in the "encodings" list
	if default_encoding is in encodings then
		repeat with i from 1 to count of encodings
			if item i of encodings is default_encoding then
				exit repeat
			end if
		end repeat
	else
		-- if the "default_encoding" is not among the encodings then choose the alphabetically first available encoding name
		set i to 1
	end if
	
	set the encoding to choose from list encodings with prompt "Pick an encoding:" default items item i of encodings OK button name "OK" cancel button name "Cancel" without multiple selections allowed and empty selection allowed
	if the result is false then
		return
	end if
	
	-- The linefeed character
	set linefeed to ASCII character 10
	
	-- The whole text of the document
	set whole_document to (the text of the front document) as string
	
	-- The offset of the selection
	set selection_offset to offset of the selection of the front document
	
	-- The length of the selection
	set selection_length to length of the selection of the front document
	
	-- Find and delete a previous encoding specification
	-- (it will not handle more than one specification)
	set searchString1 to "%!TEX encoding ="
	set search1 to (search for searchString1 starting from 0) of front document
	set searchString2 to "% !TEX encoding ="
	set search2 to (search for searchString2 starting from 0) of front document
	
	if search1 * search2 > 0 then
		if search1 < search2 then
			set first_occurrence to search1
		else
			set first_occurrence to search2
		end if
	else if search1 > 0 then
		set first_occurrence to search1
	else
		set first_occurrence to search2
	end if
	if first_occurrence > 0 then
		set offset of selection of front document to (first_occurrence - 1)
		
		-- Get the offset of the line feed (or eof) ending the line containing "% !TEX encoding ="
		-- (here we use a "try" statement to avoid  needing to have a saved file
		-- from which we could get the "eof") 
		set i to first_occurrence
		set end_of_file to false
		set char to character i of whole_document
		repeat while char is not in {linefeed, return}
			set i to i + 1
			try
				set char to character i of whole_document
			on error
				set end_of_file to true
				exit repeat
			end try
		end repeat
		
		-- Detect if the line starts with "% !TEX encoding =" and it is not the last line,
		-- if so we will delete not only "% !TEX encoding =..." but the whole line
		if ((first_occurrence = 1) or (character (first_occurrence - 1) of whole_document is in {linefeed, return})) and not end_of_file then
			set i to i + 1
		end if
		
		set length of selection of front document to (i - first_occurrence)
		-- Delete the line
		set the content of the selection of the front document to ""
		
		-- We will try to restore the selection the user had before invoking this script
		-- so we compute what the new selection_offset should be.
		if (selection_offset  first_occurrence - 1) and (selection_offset < i - 1) then
			set selection_offset to first_occurrence - 1
			set selection_length to 0
		else if selection_offset  i - 1 then
			set selection_offset to selection_offset - (i - first_occurrence)
		end if
	end if
	
	set program to "% !TEX encoding = " & encoding & linefeed
	set selection_offset to selection_offset + (count of program)
	
	-- If the first line starts with "%&" set the insertion offset
	-- to the beginning of the second line.
	try
		set first_line to paragraph 1 of the text of the front document as string
		if the first_line starts with "%&" then
			set insertion_offset to count the characters of the first_line
			try
				get paragraph 2 of the text of the front document
			on error -- There is only one line?
				set selection_offset to selection_offset + 1
				set program to linefeed & program
			end try
		else
			set insertion_offset to 0
		end if
	on error -- The document was empty?
		set insertion_offset to 0
	end try
	
	-- Insert Encoding
	set offset of the selection of the front document to insertion_offset
	set length of the selection of the front document to 0
	set content of the selection of the front document to program
	
	-- Restore the offset of the selection
	set offset of the selection of the front document to selection_offset
	
	-- Restore the length of the selection
	set length of the selection of the front document to selection_length
	
end tell

(* 
http://www.macosxhints.com/article.php?story=20040513173003941
Sort lists in AppleScript using the Unix sort command
Mon, May 17 '04 at 09:13AM • from: erickaterman *)
on sort(the_list)
	set old_delims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {ASCII character 10} -- always a linefeed
	set list_string to (the_list as string)
	set new_string to do shell script "echo " & quoted form of list_string & " | sort -f -u"
	set new_list to (paragraphs of new_string)
	set AppleScript's text item delimiters to old_delims
	return new_list
end sort