Thanks Axel Schneider, that's the ticket. I did't think of disabling it in the native NSTextView. At first I was doing a bunch of ReplaceAll() calls, but clearly, that's a lot of processing to undo what the OS is doing, and the correct answer is to simply turn off the automatic stuff in the first place.
After playing with it for a while, I discovered that I also needed to turn off not only smart quotes, but also smart dashes and other automatic substitutions (like the user's own defined substitutions). So, I ended up setting a few more of NSTextView's flags:
#if TargetCocoa then
declare function NSClassFromString lib "Cocoa" (aClassName as CFStringRef) as Ptr
declare function documentView lib "Cocoa" selector "documentView" _
(obj_id as Integer) as Ptr
declare sub setAutomaticQuoteSubstitutionEnabled lib "Cocoa" _
selector "setAutomaticQuoteSubstitutionEnabled:" _
(id as ptr, value as Boolean)
declare sub setAutomaticDashSubstitutionEnabled lib "Cocoa" _
selector "setAutomaticDashSubstitutionEnabled:" _
(id as ptr, value as Boolean)
declare sub setAutomaticTextReplacementEnabled lib "Cocoa" _
selector "setAutomaticTextReplacementEnabled:" _
(id as ptr, value as Boolean)
dim myTextArea as ptr = documentView(self.Handle)
setAutomaticQuoteSubstitutionEnabled(myTextArea, value)
setAutomaticDashSubstitutionEnabled(myTextArea, value)
setAutomaticTextReplacementEnabled(myTextArea, value)
#endif