diff --git a/arch/xcode/MegaZeux.xcodeproj/project.pbxproj b/arch/xcode/MegaZeux.xcodeproj/project.pbxproj index f66f40c43..cc5f9e18b 100644 --- a/arch/xcode/MegaZeux.xcodeproj/project.pbxproj +++ b/arch/xcode/MegaZeux.xcodeproj/project.pbxproj @@ -7,7 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - BF00DC0C2085644A00CD2DD2 /* clipboard_sdl2.c in Sources */ = {isa = PBXBuildFile; fileRef = BF00DC0B2085644A00CD2DD2 /* clipboard_sdl2.c */; }; + 482C0E8F2617D38E002D9030 /* vio.h in Headers */ = {isa = PBXBuildFile; fileRef = 482C0E8E2617D38E002D9030 /* vio.h */; }; + 482C0E912617D49D002D9030 /* clipboard_cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 482C0E902617D49C002D9030 /* clipboard_cocoa.m */; }; BF10127F1FCCA7C2008EEDB6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF10127E1FCCA7C2008EEDB6 /* Assets.xcassets */; }; BF1012A61FCCA993008EEDB6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF1012A51FCCA993008EEDB6 /* Assets.xcassets */; }; BF1012BA1FCCABB5008EEDB6 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1012B71FCCABB4008EEDB6 /* Vorbis.framework */; }; @@ -83,7 +84,7 @@ BFD5B0482465AFAE00BC91E9 /* zip_stream.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0332465AFAC00BC91E9 /* zip_stream.h */; }; BFD5B0492465AFAE00BC91E9 /* dir.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0342465AFAC00BC91E9 /* dir.h */; }; BFD5B04A2465AFAE00BC91E9 /* zip_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD5B0352465AFAC00BC91E9 /* zip_stream.c */; }; - BFD5B04B2465AFAE00BC91E9 /* vfile.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD5B0362465AFAC00BC91E9 /* vfile.c */; }; + BFD5B04B2465AFAE00BC91E9 /* vio.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD5B0362465AFAC00BC91E9 /* vio.c */; }; BFD5B04C2465AFAE00BC91E9 /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD5B0372465AFAC00BC91E9 /* path.c */; }; BFD5B04D2465AFAE00BC91E9 /* zip_deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0382465AFAC00BC91E9 /* zip_deflate.h */; }; BFD5B04E2465AFAE00BC91E9 /* fsafeopen.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0392465AFAC00BC91E9 /* fsafeopen.h */; }; @@ -92,7 +93,7 @@ BFD5B0512465AFAE00BC91E9 /* zip_implode.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B03C2465AFAD00BC91E9 /* zip_implode.h */; }; BFD5B0522465AFAE00BC91E9 /* memfile.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B03D2465AFAD00BC91E9 /* memfile.h */; }; BFD5B0532465AFAE00BC91E9 /* zip_shrink.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B03E2465AFAD00BC91E9 /* zip_shrink.h */; }; - BFD5B0542465AFAE00BC91E9 /* vfile_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B03F2465AFAD00BC91E9 /* vfile_posix.h */; }; + BFD5B0542465AFAE00BC91E9 /* vio_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B03F2465AFAD00BC91E9 /* vio_posix.h */; }; BFD5B0552465AFAE00BC91E9 /* zip_dict.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0402465AFAD00BC91E9 /* zip_dict.h */; }; BFD5B0562465AFAE00BC91E9 /* dir.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD5B0412465AFAD00BC91E9 /* dir.c */; }; BFD5B0582465AFEB00BC91E9 /* hashtable.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD5B0572465AFEB00BC91E9 /* hashtable.h */; }; @@ -370,7 +371,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - BF00DC0B2085644A00CD2DD2 /* clipboard_sdl2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = clipboard_sdl2.c; path = ../../src/editor/clipboard_sdl2.c; sourceTree = ""; }; + 482C0E8E2617D38E002D9030 /* vio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vio.h; path = ../../src/io/vio.h; sourceTree = ""; }; + 482C0E902617D49C002D9030 /* clipboard_cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = clipboard_cocoa.m; path = ../../src/editor/clipboard_cocoa.m; sourceTree = ""; }; BF1012781FCCA7C2008EEDB6 /* MegaZeux.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MegaZeux.app; sourceTree = BUILT_PRODUCTS_DIR; }; BF10127E1FCCA7C2008EEDB6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; BF1012831FCCA7C2008EEDB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -430,7 +432,7 @@ BF6058D9216B3725001B738C /* settings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = settings.c; path = ../../src/settings.c; sourceTree = ""; }; BFA1FB062536752500BB429F /* ice_load.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ice_load.c; path = ../../contrib/libxmp/src/loaders/ice_load.c; sourceTree = ""; }; BFA52FD0233AC48100A90CB4 /* audio_reality.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = audio_reality.h; path = ../../src/audio/audio_reality.h; sourceTree = ""; }; - BFA52FD1233AC48100A90CB4 /* audio_reality.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = audio_reality.cpp; path = ../../src/audio/audio_reality.cpp; sourceTree = ""; }; + BFA52FD1233AC48100A90CB4 /* audio_reality.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = audio_reality.cpp; path = ../../src/audio/audio_reality.cpp; sourceTree = ""; }; BFC0B26520681A9000D28296 /* hmn_load.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hmn_load.c; path = ../../contrib/libxmp/src/loaders/hmn_load.c; sourceTree = ""; }; BFC0B26620681A9000D28296 /* flt_load.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = flt_load.c; path = ../../contrib/libxmp/src/loaders/flt_load.c; sourceTree = ""; }; BFC0B26720681A9000D28296 /* st_load.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = st_load.c; path = ../../contrib/libxmp/src/loaders/st_load.c; sourceTree = ""; }; @@ -460,7 +462,7 @@ BFD5B0332465AFAC00BC91E9 /* zip_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zip_stream.h; path = ../../src/io/zip_stream.h; sourceTree = ""; }; BFD5B0342465AFAC00BC91E9 /* dir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dir.h; path = ../../src/io/dir.h; sourceTree = ""; }; BFD5B0352465AFAC00BC91E9 /* zip_stream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_stream.c; path = ../../src/io/zip_stream.c; sourceTree = ""; }; - BFD5B0362465AFAC00BC91E9 /* vfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vfile.c; path = ../../src/io/vfile.c; sourceTree = ""; }; + BFD5B0362465AFAC00BC91E9 /* vio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vio.c; path = ../../src/io/vio.c; sourceTree = ""; }; BFD5B0372465AFAC00BC91E9 /* path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = path.c; path = ../../src/io/path.c; sourceTree = ""; }; BFD5B0382465AFAC00BC91E9 /* zip_deflate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zip_deflate.h; path = ../../src/io/zip_deflate.h; sourceTree = ""; }; BFD5B0392465AFAC00BC91E9 /* fsafeopen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fsafeopen.h; path = ../../src/io/fsafeopen.h; sourceTree = ""; }; @@ -469,7 +471,7 @@ BFD5B03C2465AFAD00BC91E9 /* zip_implode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zip_implode.h; path = ../../src/io/zip_implode.h; sourceTree = ""; }; BFD5B03D2465AFAD00BC91E9 /* memfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memfile.h; path = ../../src/io/memfile.h; sourceTree = ""; }; BFD5B03E2465AFAD00BC91E9 /* zip_shrink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zip_shrink.h; path = ../../src/io/zip_shrink.h; sourceTree = ""; }; - BFD5B03F2465AFAD00BC91E9 /* vfile_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vfile_posix.h; path = ../../src/io/vfile_posix.h; sourceTree = ""; }; + BFD5B03F2465AFAD00BC91E9 /* vio_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vio_posix.h; path = ../../src/io/vio_posix.h; sourceTree = ""; }; BFD5B0402465AFAD00BC91E9 /* zip_dict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zip_dict.h; path = ../../src/io/zip_dict.h; sourceTree = ""; }; BFD5B0412465AFAD00BC91E9 /* dir.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dir.c; path = ../../src/io/dir.c; sourceTree = ""; }; BFD5B0572465AFEB00BC91E9 /* hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hashtable.h; path = ../../src/hashtable.h; sourceTree = ""; }; @@ -816,8 +818,9 @@ BFD5B03D2465AFAD00BC91E9 /* memfile.h */, BFD5B0372465AFAC00BC91E9 /* path.c */, BFD5B03A2465AFAD00BC91E9 /* path.h */, - BFD5B03F2465AFAD00BC91E9 /* vfile_posix.h */, - BFD5B0362465AFAC00BC91E9 /* vfile.c */, + BFD5B03F2465AFAD00BC91E9 /* vio_posix.h */, + BFD5B0362465AFAC00BC91E9 /* vio.c */, + 482C0E8E2617D38E002D9030 /* vio.h */, BFD5B0322465AFAC00BC91E9 /* vfile.h */, BFD5B0382465AFAC00BC91E9 /* zip_deflate.h */, BFD5B02D2465AFAB00BC91E9 /* zip_deflate64.h */, @@ -1054,7 +1057,7 @@ BFFF18401FCDCF6600BDEC58 /* char_ed.c */, BFFF18271FCDCF6300BDEC58 /* char_ed.h */, BFFF18211FCDCF6200BDEC58 /* clipboard.h */, - BF00DC0B2085644A00CD2DD2 /* clipboard_sdl2.c */, + 482C0E902617D49C002D9030 /* clipboard_cocoa.m */, BFFF18241FCDCF6300BDEC58 /* configure.c */, BFFF18351FCDCF6500BDEC58 /* configure.h */, BFFF183A1FCDCF6600BDEC58 /* debug.c */, @@ -1114,6 +1117,7 @@ BF6058F7216B3725001B738C /* game_player.h in Headers */, BFFF17CA1FCDCCF300BDEC58 /* hmn_extras.h in Headers */, BFFF17031FCDC76900BDEC58 /* str.h in Headers */, + 482C0E8F2617D38E002D9030 /* vio.h in Headers */, BFFF17011FCDC76900BDEC58 /* sprite.h in Headers */, BFD5B04D2465AFAE00BC91E9 /* zip_deflate.h in Headers */, BFFF16BE1FCDC76900BDEC58 /* block.h in Headers */, @@ -1186,7 +1190,7 @@ BFFF16C81FCDC76900BDEC58 /* error.h in Headers */, BFFF16D11FCDC76900BDEC58 /* game.h in Headers */, BFFF18111FCDCD1200BDEC58 /* xm.h in Headers */, - BFD5B0542465AFAE00BC91E9 /* vfile_posix.h in Headers */, + BFD5B0542465AFAE00BC91E9 /* vio_posix.h in Headers */, BFFF17CD1FCDCCF300BDEC58 /* md5.h in Headers */, BF6058EC216B3725001B738C /* core.h in Headers */, BFD5B0512465AFAE00BC91E9 /* zip_implode.h in Headers */, @@ -1503,7 +1507,7 @@ BFFF16D81FCDC76900BDEC58 /* idput.c in Sources */, BFFF17C21FCDCCF300BDEC58 /* smix.c in Sources */, BFA52FD3233AC48100A90CB4 /* audio_reality.cpp in Sources */, - BFD5B04B2465AFAE00BC91E9 /* vfile.c in Sources */, + BFD5B04B2465AFAE00BC91E9 /* vio.c in Sources */, BFFF18031FCDCD1200BDEC58 /* okt_load.c in Sources */, BFFF16ED1FCDC76900BDEC58 /* render_glsl.c in Sources */, BFFF17BF1FCDCCF300BDEC58 /* player.c in Sources */, @@ -1558,6 +1562,7 @@ BFFF18661FCDCF7C00BDEC58 /* debug.c in Sources */, BFFF18701FCDCF7C00BDEC58 /* macro.c in Sources */, BFFF18721FCDCF7C00BDEC58 /* pal_ed.c in Sources */, + 482C0E912617D49D002D9030 /* clipboard_cocoa.m in Sources */, BFFF18681FCDCF7C00BDEC58 /* edit_di.c in Sources */, BF6058B5216B3683001B738C /* buffer.c in Sources */, BFFF186A1FCDCF7C00BDEC58 /* edit.c in Sources */, @@ -1568,7 +1573,6 @@ BFFF18781FCDCF7C00BDEC58 /* robo_ed.c in Sources */, BF6058B2216B3683001B738C /* edit_menu.c in Sources */, BFFF187C1FCDCF7C00BDEC58 /* select.c in Sources */, - BF00DC0C2085644A00CD2DD2 /* clipboard_sdl2.c in Sources */, BFFF186C1FCDCF7C00BDEC58 /* fill.c in Sources */, BFFF187A1FCDCF7C00BDEC58 /* robot.c in Sources */, BFFF18841FCDCF7C00BDEC58 /* world.c in Sources */, @@ -1774,6 +1778,7 @@ NEED_PNG_WRITE_SCREEN, "DEBUG=1", LIBXMP_NO_DEPACKERS, + LIBXMP_NO_PROWIZARD, ); HEADER_SEARCH_PATHS = ( SDL2.framework/Headers, @@ -1804,6 +1809,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( NEED_PNG_WRITE_SCREEN, LIBXMP_NO_DEPACKERS, + LIBXMP_NO_PROWIZARD, ); HEADER_SEARCH_PATHS = ( SDL2.framework/Headers, diff --git a/src/editor/Makefile.in b/src/editor/Makefile.in index 18eb9b078..e566c0f0b 100644 --- a/src/editor/Makefile.in +++ b/src/editor/Makefile.in @@ -49,16 +49,21 @@ editor_objs := \ ifeq (${PLATFORM},mingw) editor_objs += ${editor_obj}/clipboard_win32.o +# Mac OS X clipboard handler via Cocoa +else ifeq (${PLATFORM},darwin) +editor_ldflags += -framework Cocoa +#editor_objs += ${editor_obj}/clipboard_carbon.o +editor_objs += ${editor_obj}/clipboard_cocoa.o + +${editor_obj}/%.o: ${editor_src}/%.m + $(if ${V},,@echo " OBJC " $<) + ${CC} -MD ${core_cflags} ${editor_flags} ${editor_spec} -c $< -o $@ + # Use the SDL2 clipboard handler else ifeq (${BUILD_LIBSDL2},1) editor_ldflags += ${SDL_LDFLAGS} editor_objs += ${editor_obj}/clipboard_sdl2.o -# Mac OS X clipboard handler via Carbon -else ifeq (${PLATFORM},darwin) -editor_ldflags += -framework Cocoa -editor_objs += ${editor_obj}/clipboard_carbon.o - # X11 clipboard handler (requires SDL 1.2) else ifneq (${X11DIR},) editor_flags += ${X11_CFLAGS} diff --git a/src/editor/clipboard_cocoa.m b/src/editor/clipboard_cocoa.m new file mode 100644 index 000000000..565f9367a --- /dev/null +++ b/src/editor/clipboard_cocoa.m @@ -0,0 +1,128 @@ +/* MegaZeux + * + * Copyright (C) 2021 Alice Rowan + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include +#include + +#include "clipboard.h" + +/** + * Native MacOS clipboard handler using AppKit. Unlike the SDL2 clipboard + * handler, this handler treats the input text as being encoded in Mac OS Roman + * (unlike ISO Latin-1, Windows 1292, etc, all 256 codepoints of Mac OS Roman + * will be encoded as valid UTF-8 symbols). + * + * Notes: + * - Literal arrays require LLVM 3.1, so explicitly allocate NSArrays. + * - @autoreleasepool requires LLVM 3.0, so use NSAutoreleasePool directly. + */ + +/** + * Send an array of extended ASCII lines to the system clipboard via Cocoa. + * These lines will be re-encoded to UTF-8 using Mac OS Roman codepoints. + */ +void copy_buffer_to_clipboard(char **buffer, int lines, int total_length) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + char *buf = cmalloc(total_length + 1); + char *pos = buf; + for(int i = 0; i < lines; i++) + { + size_t len = strlen(buffer[i]); + memcpy(pos, buffer[i], len); + pos += len; + *(pos++) = '\n'; + } + buf[total_length] = '\0'; + + /* Convert to NSString. NOTE: this function requires 10.3+, haven't + * looked for a compelling way to do this for 10.0. + */ + NSString *string = [[[NSString alloc] initWithBytes:buf length:total_length + encoding:NSMacOSRomanStringEncoding] autorelease]; + free(buf); + + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 + + [pasteboard clearContents]; + [pasteboard writeObjects:[NSArray arrayWithObject:string]]; + +#else /* VERSION_MIN < 1060 */ + + [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; + [pasteboard setString:string forType:NSStringPboardType]; + +#endif /* VERSION_MIN < 1060 */ + + [pool release]; +} + +/** + * Fetch an extended ASCII buffer from the system clipboard via Cocoa. + * These lines will be re-encoded from UTF-8 using Mac OS Roman codepoints. + */ +char *get_clipboard_buffer(void) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 + + NSArray *for_classes = [NSArray arrayWithObject:[NSString class]]; + NSArray *items = [pasteboard readObjectsForClasses:for_classes options:nil]; + + NSString *string = items && [items count] ? [items objectAtIndex:0] : nil; + if(!string) + goto err; + +#else /* VERSION_MIN < 1060 */ + + NSArray *types = [NSArray arrayWithObject:NSStringPboardType]; + if(![pasteboard availableTypeFromArray:types]) + goto err; + + NSString *string = [pasteboard stringForType:NSStringPboardType]; + if(!string) + goto err; + +#endif /* VERSION_MIN < 1060 */ + + NSData *chrdata = [string dataUsingEncoding:NSMacOSRomanStringEncoding + allowLossyConversion:true]; + if(!chrdata) + goto err; + + size_t buf_len = [chrdata length]; + char *buf = cmalloc(buf_len + 1); + + [chrdata getBytes:buf length:buf_len]; + buf[buf_len] = '\0'; + [pool release]; + return buf; + +err: + [pool release]; + return NULL; +}