invert screen colors, works properly with any number of displays

I often work on my computer at night and sometimes the screen is just too bright so I like to invert the colors to have a darker display. When I’m only reading text this seems to be a great way to work. I’ve seen other scripts which invert your screen but none of them properly restored my desktop back to original settings when I re-inverted the screen back to normal. Mostly this was because I have 2 displays connected to my computer and the other scripts didn’t take that into account. This one does. It works for any number of displays you have attached to your computer. It even works if your desktop is set to change its picture periodically.

Any improvements or comments are welcome.

(*This is a "toggle" script... it will toggle between inverted screen colors and not-inverted screen colors on successive runs. It will work with any number of displays you have connected to your computer.*)
(* When your screens are inverted, the script will store the state of your current desktops for each display you have connected to your computer. It will set the desktop picture of each display to a white image so that when inverted your desktops will appear black. When the screen is returned to normal it will restore the stored desktop settings so your desktops appears like they were before you inverted them.*)

property prefFile : (path to preferences as string) & "com.apple.desktop.plist"
property invertPic : "/Library/Desktop Pictures/Solid Colors/Solid White.png"
property desktopPics : {}
property changeStates : {}
property displayIDs : {}
property is_inverted : false

if not my prefFile_check(prefFile) then return -- check for the needed pref file and stop if it doesn't exist

if is_inverted then -- screens are inverted so set them back to normal with persistent values of previous normal state
	tell application "System Events"
		repeat with i from 1 to (count of displayIDs)
			try
				set value of property list item "ImageFilePath" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile to (item i of desktopPics)
				set value of property list item "Change" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile to (item i of changeStates)
			end try
		end repeat
	end tell
	my invert_screen()
	set is_inverted to false
else -- screens are normal so store current desktop values and set screens to an inverted state
	set {desktopPics, changeStates, displayIDs} to {{}, {}, {}}
	set displayIDs to my get_displayIDs() -- get display ids for currently connected displays
	if displayIDs is false then return
	tell application "System Events"
		repeat with i from 1 to (count of displayIDs)
			try -- store current normal values for currently connected displays
				set end of desktopPics to value of property list item "ImageFilePath" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile
			on error
				tell me to display alert "Error. A needed setting is missing!" message "Please open the \"Desktop & Screensaver\" preference pane and change your desktop picture for each of your displays because this action will create the missing setting." & return & return & "Note: you only have to do this once. You can change your desktop picture to anything you want and then change it right back to its original setting if you wish." as warning
				return
			end try
			try -- prepare for inverted state by setting desktop pics to invertPic and change states to "Never"
				set value of property list item "ImageFilePath" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile to invertPic
				set end of changeStates to value of property list item "Change" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile
				set value of property list item "Change" of property list item (item i of displayIDs) of property list item "Background" of property list file prefFile to "Never"
			end try
		end repeat
	end tell
	my invert_screen()
	set is_inverted to true
end if


(*================== SUBROUTINES ====================*)
on get_displayIDs()
	-- this returns a list of the id numbers for each display connected to your computer
	-- this needs the number_to_text subroutine to work
	try
		set plistFolderPath to (path to preferences folder as string) & "ByHost:"
		tell application "Finder" to set plistName to (name of files of folder plistFolderPath whose name contains "com.apple.windowserver") as string
		set plistPath to plistFolderPath & plistName
		tell application "Image Events" to set count_of_displays to count of displays
		set j to 1
		repeat
			set displayIDs to {}
			tell application "System Events" to set displaySet to value of property list item j of property list item "DisplaySets" of property list file plistPath
			try
				repeat with i from 1 to count_of_displays
					set expID to |DisplayID| of (item i of displaySet)
					set stringID to my number_to_text(expID)
					set end of displayIDs to stringID
				end repeat
				exit repeat
			on error
				set j to j + 1
			end try
		end repeat
		return displayIDs
	on error
		set frontApp to displayed name of (info for (path to frontmost application))
		tell application frontApp to display alert "Error. A needed file is missing!" message "Please make some changes to the settings in the \"Displays\" preference pane because this action will create the missing file." & return & return & "Note: you only have to do this once. You can make any change in the preference pane (which will create the needed file) and then you can change the setting right back if you wish." as warning
		return false
	end try
end get_displayIDs

on number_to_text(this_number)
	(*This subroutine will convert any number to a string of numeric characters. This is a modified version of a subroutine found at http://www.apple.com/applescript/guidebook/sbrt/pgs/sbrt.08.htm. Apple's original version deleted all the decimal places from the number, this one keeps them.*)
	set this_number to this_number as text
	if this_number contains "E+" then
		set x to the offset of "." in this_number
		set y to the offset of "+" in this_number
		set z to the offset of "E" in this_number
		set the decimal_adjust to characters (y - (length of this_number)) thru ¬
			-1 of this_number as string as number
		if x is not 0 then
			set the first_part to characters 1 thru (x - 1) of this_number as string
		else
			set the first_part to ""
		end if
		set the second_part to characters (x + 1) thru (z - 1) of this_number as string
		set the converted_number to the first_part
		set decimal_added to false
		repeat with i from 1 to the (length of second_part)
			try
				set the converted_number to ¬
					the converted_number & character i of the second_part
			on error
				set the converted_number to the converted_number & "0"
			end try
			if decimal_added is false and (i mod decimal_adjust) is 0 and (i is not (length of second_part)) then
				set the converted_number to the converted_number & "."
				set decimal_added to true
			end if
		end repeat
		return the converted_number
	else
		return this_number
	end if
end number_to_text

on prefFile_check(prefFile)
	try
		set test_for_prefFile to alias prefFile
		return true
	on error
		set frontApp to displayed name of (info for (path to frontmost application))
		tell application frontApp to display alert "Error. A needed file is missing!" message "Please open the \"Desktop & Screensaver\" preference pane and change the desktop picture for each of your displays because this action will create the missing file." & return & return & "Note: you only have to do this once. You can change your desktop picture to anything you want and then change it right back to its original setting if you wish." as warning
		return false
	end try
end prefFile_check

on invert_screen()
	tell application "System Events" to key code 28 using {command down, control down, option down}
end invert_screen

I often prefer working in the inverse mode on my laptop, but sometimes I need to work in the “normal” color mode. I usually have a lot of terminal windows open and usually want them black in either mode. I also use an image I like in both modes on my desktop, using an inverted version of it in inverse mode so that it comes out the same in either mode. Wrote this script to change all of it in one stroke. I use quicksilver to trigger it with a apple-ctrl-8 as I’m used to doing apple-opt-ctrl-8 to invert. When run the screen is inverted, the settingset of all terminal windows and the default is switched to the settingset which isn’t active already (of those set in the top of the script) and likewise switches the desktop image to what’s specified in the top of the file that isn’t already active. It’s not as general as yours regulus6633, but it’s short simple and gets the job done for one or two monitors (I like to attach a second monitor when I can). This is my first applescript so it might not be as polished as it could be, but I thought it might be good to post anyway.

#!/usr/bin/osascript
(************ system dependent stuff that must be customized ********)
----------------Set Paths for Desktop images-------------------
set idpic to "Macintosh HD:Library:Desktop Pictures:Black & White:Mojave-invr.jpg" --path to use in inverse mode
set dpic to "Macintosh HD:Library:Desktop Pictures:Black & White:Mojave.jpg"   --path to use in "normal" mode
---------------- Set Names of termianl settingsets ---------------
set ss1 to "black" -- name of first terminal settingsset
set ss2 to "black in black" -- name of second terminal settingsset
------------------------------------------------------------------

(********** invert the screen ********)
tell application "System Events"
  tell application processes
    key code 28 using {command down, option down, control down}
  end tell
end tell

(***** switch the terminal window color settings *****)
-- just switches to the settingset which isn't currently active 
tell application "Terminal"
  if default settings is equal to settings set ss1 then
    set settingsSet to ss2
  else if default settings is equal to settings set ss2 then
    set settingsSet to ss1
  end if
  set default settings to settings set settingsSet
  repeat with w in every window
    set current settings of w to settings set settingsSet
  end repeat
end tell

(************ set the desktop image(s) *************)
-- just sets the opposte space image to whatever is currently set
tell application "System Events"
   tell desktop 1
       set currentpic to picture as alias
       if path of currentpic is idpic then
   	  set picture to dpic
       else
          set picture to idpic	
       end if
   end tell
   try -- if there is a second monitor do the same for it
      tell desktop 2
        set currentpic to picture as alias
      	if path of currentpic is idpic then
          set picture to dpic
        else
          set picture to idpic
       end if
     end tell
   end try
end tell

Model: macbook pro
Browser: Camino (nightly build)
Operating System: Mac OS X (10.5)