diff --git a/Frameworks/DocumentWindow/src/DocumentController.mm b/Frameworks/DocumentWindow/src/DocumentController.mm
index 39758e2c..bed7a26e 100644
--- a/Frameworks/DocumentWindow/src/DocumentController.mm
+++ b/Frameworks/DocumentWindow/src/DocumentController.mm
@@ -837,7 +837,7 @@ NSString* const kUserDefaultsFileBrowserPlacementKey = @"fileBrowserPlacement";
// = Document Action Methods =
// ===========================
-- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath contextInfo:(void*)info
+- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM
{
if(!aPath)
return;
@@ -849,6 +849,10 @@ NSString* const kUserDefaultsFileBrowserPlacementKey = @"fileBrowserPlacement";
ASSERT_LT(0, paths.size());
[self selectedDocument]->set_path(paths[0]); // FIXME check if document already exists (overwrite)
+ [self selectedDocument]->set_disk_encoding(encoding);
+ [self selectedDocument]->set_disk_newlines(newlines);
+ [self selectedDocument]->set_disk_bom(useBOM);
+
[DocumentSaveHelper trySaveDocument:self.selectedDocument forWindow:self.window defaultDirectory:nil andCallback:NULL];
if(paths.size() > 1)
@@ -858,6 +862,9 @@ NSString* const kUserDefaultsFileBrowserPlacementKey = @"fileBrowserPlacement";
{
documents.push_back(document::create(paths[i]));
documents.back()->open(); // so that we find this when going to counterpart
+ documents.back()->set_disk_encoding(encoding);
+ documents.back()->set_disk_newlines(newlines);
+ documents.back()->set_disk_bom(useBOM);
}
[self addDocuments:documents andSelect:kSelectDocumentNone closeOther:NO pruneTabBar:NO];
@@ -870,18 +877,20 @@ NSString* const kUserDefaultsFileBrowserPlacementKey = @"fileBrowserPlacement";
- (IBAction)saveDocument:(id)sender
{
D(DBF_DocumentController, bug("%s\n", [self selectedDocument]->path().c_str()););
- if([self selectedDocument]->path() != NULL_STR)
- [DocumentSaveHelper trySaveDocument:self.selectedDocument forWindow:self.window defaultDirectory:nil andCallback:NULL];
- else [OakSavePanel showWithPath:DefaultSaveNameForDocument([self selectedDocument]) directory:self.untitledSavePath fowWindow:self.window delegate:self contextInfo:NULL];
+ document::document_ptr doc = [self selectedDocument];
+ if(doc->path() != NULL_STR)
+ [DocumentSaveHelper trySaveDocument:doc forWindow:self.window defaultDirectory:nil andCallback:NULL];
+ else [OakSavePanel showWithPath:DefaultSaveNameForDocument(doc) directory:self.untitledSavePath fowWindow:self.window delegate:self encoding:doc->disk_encoding() newlines:doc->disk_newlines() useBOM:doc->disk_bom()];
}
- (IBAction)saveDocumentAs:(id)sender
{
D(DBF_DocumentController, bug("%s\n", [self selectedDocument]->path().c_str()););
- std::string const documentPath = [self selectedDocument]->path();
+ document::document_ptr doc = [self selectedDocument];
+ std::string const documentPath = doc->path();
NSString* documentFolder = [NSString stringWithCxxString:path::parent(documentPath)];
NSString* documentName = [NSString stringWithCxxString:path::name(documentPath)];
- [OakSavePanel showWithPath:(documentName ?: DefaultSaveNameForDocument([self selectedDocument])) directory:(documentFolder ?: self.untitledSavePath) fowWindow:self.window delegate:self contextInfo:NULL];
+ [OakSavePanel showWithPath:(documentName ?: DefaultSaveNameForDocument(doc)) directory:(documentFolder ?: self.untitledSavePath) fowWindow:self.window delegate:self encoding:doc->disk_encoding() newlines:doc->disk_newlines() useBOM:doc->disk_bom()];
}
- (IBAction)saveAllDocuments:(id)sender
diff --git a/Frameworks/DocumentWindow/src/DocumentSaveHelper.mm b/Frameworks/DocumentWindow/src/DocumentSaveHelper.mm
index 0dc36b8b..945d1318 100644
--- a/Frameworks/DocumentWindow/src/DocumentSaveHelper.mm
+++ b/Frameworks/DocumentWindow/src/DocumentSaveHelper.mm
@@ -44,7 +44,7 @@ namespace
D(DBF_DocumentController_SaveHelper, bug("\n"););
init(context);
- [OakSavePanel showWithPath:DefaultSaveNameForDocument(_document) directory:_self.saveFolder fowWindow:_window delegate:_self contextInfo:NULL];
+ [OakSavePanel showWithPath:DefaultSaveNameForDocument(_document) directory:_self.saveFolder fowWindow:_window delegate:_self encoding:_document->disk_encoding() newlines:_document->disk_newlines() useBOM:_document->disk_bom()];
}
void select_make_writable (std::string const& path, io::bytes_ptr content, file::save_context_ptr context)
@@ -197,12 +197,15 @@ namespace
// = Sheet Callbacks =
// ===================
-- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath contextInfo:(void*)info
+- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM
{
D(DBF_DocumentController_SaveHelper, bug("%s\n", to_s(aPath).c_str()););
if(aPath)
{
documents.back()->set_path(to_s(aPath));
+ documents.back()->set_disk_encoding(encoding);
+ documents.back()->set_disk_newlines(newlines);
+ documents.back()->set_disk_bom(useBOM);
context->set_path(to_s(aPath));
}
else
diff --git a/Frameworks/OakAppKit/resources/English.lproj/EncodingSaveOptions.xib b/Frameworks/OakAppKit/resources/English.lproj/EncodingSaveOptions.xib
new file mode 100644
index 00000000..1063898e
--- /dev/null
+++ b/Frameworks/OakAppKit/resources/English.lproj/EncodingSaveOptions.xib
@@ -0,0 +1,583 @@
+
+
+
+ 1070
+ 12A269
+ 2549
+ 1187
+ 624.00
+
+
+ NSButton
+ NSButtonCell
+ NSCustomObject
+ NSCustomView
+ NSMenu
+ NSMenuItem
+ NSPopUpButton
+ NSPopUpButtonCell
+ NSTextField
+ NSTextFieldCell
+ NSUserDefaultsController
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+
+
+
+
+
+
+ YES
+
+
+
+
+
+
+ view
+
+
+
+ 228
+
+
+
+ encodingPopUpButton
+
+
+
+ 238
+
+
+
+ selectedTag: lineEndings
+
+
+
+
+
+ selectedTag: lineEndings
+ selectedTag
+ lineEndings
+
+ NSValueTransformerName
+ OakLineEndingsTransformer
+
+ 2
+
+
+ 247
+
+
+
+ value: useByteOrderMark
+
+
+
+
+
+ value: useByteOrderMark
+ value
+ useByteOrderMark
+ 2
+
+
+ 240
+
+
+
+ enabled: canUseByteOrderMark
+
+
+
+
+
+ enabled: canUseByteOrderMark
+ enabled
+ canUseByteOrderMark
+ 2
+
+
+ 242
+
+
+
+
+
+ 0
+
+
+
+
+
+ -2
+
+
+ File's Owner
+
+
+ -1
+
+
+ First Responder
+
+
+ -3
+
+
+ Application
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ 33
+
+
+
+
+
+
+
+ 34
+
+
+
+
+ 2
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+ 5
+
+
+
+
+ 11
+
+
+
+
+
+
+
+ 13
+
+
+
+
+
+
+
+ 14
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+
+ 16
+
+
+
+
+ 15
+
+
+
+
+ 25
+
+
+
+
+
+
+
+ 26
+
+
+
+
+ 29
+
+
+
+
+
+
+
+ 30
+
+
+
+
+ 243
+
+
+
+
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ Line Endings Pop Up Button
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ OakEncodingPopUpButton
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+
+
+
+ 247
+
+
+
+
+ OakEncodingPopUpButton
+ NSPopUpButton
+
+ IBProjectSource
+ ./Classes/OakEncodingPopUpButton.h
+
+
+
+ OakEncodingSaveOptionsViewController
+ NSViewController
+
+ encodingPopUpButton
+ OakEncodingPopUpButton
+
+
+ encodingPopUpButton
+
+ encodingPopUpButton
+ OakEncodingPopUpButton
+
+
+
+ IBProjectSource
+ ./Classes/OakEncodingSaveOptionsViewController.h
+
+
+
+
+ 0
+ IBCocoaFramework
+
+ com.apple.InterfaceBuilder.CocoaPlugin.macosx
+
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3
+
+
+ YES
+ 3
+
+ {11, 11}
+ {10, 3}
+ {15, 15}
+
+
+
diff --git a/Frameworks/OakAppKit/src/OakSavePanel.h b/Frameworks/OakAppKit/src/OakSavePanel.h
index f1c20c1e..02073d13 100644
--- a/Frameworks/OakAppKit/src/OakSavePanel.h
+++ b/Frameworks/OakAppKit/src/OakSavePanel.h
@@ -1,11 +1,12 @@
+@class OakEncodingSaveOptionsViewController;
+
@interface OakSavePanel : NSObject
{
- id delegate;
- void* contextInfo;
+ OakEncodingSaveOptionsViewController* optionsViewController;
}
-+ (void)showWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate contextInfo:(void*)info;
++ (void)showWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM;
@end
@interface NSObject (OakSavePanelDelegate)
-- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath contextInfo:(void*)info;
+- (void)savePanelDidEnd:(OakSavePanel*)sheet path:(NSString*)aPath encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM;
@end
diff --git a/Frameworks/OakAppKit/src/OakSavePanel.mm b/Frameworks/OakAppKit/src/OakSavePanel.mm
index 703797c8..84b8cc5d 100644
--- a/Frameworks/OakAppKit/src/OakSavePanel.mm
+++ b/Frameworks/OakAppKit/src/OakSavePanel.mm
@@ -1,13 +1,90 @@
-#import "NSSavePanel Additions.h"
#import "OakSavePanel.h"
+#import "OakEncodingPopUpButton.h"
+#import "NSSavePanel Additions.h"
+#import
+#import
+#import
+
+@interface OakEncodingSaveOptionsViewController : NSViewController
+{
+ IBOutlet OakEncodingPopUpButton* encodingPopUpButton;
+
+ NSString* encoding;
+ NSString* lineEndings;
+ BOOL useByteOrderMark;
+}
+@property (nonatomic, retain) NSString* lineEndings;
+@property (nonatomic, retain) NSString* encoding;
+@property (nonatomic, assign) BOOL useByteOrderMark;
+@property (nonatomic, readonly) BOOL canUseByteOrderMark;
+@end
+
+@implementation OakEncodingSaveOptionsViewController
+@synthesize encoding, lineEndings, useByteOrderMark;
+
++ (NSSet*)keyPathsForValuesAffectingCanUseByteOrderMark { return [NSSet setWithObject:@"encoding"]; }
+
++ (void)initialize
+{
+ [OakStringListTransformer createTransformerWithName:@"OakLineEndingsTransformer" andObjectsArray:@[ @"\n", @"\r", @"\r\n" ]];
+ [OakStringListTransformer createTransformerWithName:@"OakLineEndingsListTransformer" andObjectsArray:@[ @"\n", @"\r", @"\r\n" ]];
+}
+
+- (id)init
+{
+ if(self = [super initWithNibName:@"EncodingSaveOptions" bundle:[NSBundle bundleForClass:[self class]]])
+ {
+ self.encoding = @"UTF-8";
+ self.lineEndings = @"\n";
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [self unbind:@"encoding"];
+ [super dealloc];
+}
+
+- (void)loadView
+{
+ [super loadView];
+ encodingPopUpButton.encoding = encoding;
+ [self bind:@"encoding" toObject:encodingPopUpButton withKeyPath:@"encoding" options:nil];
+}
+
+- (BOOL)canUseByteOrderMark
+{
+ return [self.encoding hasPrefix:@"UTF-"];
+}
+
+- (void)setEncoding:(NSString*)newEncoding
+{
+ if(encoding != newEncoding && ![encoding isEqualToString:newEncoding])
+ {
+ [encoding autorelease];
+ encoding = [newEncoding retain];
+
+ self.useByteOrderMark = [self canUseByteOrderMark] && ![encoding isEqualToString:@"UTF-8"];
+ }
+}
+@end
@implementation OakSavePanel
-- (id)initWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate contextInfo:(void*)info
+- (id)initWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM
{
if((self = [super init]))
{
- delegate = aDelegate;
- contextInfo = info;
+ optionsViewController = [OakEncodingSaveOptionsViewController new];
+ if(!optionsViewController)
+ {
+ [self release];
+ return nil;
+ }
+
+ optionsViewController.encoding = [NSString stringWithCxxString:encoding] ?: @"UTF-8";
+ optionsViewController.lineEndings = [NSString stringWithCxxString:newlines] ?: @"\n";
+ optionsViewController.useByteOrderMark = useBOM;
[[aWindow attachedSheet] orderOut:self]; // incase there already is a sheet showing (like “Do you want to save?”)
@@ -16,9 +93,10 @@
if(aDirectorySuggestion)
[savePanel setDirectoryURL:[NSURL fileURLWithPath:aDirectorySuggestion]];
[savePanel setNameFieldStringValue:[aPathSuggestion lastPathComponent]];
+ [savePanel setAccessoryView:optionsViewController.view];
[savePanel beginSheetModalForWindow:aWindow completionHandler:^(NSInteger result) {
NSString* path = result == NSOKButton ? [[savePanel.URL filePathURL] path] : nil;
- [delegate savePanelDidEnd:self path:path contextInfo:contextInfo];
+ [aDelegate savePanelDidEnd:self path:path encoding:to_s(optionsViewController.encoding) newlines:to_s(optionsViewController.lineEndings) useBOM:optionsViewController.useByteOrderMark];
[self release];
}];
[savePanel deselectExtension];
@@ -26,9 +104,14 @@
return self;
}
-+ (void)showWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate contextInfo:(void*)info
+- (void)dealloc
{
- [[OakSavePanel alloc] initWithPath:aPathSuggestion directory:aDirectorySuggestion fowWindow:aWindow delegate:aDelegate contextInfo:info];
+ [optionsViewController release];
+ [super dealloc];
}
++ (void)showWithPath:(NSString*)aPathSuggestion directory:(NSString*)aDirectorySuggestion fowWindow:(NSWindow*)aWindow delegate:(id)aDelegate encoding:(std::string const&)encoding newlines:(std::string const&)newlines useBOM:(BOOL)useBOM
+{
+ [[OakSavePanel alloc] initWithPath:aPathSuggestion directory:aDirectorySuggestion fowWindow:aWindow delegate:aDelegate encoding:encoding newlines:newlines useBOM:useBOM];
+}
@end