Ultimate MS Outlook Editor

matthew's picture

At my work, I'm required to use Microsoft Outlook for exchanging email with my co-workers. At home, I use Mutt on FreeBSD, and have grown to really love the lightning-fast responsiveness, immunity to virusses, and easy scriptability of this tiny text-based mail reader.

I'm going to tell you one solution, just so I can tell you another one :)

It's possible to use Mutt with Microsoft Exchange:

  • Set up IMAP on your Exchange server. This was already done here.
  • Install a copy of Cygwin, including Python.
  • Either set up Mutt to access IMAP on Exchange directly, or do what I prefer to do: download and set up offlineimap. This IMAP-to-Maildir synchronization utility is excellent.
    1. First, you need to run the "rebaseall" utility so that Python doesn't dump with traceback when you try to run offlineimap. You can't rebaseall if you're trying to do it from an rxvt window -- you need to be using the cmd-based Cygwin shell for it to finish without an error.
    2. Then you need make sure your .offlineimaprc file specifies "Curses.Blinkenlights" as the first available interface -- the TK interface, on Win32, just hangs.
  • You can't use offlineimap on a non-managed Cygwin mount. The reason is that the Maildir specification uses the ":" character, which is a big no-no in Windows-land. The solution is to use this command:
    $ mount -f -s -b -o managed "d:/tmp/mail" "/home/of/mail"
    
    substituting the windows-path directory you wish to use for mail for the "d:/tmp/mail" above, and the mount point you wish to put it on instead of "/home/of/mail".
  • Once you have IMAP-to-Maildir synchronization going to your local PC, then you're good to go with offline IMAP stuff and Mutt. Follow the usual directions for configuring Mutt to use the Maildir you've set up, paying particular attention to choice of outbound mailer (probably ssmtp).
Obviously, though I'm a big fan of Mutt, that seemed like a lot of work. Lucky me, I chanced across a script that, with minor modifications, gave me the primary thing I loved about using Mutt: being able to use vim as my text editor. I'm just much faster using that than any other editor, and it's ubiquitous on UNIX systems, either in a more-primitive incarnation of "vi", or in some version.

So I installed Python and the Win32 extensions for Python, then linked this script on my quickbar in Windows, conveniently right next to Outlook:

#!/bin/env python
'''
outlook.pyw (OutLook editor launcher) -- allows one to edit an open e-mail
      mesg from Outlook using Emacs or *Vi* rather than "Notepad--".  :-)
      NOTE:  requires Python 1.6 and newer (use of string methods)

created by John Klassa (klassa at employees.org) on 2001 May 29
updated by Wesley Chun (cyberweb at rocketmail.com) on 2002 Feb 28

$Id: outlook.pyw,v 0.2 2002/08/28 18:04:06 wesc Exp wesc $
'''

from os import spawnv, P_WAIT, unlink
from tempfile import mktemp
from Tkinter import Tk, Button, Frame, Label
from Tkconstants import *
from win32com.client import Dispatch

def launch():
    '''launch() spawns your favorite editor to edit the Outlook compose 
    window (either new or reply), then returns that data to Outlook...
    change the 'ed' variable to switch editors.'''

    # Get a handle to Outlook.
    o = Dispatch("Outlook.Application")

    # Work our way down to the reply (a "MailItem").
    insp = o.ActiveInspector()
    if insp == None: return
    item = insp.CurrentItem
    if item == None: return

    # Grab the message body in the reply.
    body = item.Body

    # Write the body... need to "encode" the string because Outlook uses
    # Unicode with bunch of unprintables (ASCII chars > 128).  Also, since
    # we are going from DOS2UNIX2DOS, we have the \r\n vs \n issue, re-
    # sulting in those fabulous ^M characters.  A persistent, bound-to-a-
    # key Emacs macro takes care of that nicely, but the solution imple-
    # mented here is to just wipe the '\r's now, then add them back when
    # we reread this file back before returning the body to Outlook.
    tmp = mktemp()                  # generate a unique tmp filename
    fh = open(tmp, "w")
    fh.write(body.encode('ascii', 'ignore').replace('\r\n', '\n'))
    fh.close()

    # Launch editor to edit the file (should make this configurable).
    #ed = r"d:\emacs-20.7\bin\emacs"            # emacs editor binary
    ed = r"c:\vim\vim62\gvim.exe"   # *vi*  editor binary
    spawnv(P_WAIT, ed, [ed, tmp])

    # Read edited file back into memory, restore '\r's, and kill tmp file.
    fh = open(tmp)
    body = fh.read().replace('\n', '\r\n')
    fh.close()
    unlink(tmp)

    # Store it as the body of the reply.  Note that we are merely
    # sending this data back to Outlook -- it does not prevent MS from
    # mucking with your message.  For example, it may add your signature
    # again, or it may remove newlines.  MS software... what can you do?
    item.Body = body

# Create the Tk(inter) GUI app with the appropriate label and buttons.
if __name__=='__main__':
    tk = Tk()
    f = Frame(tk, relief=RIDGE, borderwidth=2).pack()
    Label(f, text="Outlook Edit Launcher v0.2").pack()
    Button(f, text="Edit", fg='blue', command=launch).pack(fill=BOTH)
    Button(f, text="Quit", fg='red', command=tk.quit).pack(fill=BOTH)
    tk.mainloop()

I now click Outlook, then click my outlook.py script. I minimize the annoying black cmd window that comes up (anybody know how to get rid of this?), and I now have a little Python/TK window with a convenient "edit" button on it. When I compose a message in LookOut, I click this "edit" button, and up pops gvim 6.2, ready for me to type the message. When I'm done typing it, I just write-quit out of gvim, and the text pops up in my Outlook compose window.

Convenient! Well, for a UNIX-geek at least.

Anyway, I'm still torn. Do I really need to use Outlook here? Realistically, I have maybe one meeting a week that I need to keep track of, and that's easily done in my Palm. Maybe I should just use Mutt in Cygwin on a managed mount? Who knows, but both are valid choices. And in a world where MS wants you to only use MS products, and those products are funkily generic and slow, it's nice to have choices.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Sammy G's picture

That's so 1990s

Matt, c'mon man, who isn't using Mutt in Cygwin on a manager mount these days? Get with the times dude.

Here's a question: say a small firm is setting up an office for 5 employees. The set up is going to be a server-client network (no shared apps). Do you recommend going with a MS Windows or Mac OS system? Are there choices in buying out-of-the-box or configurable servers and workstations that can house popular software, don't cost an arm and a leg and give choice?

Wondering if you can go out and buy the computing pieces and then run a freeware OS and pick and choose your components...and if it makes compatibility and cost sense...

BTW -- I'm not trying to diminish the genius of your original post, it's just that I don't understand it. :)

matthew's picture

Well, you brought up a very g

Well, you brought up a very general topic. So I'm going to give generic advice for setting up a small office network on the cheap.

The first thing to realize is that "freeware", or "open source" is only free if your time is worth nothing. If you know nothing about what you're doing, you'll be paying a consultant to do it right regardless of what platform you choose. You can do it "on the cheap" on your own, but you'll be learning a lot as you do so :)

There are several basic components to any office setup, some of which may be optional depending on your situation and type of business:

    Infrastructure:
  • Electronic Mail System
  • Shared calendaring system
  • Telephone (PBX) System
  • Fax system
  • File-Sharing
  • Web presence (lots to this, depending on what you wish to do)
  • Switch, router, and firewall
  • Documentation management
  • Customer Relationship Management
  • Web browser
  • Email reader
  • Office suite
  • Domain-specific applications (Photoshop for the artist, Lightwave for the modeler, etc.)
  • Accounting package(s)
  • Project management

With all of these, you can pick-and-choose where you want technology to assist you, and where you wish to do things by hand. You can also choose to outsource much of it, pick a closed-source application, or pick an open-source app that you can modify to suit your needs.

My default rule in new buildouts is to use open-source ("free" or "libre") software wherever possible. I can make that default choice without additional justification if it's capable of meeting the needs of the client. If I must choose a proprietary application (such as Microsoft Exchange), I then need to give justifications for that choice.

For desktops, if it is feasible, I would choose GNU/Linux. Which distribution is probably irrelevant, but for ease of updating, and due to some idealistic concerns regarding free software, I would probably pick Debian.

If I had to choose between MacOSX and Windows, I would pick MacOSX in a heartbeat. At its core, it is a UNIX-based operating system. It is also less popular than MS Windows, and in this age of monoculture computer virusses, that alone is an excellent justification. It has all the domain-specific apps people need in a creative workshop, runs on standardized hardware that, while expensive, has a much lower failure rate than commodity PCs, and has a definite sex appeal :)

On the server side, I'd buy one really fast, capable dual-processor PC with 2 GB+ RAM, a 64-bit processor (AMD or Intel), running GNU/Linux. Possibly, if you want to stay an all-Mac shop, a Mac rackable G5 server would be a good choice for this, too. Run all the critical services on this one box, and maybe set up a second one with an identical configuration so you have a backup in case the primary fails.

I could write an essay about this, so I'll stop now.

--
Matthew P. Barnson

--
Matthew P. Barnson

weed's picture

The MS Way

Matt,

Try this:

  1. Copy the following into a file and name it 'launchvim.vbs'
    Option Explicit
    
    Private Sub launch()
    
          Const TemporaryFolder = 2
    
          Dim ws, ol, insp, item, body, fso, tempfile, tfolder, tname, tfile
    
          Set ol = CreateObject("Outlook.Application")
    
          Set insp = ol.ActiveInspector
          If insp Is Nothing then
                Exit Sub
          End if
          Set item = insp.CurrentItem
          If item Is Nothing then
                Exit Sub
          End if
    
          body = CStr(item.Body)
    
          Set fso = CreateObject("Scripting.FileSystemObject")
          Set tfolder = fso.GetSpecialFolder(TemporaryFolder)
          tname = fso.GetTempName
          Set tfile = tfolder.CreateTextFile(tname)
          tfile.Write( Replace( body, Chr(13) & Chr(10), Chr(10) ) )
          tfile.Close()
    
          Set ws = WScript.CreateObject("WScript.Shell")
          Wsh.Echo( "c:\vim\vim62\gvim.exe " & tfolder.Path & "\" & tname )
          ws.Run "c:\vim\vim62\gvim.exe " & tfolder.Path & "\" & tname ,4, true
    
          Set tfile = fso.OpenTextFile(tfolder.Path & "\" & tname, 1 )
          item.body = Replace( tfile.ReadAll, Chr(10), Chr(13) & Chr(10) )
          tfile.close()
    
          fso.DeleteFile( tfolder.Path & "\" & tname )
    
    End Sub
    
    Call launch()
    
    
  2. In Outlook, Go To Tools->Macros->VB Editor (Make sure your Security settings for Outlook are set to Medium)
  3. Add a new module, and paste this into it
    Sub LaunchVIM()
    
        Dim windir As String
    
        windir = Environ("WinDir")
    
        Shell (windir & "\system32\cscript.exe " & windir & "\system32\launchvim.vbs")
    
    End Sub
    
    
  4. Open a new Outlook mail message
  5. Click View->Toolbars->Customize
  6. Under the Commands tab, Select Macros on the left, and drag the macro you just created to the Outlook toolbar in your newly opened mail dialog.
Voila! Now you can launch vim from the Outlook toolbar!

EDIT by matthew: cleaned up formatting for slightly easier readability.

My $.02
Weed

matthew's picture

SWEET!

Pretty sweet, dude. I now have a "Project1.LaunchVIM" button on my toolbar. Unfortunately, setting security to Medium violates our corporate security policy. So I reset it back to High after installing the button, and the button continues to work fine.

So, for future security-conscious readers, set to Medium to install the script, then back to High and your script will continue to run without problems. How long did it take you to whip that out, Weed? I know next to nothing about Visual Basic, but it is visually much cleaner (and easier to install) than a separate Python window with an "EDIT" button :)

--
Matthew P. Barnson

--
Matthew P. Barnson

weed's picture

Uh-oh

Matt

The security feature of the macros takes place after the next restart, so more than likely the next time you open Outlook your button won't work.

I'll look into signing the code so it works with High. You may have to install my company's cert authority tho, 'cause I'm not paying Veri$ign to sign it.

As for VBScript, it's not hard. http://msdn.microsoft.com/ has a bunch of information on it, but, as with all Microsoft, you have to learn how to search for it.

Look here:
http://www.microsoft.com/technet/prodtechnol/office/office2000/maintain/...

My $.02
Weed

matthew's picture

Roger that

Yeah, just fired up Outlook again, and the button does nothing. Durn.

For now, I'm continuing to use my offlineimap/Mutt/Cygwin solution. It works very well to keep the folders synchronized, but stuff like seeing other users' folders just doesn't work at all, so I have to keep Outlook around.

--
Matthew P. Barnson

--
Matthew P. Barnson

Change the .py to .pyw

Getting rid of the python console is easy - change the file extension. The app will work and the console will not be spawned.

matthew's picture

.py to .pyw

Changing the file extension to .pyw worked like a champ for getting rid of the console window; thanks for the tip!

--
Matthew P. Barnson

--
Matthew P. Barnson

Restoring the text format

Hi Weed, this script works well for me. It is very useful and productive for Vim fans like me! I am looking for one more feature. Right now, when I return back from my Vim session the file type is set to 'rich text' irrespective of the state before editing in vim. Is it possible to restore the text format. If that is not possible, how to set it to 'plain text' which makes more sense when we edit using vim (the nice indentations will show up the same way in outlook)

Thanks
--Mahesh N

How to sign it

See this page
for how to sign the thing. Working for me now.

--
Paul Wright

EDIT by matthew: linked.

matthew's picture

Mail format

Unfortunately, this is a change you have to make in Outlook, not in your configuration for using VIM.

In Outlook, go to the Tools menu and select Options. Click the "Mail Format" tab, and change the "Compose in this message format" from "Rich Text" to "Plain Text". The problem is then solved, and you have your nice indentation and mail config.

I'm in this same boat again today, since I'm working a new job where they use Outlook exclusively. And, in this case, Outlook is extremely tied-in to their basic management systems, so using Mutt to the exclusion out Outlook is no longer an option (sigh)... So I came back to this page this morning to remember how I did it!

Anyway, changing those options will do the trick. The one annoyance left is that with the latest patches to Outlook, every time I launch this I get a prompt saying "A program is trying to access your Address Book", and I have to click "Yes" to allow it to run. It's only one extra click, but I do this in part for convenience. I've been digging around trying to figure out how to turn this off for a signed, truested vbscript, but no luck.

However, the tips above on signing your own code work great to make it work appropriately, with the exception of that annoying pop-up every time I compose a mail message.

The price I pay for being a UNIX geek, I guess... maybe I'll go back to using Mutt on Cygwin for email, and just use LookOut for calendars, contacts, etc.

--
Matthew P. Barnson

--
Matthew P. Barnson

what if we don't have gvim installed?

I use non-gui version of vim under Windows XP + cygwin, and I am not willing to install another windows version gvim at the moment. Is it possible to tailor these scripts so that it works under such environment?

I am always wanting tweaks such that whenever windows calls for a text editor, it invokes rxvt + vim, is this possible?

Thanks,

Jindan

matthew's picture

Yes, replacement

Jindan,

Yes, replacement is trivially easy in each of these scripts in order to use the cygwin version of vim instead of the native Win32 gvim. Simply everywhere it currently calls c:\some_path\bin\vim, replace it with c:\your_cygwin_path\bin\rxvt -e vim.

For instance, in my case, my Cygwin root is in d:\cygwin. I would replace this line:

ed = r"c:\vim\vim62\gvim.exe"   # *vi*  editor binary

with this one:

ed = r"d:\cygwin\bin\rxvt.exe -e vim"   # *vi*  editor binary

Just tested it, done and done. So the Python version is figured out; you'd need to adjust it similarly if you were to use Weed's Visual Basic version on the parent page. I'm not using either one anymore, at the moment, because I'm so sick of Outlook. I went back to using OfflineIMAP + Mutt on a Cygwin managed mount because it's so much faster, and I can run it remotely without having to use some sort of remote desktop. If I get an appointment in my inbox that requires their synchronization tool, I note the time of the appointment in my Palm Pilot, and next time I'm in the office I might fire up Outlook to confirm the appointment (or just show up; people around here rarely seem to care if you actually RSVP for the meeting or not).

Curiously, my new company's Exchange server doesn't create nearly the havoc with offlineimap that the old one did. I wonder if they improved their IMAP support in the latest version?

--
Matthew P. Barnson

--
Matthew P. Barnson

That is so cool!

This is what I did, first I created vim.bat in c:\program files\cygwin\bin with this line:

start rxvt -sr -sl 2500 -geometry 90x30 -fg grey70 -bg midnightblue -fn "Lucida ConsoleP-16" -e vim %1

Then I changed the View Source program from Notepad to vim.bat, worked out like a charm! Since many of the IE temp file doesn't have an extension file name, I need to manually type

set syntax=html

to enable syntax highlighting each time. Trying to figure out a workaround now.

Weed's code doesn't work out (yet), when I press the macro button, the screen flashed as if something happening, but then nothing. Is there a log that I can check in VB editor or Outlook so that I can tell what happened?

matthew's picture

syntax highlighting

Try adding these lines to your $HOME/.vimrc file (this varies according to installation, the easiest way is to just do "vi ~/.vimrc" from a cygwin shell):

"turn on syntax highlighting
:syntax on

Now it's possible that vim may not recognize your terminal type. In order to work around this (like if syntax highlighting won't turn on from this one addition to your .vimrc), then try adding these to your ~/.vimrc:

"fix inability to read term type
:set term=xterm-color

--
Matthew P. Barnson

--
Matthew P. Barnson

I think the problem is with ...

That the IE temporary files are sometimes without an explicit extension name, i.e. .html, .htm, etc., thus vim can't find a proper syntax highlighting scheme, even though I have "syntax on" set in my .vimrc file.

Okay, the prolem is solved by ...

modifying my vim.bat as followed:

start rxvt -sr -sl 2500 -geometry 90x30 -fg grey70 -bg midnightblue -fn "Lucida ConsoleP-16" -e vim -c "set syntax=html" %1

Thanks, Matt!

matthew's picture

syntax=mail

You'll get even better results with syntax highlighting if you do a:

vim -c "set syntax=mail" %1

Vim's very smart about email syntax, understanding quoting and such. Since I prefer a dark background with light text, I'd add this to my .vimrc as well:

:colorscheme murphy

Other light-on-dark colorschemes that work well are "torte", "evening", and "ron".

Good luck!

:wq!

--
Matthew P. Barnson

--
Matthew P. Barnson

Alternatively

Since Windows runs programs based on extension and not MIME-type, setting the first line in the script to:

#!c:\python24\pythonw.exe 

will do the same thing.

Python for Windows associates *.py with python.exe and *.pyw with pythonw.exe.

The Python code strips accented letters from Outlook

fh.write(body.encode('ascii', 'ignore').replace('\r\n', '\n'))
likely is the reason that accented letters like é in Gérard end up being dropped :-(
This severely limits an otherwise very good call to VIM for Outlook.

Any fix?

matthew's picture

encoding...

I'd think replacing "ascii" with a Unicode encoding such as "Latin-1" might do the trick, or, more likely, eliminate the body.encode call entirely and try just doing an fh.write. Unfortunately, I've stopped using this program for "real" work, so I don't have a way to test it.

You'll also have to make sure your Vim is set up to handle Unicode, which is an area where I have to claim utter ignorance :)

Additionally, I don't know that the whole stripping \r\n thing is even necessary in the Windows version of Vim today. The one I'm running now handles DOS-formatted files without a hiccup.

--
Matthew P. Barnson

--
Matthew P. Barnson

Weed's code

It doesn't work for me (yet). I tried debugging the script and found that the GetInspector methor returns "Nothing" - I have Microsoft Outlook 2003. I went to outlookcode.com and obtained a few test scripts - all of them exit with the same result - GetInspector returns nothing. Does anyone have any clues to offer?

Thanks in advance,
Girish

No replies yet?

:(

Problem with VBS

Hi,

I successfully created the launchvim.vbs script and the acompanying VB Makro. But vim doesn't start when clicking on the macro-button in the toolbar. Does anyone have a clue?

I'm using Outlook 2003 and VIM 7.0

weed's picture

Here's the new version

All,

I changed the code up a bit. Here are the new steps.

1) In Outlook, click Tools->Macro->Visual Basic Editor
2) Under Tools->References, make sure Microsoft Scripting Runtime is selected. Close out of the dialog
3) Either create a new module or use and existing one
4) Paste the following code into the module:

Option Explicit

Private Type STARTUPINFO
   cb As Long
   lpReserved As String
   lpDesktop As String
   lpTitle As String
   dwX As Long
   dwY As Long
   dwXSize As Long
   dwYSize As Long
   dwXCountChars As Long
   dwYCountChars As Long
   dwFillAttribute As Long
   dwFlags As Long
   wShowWindow As Integer
   cbReserved2 As Integer
   lpReserved2 As Long
   hStdInput As Long
   hStdOutput As Long
   hStdError As Long
End Type

Private Type PROCESS_INFORMATION
   hProcess As Long
   hThread As Long
   dwProcessID As Long
   dwThreadID As Long
End Type

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
   hHandle As Long, ByVal dwMilliseconds As Long) As Long

Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
   lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
   lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
   ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
   ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
   lpStartupInfo As STARTUPINFO, lpProcessInformation As _
   PROCESS_INFORMATION) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _
   hObject As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&

Sub LaunchVIM()

    'Dim windir As String

    'windir = Environ("WinDir")

    'Shell (windir & "\system32\cscript.exe " & windir & "\system32\launchvim.vbs")
    
    Const TemporaryFolder = 2
    Const VIMLocation = "C:\Program Files\Vim\vim70\gvim.exe"

    Dim ol, insp, item, body, fso, tempfile, tfolder, tname, tfile, appRef, x

    Set ol = Application

    Set insp = ol.ActiveInspector
    If insp Is Nothing Then
        Exit Sub
    End If
    Set item = insp.CurrentItem
    If item Is Nothing Then
        Exit Sub
    End If

    body = CStr(item.body)

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set tfolder = fso.GetSpecialFolder(TemporaryFolder)
    tname = fso.GetTempName
    Set tfile = tfolder.CreateTextFile(tname)
    tfile.Write (Replace(body, Chr(13) & Chr(10), Chr(10)))
    tfile.Close

    ExecCmd VIMLocation & " " & Chr(34) & tfolder.Path & "\" & tname & Chr(34)

    Set tfile = fso.OpenTextFile(tfolder.Path & "\" & tname, 1)
    item.body = Replace(tfile.ReadAll, Chr(10), Chr(13) & Chr(10))
    tfile.Close

    fso.DeleteFile (tfolder.Path & "\" & tname)

End Sub

Public Sub ExecCmd(cmdline$)
    
    Dim proc As PROCESS_INFORMATION
    Dim start As STARTUPINFO
    Dim ReturnValue As Integer

    ' Initialize the STARTUPINFO structure:
    start.cb = Len(start)

    ' Start the shelled application:
    ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
      NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

    ' Wait for the shelled application to finish:
    Do
        ReturnValue = WaitForSingleObject(proc.hProcess, 0)
        DoEvents
    Loop Until ReturnValue <> 258

    ReturnValue = CloseHandle(proc.hProcess)
    
End Sub

Now follow the above intructions on creating a toolbar button that launches the Macro "LaunchVIM"

This method keeps everything in VBA and strips out the VBScript external application as well as the WSH junk.

This post used massive amounts of cut-and-paste programming from examples provided at the MS MSDN site. All the answers are there, however finding them is the trick. ;)

My $.02
Weed

My $.02
Weed

matthew's picture

Colorized!

And, of course, the preceding code... colorized!

Yeah, I'm useless. But I like coloring books.

Option Explicit

Private Type STARTUPINFO
   cb As Long
   lpReserved As String
   lpDesktop As String
   lpTitle As String
   dwX As Long
   dwY As Long
   dwXSize As Long
   dwYSize As Long
   dwXCountChars As Long
   dwYCountChars As Long
   dwFillAttribute As Long
   dwFlags As Long
   wShowWindow As Integer
   cbReserved2 As Integer
   lpReserved2 As Long
   hStdInput As Long
   hStdOutput As Long
   hStdError As Long
End Type

Private Type PROCESS_INFORMATION
   hProcess As Long
   hThread As Long
   dwProcessID As Long
   dwThreadID As Long
End Type

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
   hHandle As Long, ByVal dwMilliseconds As Long) As Long

Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
   lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
   lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
   ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
   ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
   lpStartupInfo As STARTUPINFO, lpProcessInformation As _
   PROCESS_INFORMATION) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _
   hObject As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&

Sub LaunchVIM()

    'Dim windir As String

    'windir = Environ("WinDir")

    'Shell (windir & "\system32\cscript.exe " & windir & "\system32\launchvim.vbs")

    Const TemporaryFolder = 2
    Const VIMLocation = "C:\Program Files\Vim\vim70\gvim.exe"

    Dim ol, insp, item, body, fso, tempfile, tfolder, tname, tfile, appRef, x

    Set ol = Application

    Set insp = ol.ActiveInspector
    If insp Is Nothing Then
        Exit Sub
    End If
    Set item = insp.CurrentItem
    If item Is Nothing Then
        Exit Sub
    End If

    body = CStr(item.body)

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set tfolder = fso.GetSpecialFolder(TemporaryFolder)
    tname = fso.GetTempName
    Set tfile = tfolder.CreateTextFile(tname)
    tfile.Write (Replace(body, Chr(13) & Chr(10), Chr(10)))
    tfile.Close

    ExecCmd VIMLocation & " " & Chr(34) & tfolder.Path & "\" & tname & Chr(34)

    Set tfile = fso.OpenTextFile(tfolder.Path & "\" & tname, 1)
    item.body = Replace(tfile.ReadAll, Chr(10), Chr(13) & Chr(10))
    tfile.Close

    fso.DeleteFile (tfolder.Path & "\" & tname)

End Sub

Public Sub ExecCmd(cmdline$)

    Dim proc As PROCESS_INFORMATION
    Dim start As STARTUPINFO
    Dim ReturnValue As Integer

    ' Initialize the STARTUPINFO structure:
    start.cb = Len(start)

    ' Start the shelled application:
    ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
      NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

    ' Wait for the shelled application to finish:
    Do
        ReturnValue = WaitForSingleObject(proc.hProcess, 0)
        DoEvents
    Loop Until ReturnValue  258

    ReturnValue = CloseHandle(proc.hProcess)

End Sub


--
Matthew P. Barnson

--
Matthew P. Barnson

weed's picture

Do Tell

How did ye colorize it?

Weed

My $.02
Weed

matthew's picture

Copy/paste

I use.