diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..bd32b51 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,56 @@ +# ClipMenu — Agent Instructions + +## Migration Status Rule + +**Every agent that completes or advances a migration step MUST update `migration_status.md` before finishing.** + +This applies to any work that: +- Implements or stubs a file listed in `Sources/` +- Changes `project.yml` or regenerates `ClipMenu.xcodeproj` +- Adds, removes, or modifies a package dependency +- Makes a structural change to `Sources/` +- Completes or partially completes any task listed under "Not Started" or "In Progress" in `migration_status.md` + +**How to update:** +1. Move the completed task from "Not Started" → "Completed" (or update its checkbox). +2. If a task is partially done, move it to "In Progress" with a short note on what remains. +3. Update the "Overall progress" summary line at the top. +4. Do **not** remove the "Key Decisions" table entries without explicit user instruction. + +## Architecture + +- New Swift source lives in `Sources/` (see `doc/migration.md` for the full directory spec). +- Legacy Objective-C source was removed from this repository after migration completion. +- Build system: XcodeGen — edit `project.yml`, then run `xcodegen generate` to regenerate `ClipMenu.xcodeproj`. +- The `.xcodeproj` is generated output; never hand-edit `project.pbxproj`. + +## SwiftUI View Rule + +**Every SwiftUI `View` in `Sources/UI/` MUST have at least one `#Preview` block.** + +- The preview must compile and render without requiring a live app or device. +- Use in-memory `ModelContainer` when SwiftData models are needed: + ```swift + .modelContainer(for: [ClipEntry.self, ...], inMemory: true) + ``` +- Inject required environment values using test instances: + ```swift + .environment(ClipMenuSettings()) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + ``` +- A view file without a `#Preview` block must not be marked completed in `migration_status.md`. + +## Build & Verify + +```sh +xcodegen generate +xcodebuild -project ClipMenu.xcodeproj -scheme ClipMenu -configuration Debug build \ + CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO +``` + +Both commands must succeed with no errors before a task is marked completed. + +## Behavior Reference + +Legacy source references are historical only and are no longer available in this repository. +When implementing behavior changes, rely on the current Swift implementation and documented behavior in `doc/features.md`. diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9c621f0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "chat.tools.terminal.autoApprove": { + "xcodebuild": true, + "defaults": true, + "true": true + } +} \ No newline at end of file diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png new file mode 100644 index 0000000..3efeaf4 Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png new file mode 100644 index 0000000..6d8c5ef Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png new file mode 100644 index 0000000..5211ca4 Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png new file mode 100644 index 0000000..f7d8bbc Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png new file mode 100644 index 0000000..6d8c5ef Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png new file mode 100644 index 0000000..6494adf Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png new file mode 100644 index 0000000..f7d8bbc Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png new file mode 100644 index 0000000..1e07a1c Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png new file mode 100644 index 0000000..28f70ca Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 0000000..50bb9d1 Binary files /dev/null and b/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/Assets.xcassets/AppIcon.appiconset/Contents.json b/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2fef260 --- /dev/null +++ b/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "AppIcon-16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "AppIcon-16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "AppIcon-32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "AppIcon-32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "AppIcon-128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "AppIcon-128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "AppIcon-256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "AppIcon-256@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "AppIcon-512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "AppIcon-512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Assets.xcassets/Contents.json b/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 0000000..bd89d41 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,65 @@ +# Build And Release Guide + +This repository contains the active Swift/XcodeGen ClipMenu project. + +## Prerequisites + +```sh +xcode-select -p +brew install xcodegen +``` + +## Generate Project + +Run whenever `project.yml` changes: + +```sh +xcodegen generate +``` + +## Build (Debug) + +```sh +xcodebuild -project ClipMenu.xcodeproj -scheme ClipMenu -configuration Debug build \ + CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO +``` + +## Build (Release) + +```sh +xcodebuild -project ClipMenu.xcodeproj -scheme ClipMenu -configuration Release build \ + CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO +``` + +## Run From Xcode + +1. Open `ClipMenu.xcodeproj`. +2. Select scheme `ClipMenu`. +3. Run with `Debug` configuration. + +ClipMenu is a menu bar app (`LSUIElement = YES`), so it does not appear in the Dock while running. + +## Accessibility Note + +Paste simulation uses CGEvent and requires Accessibility permission: + +- System Settings -> Privacy & Security -> Accessibility + +## Release Direction + +- Legacy Sparkle/appcast release scripts were removed during repository cleanup. +- Packaging/notarization should be implemented through a modern, explicit archive/export pipeline when needed. + +## Troubleshooting + +`xcodegen: command not found` + +```sh +brew install xcodegen +``` + +Code signing errors in local/CI builds + +- Use `CODE_SIGN_IDENTITY=""` +- Use `CODE_SIGNING_REQUIRED=NO` +- Use `CODE_SIGNING_ALLOWED=NO` diff --git a/ClipMenu.entitlements b/ClipMenu.entitlements new file mode 100644 index 0000000..9028b45 --- /dev/null +++ b/ClipMenu.entitlements @@ -0,0 +1,16 @@ + + + + + + + + com.apple.security.automation.apple-events + + + diff --git a/ClipMenu.xcodeproj/project.pbxproj b/ClipMenu.xcodeproj/project.pbxproj index 86953bb..b55789f 100644 --- a/ClipMenu.xcodeproj/project.pbxproj +++ b/ClipMenu.xcodeproj/project.pbxproj @@ -3,1113 +3,801 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 77; objects = { /* Begin PBXBuildFile section */ - 3505FF1D0D7FAE8300B55D03 /* ActionFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */; }; - 3505FF200D7FAF1F00B55D03 /* ActionNodeFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */; }; - 3505FF730D7FB14A00B55D03 /* BuiltInActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */; }; - 3518CA990D07646C00158053 /* MenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3518CA980D07646C00158053 /* MenuController.m */; }; - 3518CE070D07966B00158053 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3518CE060D07966B00158053 /* Carbon.framework */; }; - 3542A8AF0D5EBF3800B3BBBD /* NSString+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */; }; - 3542A8CB0D5EC15000B3BBBD /* ActionNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */; }; - 3542A92B0D5EC6C300B3BBBD /* CMUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */; }; - 3542AD6F0D62828000B3BBBD /* ActionNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542AD6E0D62828000B3BBBD /* ActionNode.m */; }; - 3551F2BF0D75224900069069 /* ActionTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */; }; - 3551F3720D7658EF00069069 /* JavaScriptSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F3710D7658EF00069069 /* JavaScriptSupport.m */; }; - 356F060E0D012C68003689C0 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F060D0D012C68003689C0 /* AppController.m */; }; - 356F073F0D024327003689C0 /* ClipsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F073E0D024327003689C0 /* ClipsController.m */; }; - 3578F7700D7E3D5E00E804BF /* Menu.png in Resources */ = {isa = PBXBuildFile; fileRef = 3578F76F0D7E3D5E00E804BF /* Menu.png */; }; - 35939D670D42D38F006504B3 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35939D660D42D38F006504B3 /* WebKit.framework */; }; - 35939DAB0D42D4FE006504B3 /* ActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35939DAA0D42D4FE006504B3 /* ActionController.m */; }; - 3593F1850D025D5500B95536 /* Clip.m in Sources */ = {isa = PBXBuildFile; fileRef = 3593F1840D025D5500B95536 /* Clip.m */; }; - 35A42CC40D7D0ABA005FFB4C /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */; }; - 35A473490D20E8DE00E6B842 /* ClipMenu.icns in Resources */ = {isa = PBXBuildFile; fileRef = 35A473480D20E8DE00E6B842 /* ClipMenu.icns */; }; - 35C028950D6838D600B95FF5 /* ActionIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028940D6838D600B95FF5 /* ActionIcon.tiff */; }; - 35C028DC0D683C0200B95FF5 /* ActionIconLarge.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */; }; - 35C02FFE0D6BAB8300B95FF5 /* script in Resources */ = {isa = PBXBuildFile; fileRef = 35C02FFA0D6BAB8300B95FF5 /* script */; }; - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - A821F5411085696E00B25C8B /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = A821F5401085696E00B25C8B /* dsa_pub.pem */; }; - A821F5421085696E00B25C8B /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = A821F5401085696E00B25C8B /* dsa_pub.pem */; }; - A82348FD10BFDEB00045C1F4 /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A82348FC10BFDEB00045C1F4 /* ImageAndTextCell.m */; }; - A82348FE10BFDEB00045C1F4 /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A82348FC10BFDEB00045C1F4 /* ImageAndTextCell.m */; }; - A823495710BFE3880045C1F4 /* BaseNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A823495610BFE3880045C1F4 /* BaseNode.m */; }; - A823495810BFE3880045C1F4 /* BaseNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A823495610BFE3880045C1F4 /* BaseNode.m */; }; - A8234A5110AA9F8200EB250C /* SnippetEditor.strings in Resources */ = {isa = PBXBuildFile; fileRef = A8234A4F10AA9F8200EB250C /* SnippetEditor.strings */; }; - A8234A5210AA9F8200EB250C /* SnippetEditor.strings in Resources */ = {isa = PBXBuildFile; fileRef = A8234A4F10AA9F8200EB250C /* SnippetEditor.strings */; }; - A82B8AB50EC3F8D700096102 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - A82B8AB70EC3F8D700096102 /* ClipMenu.icns in Resources */ = {isa = PBXBuildFile; fileRef = 35A473480D20E8DE00E6B842 /* ClipMenu.icns */; }; - A82B8AB90EC3F8D700096102 /* ActionIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028940D6838D600B95FF5 /* ActionIcon.tiff */; }; - A82B8ABA0EC3F8D700096102 /* ActionIconLarge.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */; }; - A82B8ABB0EC3F8D700096102 /* script in Resources */ = {isa = PBXBuildFile; fileRef = 35C02FFA0D6BAB8300B95FF5 /* script */; }; - A82B8ABC0EC3F8D700096102 /* Menu.png in Resources */ = {isa = PBXBuildFile; fileRef = 3578F76F0D7E3D5E00E804BF /* Menu.png */; }; - A82B8ABD0EC3F8D700096102 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A89716F20EA877CD005EE8E8 /* MainMenu.xib */; }; - A82B8AC30EC3F8D700096102 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - A82B8AC40EC3F8D700096102 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F060D0D012C68003689C0 /* AppController.m */; }; - A82B8AC50EC3F8D700096102 /* ClipsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F073E0D024327003689C0 /* ClipsController.m */; }; - A82B8AC60EC3F8D700096102 /* Clip.m in Sources */ = {isa = PBXBuildFile; fileRef = 3593F1840D025D5500B95536 /* Clip.m */; }; - A82B8AC70EC3F8D700096102 /* MenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3518CA980D07646C00158053 /* MenuController.m */; }; - A82B8AC80EC3F8D700096102 /* ActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35939DAA0D42D4FE006504B3 /* ActionController.m */; }; - A82B8ACB0EC3F8D700096102 /* NSString+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */; }; - A82B8ACC0EC3F8D700096102 /* ActionNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */; }; - A82B8ACD0EC3F8D700096102 /* CMUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */; }; - A82B8ACE0EC3F8D700096102 /* ActionNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542AD6E0D62828000B3BBBD /* ActionNode.m */; }; - A82B8AD00EC3F8D700096102 /* ActionTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */; }; - A82B8AD10EC3F8D700096102 /* JavaScriptSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F3710D7658EF00069069 /* JavaScriptSupport.m */; }; - A82B8AD30EC3F8D700096102 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */; }; - A82B8AD40EC3F8D700096102 /* ActionFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */; }; - A82B8AD50EC3F8D700096102 /* ActionNodeFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */; }; - A82B8AD60EC3F8D700096102 /* BuiltInActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */; }; - A82B8AD90EC3F8D700096102 /* Snippets.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */; }; - A82B8ADA0EC3F8D700096102 /* SnippetsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89465EA0EB97B92004ACD23 /* SnippetsController.m */; }; - A82B8ADC0EC3F8D700096102 /* IndexedArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = A894673D0EB999B5004ACD23 /* IndexedArrayController.m */; }; - A82B8ADD0EC3F8D700096102 /* PTHotKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D26F0EC1735C007DE280 /* PTHotKey.m */; }; - A82B8ADE0EC3F8D700096102 /* PTHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */; }; - A82B8ADF0EC3F8D700096102 /* PTKeyCodeTranslator.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */; }; - A82B8AE00EC3F8D700096102 /* PTKeyCombo.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */; }; - A82B8AE20EC3F8D700096102 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - A82B8AE30EC3F8D700096102 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3518CE060D07966B00158053 /* Carbon.framework */; }; - A82B8AE40EC3F8D700096102 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35939D660D42D38F006504B3 /* WebKit.framework */; }; - A8328DCD108859AE00A54DF4 /* ShortcutRecorder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8328DCC108859AE00A54DF4 /* ShortcutRecorder.framework */; }; - A8328DCE108859AE00A54DF4 /* ShortcutRecorder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8328DCC108859AE00A54DF4 /* ShortcutRecorder.framework */; }; - A8328DD9108859B100A54DF4 /* ShortcutRecorder.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A8328DCC108859AE00A54DF4 /* ShortcutRecorder.framework */; }; - A8328E0C10885FAF00A54DF4 /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8328E0B10885FAF00A54DF4 /* DBPrefsWindowController.m */; }; - A8328E0D10885FAF00A54DF4 /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8328E0B10885FAF00A54DF4 /* DBPrefsWindowController.m */; }; - A8464D9D108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D95108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png */; }; - A8464D9E108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D96108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png */; }; - A8464D9F108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D97108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png */; }; - A8464DA0108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D98108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png */; }; - A8464DA1108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D99108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png */; }; - A8464DA2108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9A108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png */; }; - A8464DA3108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9B108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png */; }; - A8464DA4108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9C108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png */; }; - A8464DA5108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D95108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png */; }; - A8464DA6108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D96108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png */; }; - A8464DA7108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D97108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png */; }; - A8464DA8108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D98108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png */; }; - A8464DA9108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D99108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png */; }; - A8464DAA108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9A108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png */; }; - A8464DAB108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9B108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png */; }; - A8464DAC108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464D9C108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png */; }; - A8464DD6108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464DD4108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png */; }; - A8464DD7108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464DD5108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png */; }; - A8464DD8108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464DD4108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png */; }; - A8464DD9108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png in Resources */ = {isa = PBXBuildFile; fileRef = A8464DD5108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png */; }; - A849BC590EE267C0009DF9D1 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = A849BC580EE267C0009DF9D1 /* Preferences.xib */; }; - A849BC5A0EE267C0009DF9D1 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = A849BC580EE267C0009DF9D1 /* Preferences.xib */; }; - A86E0701119BF24200DF8A58 /* AddSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0700119BF24200DF8A58 /* AddSnippet.tiff */; }; - A86E0702119BF24200DF8A58 /* AddSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0700119BF24200DF8A58 /* AddSnippet.tiff */; }; - A86E0708119BF38100DF8A58 /* CheckSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0706119BF38100DF8A58 /* CheckSnippet.tiff */; }; - A86E0709119BF38100DF8A58 /* DeleteSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0707119BF38100DF8A58 /* DeleteSnippet.tiff */; }; - A86E070A119BF38100DF8A58 /* CheckSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0706119BF38100DF8A58 /* CheckSnippet.tiff */; }; - A86E070B119BF38100DF8A58 /* DeleteSnippet.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A86E0707119BF38100DF8A58 /* DeleteSnippet.tiff */; }; - A86E478810B2D5E0000FB773 /* NSColor+String.m in Sources */ = {isa = PBXBuildFile; fileRef = A86E478710B2D5E0000FB773 /* NSColor+String.m */; }; - A86E478910B2D5E0000FB773 /* NSColor+String.m in Sources */ = {isa = PBXBuildFile; fileRef = A86E478710B2D5E0000FB773 /* NSColor+String.m */; }; - A86F93910ED183C30058E899 /* Action.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8DF42840ED13BF000506877 /* Action.tiff */; }; - A86F939A0ED183FC0058E899 /* ActionPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */; }; - A8755B4B1164B0C500465B3B /* check.png in Resources */ = {isa = PBXBuildFile; fileRef = A8755B4A1164B0C500465B3B /* check.png */; }; - A8755B4C1164B0C500465B3B /* check.png in Resources */ = {isa = PBXBuildFile; fileRef = A8755B4A1164B0C500465B3B /* check.png */; }; - A878AA430EC411BE00112A8E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA420EC411BE00112A8E /* Localizable.strings */; }; - A878AA440EC411BE00112A8E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA420EC411BE00112A8E /* Localizable.strings */; }; - A878AA8A0EC413B000112A8E /* Preferences.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA890EC413B000112A8E /* Preferences.strings */; }; - A878AA8B0EC413B000112A8E /* Preferences.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA890EC413B000112A8E /* Preferences.strings */; }; - A87F7D05119FC41500420FF1 /* ClipMenu3.icns in Resources */ = {isa = PBXBuildFile; fileRef = A87F7D04119FC41500420FF1 /* ClipMenu3.icns */; }; - A87F7D06119FC41500420FF1 /* ClipMenu3.icns in Resources */ = {isa = PBXBuildFile; fileRef = A87F7D04119FC41500420FF1 /* ClipMenu3.icns */; }; - A89465E60EB97A62004ACD23 /* Snippets.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */; }; - A89465EB0EB97B92004ACD23 /* SnippetsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89465EA0EB97B92004ACD23 /* SnippetsController.m */; }; - A894673E0EB999B5004ACD23 /* IndexedArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = A894673D0EB999B5004ACD23 /* IndexedArrayController.m */; }; - A89716F40EA877CD005EE8E8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A89716F20EA877CD005EE8E8 /* MainMenu.xib */; }; - A897231B1095C6F500676306 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A897231A1095C6F500676306 /* Sparkle.framework */; }; - A897231C1095C6F500676306 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A897231A1095C6F500676306 /* Sparkle.framework */; }; - A89723271095C70900676306 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A897231A1095C6F500676306 /* Sparkle.framework */; }; - A8975E9C1087042E00973851 /* SparkleIcon.tif in Resources */ = {isa = PBXBuildFile; fileRef = A8975E9B1087042E00973851 /* SparkleIcon.tif */; }; - A8975E9D1087042E00973851 /* SparkleIcon.tif in Resources */ = {isa = PBXBuildFile; fileRef = A8975E9B1087042E00973851 /* SparkleIcon.tif */; }; - A8A2D2760EC1735C007DE280 /* PTHotKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D26F0EC1735C007DE280 /* PTHotKey.m */; }; - A8A2D2770EC1735C007DE280 /* PTHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */; }; - A8A2D2780EC1735C007DE280 /* PTKeyCodeTranslator.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */; }; - A8A2D2790EC1735C007DE280 /* PTKeyCombo.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */; }; - A8A6350D116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8A6350B116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png */; }; - A8A6350E116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png in Resources */ = {isa = PBXBuildFile; fileRef = A8A6350C116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png */; }; - A8A6350F116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8A6350B116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png */; }; - A8A63510116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png in Resources */ = {isa = PBXBuildFile; fileRef = A8A6350C116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png */; }; - A8C53AB610AA6585001930BE /* SnippetEditor.xib in Resources */ = {isa = PBXBuildFile; fileRef = A8C53AB510AA6585001930BE /* SnippetEditor.xib */; }; - A8C53AB710AA6585001930BE /* SnippetEditor.xib in Resources */ = {isa = PBXBuildFile; fileRef = A8C53AB510AA6585001930BE /* SnippetEditor.xib */; }; - A8CEEA0610AA42B500C3823F /* SnippetEditorController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8CEEA0510AA42B500C3823F /* SnippetEditorController.m */; }; - A8CEEA0710AA42B500C3823F /* SnippetEditorController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8CEEA0510AA42B500C3823F /* SnippetEditorController.m */; }; - A8CEEA4C10AA465800C3823F /* BWToolkitFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8CEEA4B10AA465800C3823F /* BWToolkitFramework.framework */; }; - A8CEEA4D10AA465800C3823F /* BWToolkitFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8CEEA4B10AA465800C3823F /* BWToolkitFramework.framework */; }; - A8CEEA8010AA466800C3823F /* BWToolkitFramework.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A8CEEA4B10AA465800C3823F /* BWToolkitFramework.framework */; }; - A8DCABDE10819C81006E02C8 /* StatusMenuIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABD810819C81006E02C8 /* StatusMenuIcon.png */; }; - A8DCABDF10819C81006E02C8 /* StatusMenuIcon_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABD910819C81006E02C8 /* StatusMenuIcon_pressed.png */; }; - A8DCABE010819C81006E02C8 /* StatusMenuIconFirst.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABDA10819C81006E02C8 /* StatusMenuIconFirst.png */; }; - A8DCABE110819C81006E02C8 /* StatusMenuIconFirst_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABDB10819C81006E02C8 /* StatusMenuIconFirst_pressed.png */; }; - A8DCABE410819C81006E02C8 /* StatusMenuIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABD810819C81006E02C8 /* StatusMenuIcon.png */; }; - A8DCABE510819C81006E02C8 /* StatusMenuIcon_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABD910819C81006E02C8 /* StatusMenuIcon_pressed.png */; }; - A8DCABE610819C81006E02C8 /* StatusMenuIconFirst.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABDA10819C81006E02C8 /* StatusMenuIconFirst.png */; }; - A8DCABE710819C81006E02C8 /* StatusMenuIconFirst_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A8DCABDB10819C81006E02C8 /* StatusMenuIconFirst_pressed.png */; }; - A8DF42850ED13BF000506877 /* Action.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8DF42840ED13BF000506877 /* Action.tiff */; }; - A8DF42B20ED13E9100506877 /* ActionPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */; }; - A8EBB688109190F900208A86 /* PTKeyboardIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8EBB687109190F900208A86 /* PTKeyboardIcon.tiff */; }; - A8EBB689109190F900208A86 /* PTKeyboardIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8EBB687109190F900208A86 /* PTKeyboardIcon.tiff */; }; - A8F30E811000429E006F3F9A /* NSArray_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */; }; - A8F30E831000429E006F3F9A /* NSArray_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */; }; - A8F568DF10C2239D00646BDB /* SeparatorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F568DE10C2239D00646BDB /* SeparatorCell.m */; }; - A8F568E010C2239D00646BDB /* SeparatorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F568DE10C2239D00646BDB /* SeparatorCell.m */; }; - A8F56B1610C272AF00646BDB /* FolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56B1510C272AF00646BDB /* FolderNode.m */; }; - A8F56B1710C272AF00646BDB /* FolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56B1510C272AF00646BDB /* FolderNode.m */; }; - A8F56BBB10C292D400646BDB /* NSIndexPath_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56BBA10C292D400646BDB /* NSIndexPath_Extensions.m */; }; - A8F56BBC10C292D400646BDB /* NSIndexPath_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56BBA10C292D400646BDB /* NSIndexPath_Extensions.m */; }; - A8F56BD010C2942D00646BDB /* NMLoginItems.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56BCF10C2942D00646BDB /* NMLoginItems.m */; }; - A8F56BD110C2942D00646BDB /* NMLoginItems.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F56BCF10C2942D00646BDB /* NMLoginItems.m */; }; - A8FA6E5A10AD66E200AFAB75 /* ScriptableClip.m in Sources */ = {isa = PBXBuildFile; fileRef = A8FA6E5910AD66E200AFAB75 /* ScriptableClip.m */; }; - A8FA6E5B10AD66E200AFAB75 /* ScriptableClip.m in Sources */ = {isa = PBXBuildFile; fileRef = A8FA6E5910AD66E200AFAB75 /* ScriptableClip.m */; }; + 00CE4E605010BDF7D2B57FCB /* ActionNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A663BD7362E0C5445528C4F1 /* ActionNode.swift */; }; + 03BE0E0A2BE4CD13C915121A /* ScriptableClip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620B8F52759F74FEBF46E0F1 /* ScriptableClip.swift */; }; + 21AD2E3FCA0D9D76AC02FA23 /* LegacyMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42B59EEB0DCCE6D695636F67 /* LegacyMigration.swift */; }; + 2F8F707D3AF29A98FCBA6CAF /* ClipsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83BE5811A4FB6A1DB019AC2 /* ClipsService.swift */; }; + 34EB7B9526F4C2AAF8291A23 /* ClipboardMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9075790B975D02A5039621CB /* ClipboardMonitor.swift */; }; + 40A1F4EED97AF8553F7672B0 /* EnvironmentKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC267D67332120F313F7EA31 /* EnvironmentKeys.swift */; }; + 4611B4DE54886E009EE9970F /* SnippetsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19473B9E42EE0B4041018F4D /* SnippetsPrefsView.swift */; }; + 49010720EA3588BD56645417 /* Snippet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B60996BF476330FFB6501381 /* Snippet.swift */; }; + 529A9D03AD998DAE8ADB2A00 /* MenuPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C53F23FA57EE7251E7DC8C6E /* MenuPrefsView.swift */; }; + 5F656B886B8F29CC5617F8BB /* ClipMenuApp+Scenes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED996E53C34CFD8C7D0310C /* ClipMenuApp+Scenes.swift */; }; + 609E344BBBB03FD8514E6C91 /* ClipMenuSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29576F23AAFF791919F37AA2 /* ClipMenuSettings.swift */; }; + 6A9FBD0E7674740848F7DA2A /* scripts in Resources */ = {isa = PBXBuildFile; fileRef = A665B545F09CB77A65913253 /* scripts */; }; + 6F1C323AB9B0297F0E353CCF /* ClipMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0016B43E0CACE631C4CC81B1 /* ClipMenuItem.swift */; }; + 76969A92D3459A30D0C7A6E2 /* AppRuntime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E215E86DBA662D409E0C3E8 /* AppRuntime.swift */; }; + 80C5101B8CC05DF5E188A131 /* ClipMenuApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CDD26CD466BFA583E75E608 /* ClipMenuApp.swift */; }; + 85CEF62003CEC8629A60FEA4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B9F2FC9E1D536A30571DAAAB /* Assets.xcassets */; }; + 87A7B382426FBCFEB7553409 /* SnippetFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD0F7706C0E03012259C58E /* SnippetFolder.swift */; }; + 936E1E26F533AC6B39414F5D /* GeneralPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2761ACB3529E51DE835B8478 /* GeneralPrefsView.swift */; }; + 951A172FEC26A436F6BC3232 /* ClipEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA18E6BAC3B61463FBA61589 /* ClipEntry.swift */; }; + 9A4C53BF9C1CD72C0D832BAF /* ActionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD6C21C72EE5244BB1D7613 /* ActionService.swift */; }; + 9BB7C546A30CC1666078A52B /* ShortcutsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 137B169B289424AA2C053F6E /* ShortcutsPrefsView.swift */; }; + A4C24CFC70012228839FBA18 /* ScriptEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E03F362BFE6F8406DB1DEB /* ScriptEngine.swift */; }; + A50FD9C591A6F8E6E86F6075 /* SnippetSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83A17B48EFB6F8C9C5953E6C /* SnippetSection.swift */; }; + A976327DD179929219A27364 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 630C393A150A0A2DD37B2D11 /* AppDelegate.swift */; }; + B7B65D3023B9F10BA44E782E /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F425B2066AB9B7524D4770CD /* PreferencesView.swift */; }; + BA02CE3D4BA737DCD6AC686A /* ClipMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC2785BEDC95DB32BD21552 /* ClipMenuView.swift */; }; + BDE2E92131BD9586D21FB6FD /* SnippetService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4616EE385FA381E5A043060 /* SnippetService.swift */; }; + CBE9A7D84EC7FB0CD880BA51 /* PasteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D443B0D12EBBA794375C2643 /* PasteService.swift */; }; + D54B008B6D9741A0002054BB /* LoginItemService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B48E46B042ACC84B0F6F1766 /* LoginItemService.swift */; }; + E1DFEA8B6C7669DFC34FBC0C /* HotkeyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD749FF754FE72E7DB47E6 /* HotkeyService.swift */; }; + E3A5BEAC6D55B0DBE1B56388 /* ActionSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6321E93388B5BFB5F35292 /* ActionSection.swift */; }; + EAA8E570AEAA9695CC422081 /* ActionMenuBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2071986765235444ED5C4B6 /* ActionMenuBuilder.swift */; }; + F89987AC92544F66743A4CC7 /* ActionsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F33CC09804F1E54781E0EBD /* ActionsPrefsView.swift */; }; + F9343715F430A05D2DD97E34 /* AppExclusionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CA10EBC72D8E5AE80FF0F4E /* AppExclusionService.swift */; }; + FD1AC14BA0BC211BB0749243 /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = D3A2344418DAEC005417850D /* KeyboardShortcuts */; }; /* End PBXBuildFile section */ -/* Begin PBXCopyFilesBuildPhase section */ - A82B8AE60EC3F8D700096102 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - A8CEEA8010AA466800C3823F /* BWToolkitFramework.framework in CopyFiles */, - A89723271095C70900676306 /* Sparkle.framework in CopyFiles */, - A8328DD9108859B100A54DF4 /* ShortcutRecorder.framework in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ - 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* ClipMenu_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClipMenu_Prefix.pch; path = ../ClipMenu_Prefix.pch; sourceTree = ""; }; - 3505FF1B0D7FAE8300B55D03 /* ActionFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionFactory.h; sourceTree = ""; }; - 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionFactory.m; sourceTree = ""; }; - 3505FF1E0D7FAF1F00B55D03 /* ActionNodeFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionNodeFactory.h; sourceTree = ""; }; - 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionNodeFactory.m; sourceTree = ""; }; - 3505FF710D7FB14A00B55D03 /* BuiltInActionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltInActionController.h; sourceTree = ""; }; - 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuiltInActionController.m; sourceTree = ""; }; - 3518CA970D07646B00158053 /* MenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuController.h; path = Source/MenuController.h; sourceTree = ""; }; - 3518CA980D07646C00158053 /* MenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuController.m; path = Source/MenuController.m; sourceTree = ""; }; - 3518CE060D07966B00158053 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; - 3542A8AD0D5EBF3800B3BBBD /* NSString+NaoAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+NaoAdditions.h"; sourceTree = ""; }; - 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+NaoAdditions.m"; sourceTree = ""; }; - 3542A8C90D5EC15000B3BBBD /* ActionNodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ActionNodeController.h; path = Source/ActionNodeController.h; sourceTree = ""; }; - 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ActionNodeController.m; path = Source/ActionNodeController.m; sourceTree = ""; }; - 3542A9290D5EC6C300B3BBBD /* CMUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMUtilities.h; path = Source/CMUtilities.h; sourceTree = ""; }; - 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CMUtilities.m; path = Source/CMUtilities.m; sourceTree = ""; }; - 3542AD6D0D62828000B3BBBD /* ActionNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionNode.h; sourceTree = ""; }; - 3542AD6E0D62828000B3BBBD /* ActionNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionNode.m; sourceTree = ""; }; - 3551F2BD0D75224900069069 /* ActionTypeTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ActionTypeTransformer.h; path = Source/ActionTypeTransformer.h; sourceTree = ""; }; - 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ActionTypeTransformer.m; path = Source/ActionTypeTransformer.m; sourceTree = ""; }; - 3551F3700D7658EF00069069 /* JavaScriptSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptSupport.h; sourceTree = ""; }; - 3551F3710D7658EF00069069 /* JavaScriptSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSupport.m; sourceTree = ""; }; - 356F060C0D012C68003689C0 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppController.h; path = Source/AppController.h; sourceTree = ""; }; - 356F060D0D012C68003689C0 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppController.m; path = Source/AppController.m; sourceTree = ""; }; - 356F073D0D024327003689C0 /* ClipsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClipsController.h; sourceTree = ""; }; - 356F073E0D024327003689C0 /* ClipsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClipsController.m; sourceTree = ""; }; - 3578645D0D23A82400FAFFC5 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; - 3578F76F0D7E3D5E00E804BF /* Menu.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Menu.png; path = resource/Menu.png; sourceTree = ""; }; - 35939D660D42D38F006504B3 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = ""; }; - 35939DA90D42D4FE006504B3 /* ActionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionController.h; sourceTree = ""; }; - 35939DAA0D42D4FE006504B3 /* ActionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionController.m; sourceTree = ""; }; - 3593F1830D025D5500B95536 /* Clip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clip.h; sourceTree = ""; }; - 3593F1840D025D5500B95536 /* Clip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clip.m; sourceTree = ""; }; - 35A42CC20D7D0ABA005FFB4C /* PrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrefsWindowController.h; path = Source/PrefsWindowController.h; sourceTree = ""; }; - 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PrefsWindowController.m; path = Source/PrefsWindowController.m; sourceTree = ""; }; - 35A473480D20E8DE00E6B842 /* ClipMenu.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ClipMenu.icns; path = resource/ClipMenu.icns; sourceTree = ""; }; - 35C028940D6838D600B95FF5 /* ActionIcon.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ActionIcon.tiff; path = resource/ActionIcon.tiff; sourceTree = ""; }; - 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ActionIconLarge.tiff; path = resource/ActionIconLarge.tiff; sourceTree = ""; }; - 35C02FFA0D6BAB8300B95FF5 /* script */ = {isa = PBXFileReference; lastKnownFileType = folder; name = script; path = resource/script; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 8D1107320486CEB800E47090 /* ClipMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClipMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A821F5401085696E00B25C8B /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = resource/dsa_pub.pem; sourceTree = ""; }; - A821F5861085DA8A00B25C8B /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/InfoPlist.strings; sourceTree = ""; }; - A82348FB10BFDEB00045C1F4 /* ImageAndTextCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ImageAndTextCell.h; path = Source/CocoaExtensions/ImageAndTextCell.h; sourceTree = ""; }; - A82348FC10BFDEB00045C1F4 /* ImageAndTextCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ImageAndTextCell.m; path = Source/CocoaExtensions/ImageAndTextCell.m; sourceTree = ""; }; - A823495510BFE3880045C1F4 /* BaseNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BaseNode.h; path = Source/CocoaExtensions/BaseNode.h; sourceTree = ""; }; - A823495610BFE3880045C1F4 /* BaseNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BaseNode.m; path = Source/CocoaExtensions/BaseNode.m; sourceTree = ""; }; - A8234A5010AA9F8200EB250C /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/SnippetEditor.strings; sourceTree = ""; }; - A8234A6910AAA05E00EB250C /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/SnippetEditor.strings; sourceTree = ""; }; - A82B8A460EC3DD0A00096102 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Preferences.strings; sourceTree = ""; }; - A82B8AEB0EC3F8D700096102 /* ClipMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClipMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A8328DCC108859AE00A54DF4 /* ShortcutRecorder.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ShortcutRecorder.framework; path = /Library/Frameworks/ShortcutRecorder.framework; sourceTree = ""; }; - A8328E0A10885FAF00A54DF4 /* DBPrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBPrefsWindowController.h; sourceTree = ""; }; - A8328E0B10885FAF00A54DF4 /* DBPrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DBPrefsWindowController.m; sourceTree = ""; }; - A842D3230EA97DA200DCB303 /* constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constants.h; path = Source/constants.h; sourceTree = ""; }; - A8464D95108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors1-bw-left.png"; sourceTree = ""; }; - A8464D96108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors1-bw-right.png"; sourceTree = ""; }; - A8464D97108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors1-color-left.png"; sourceTree = ""; }; - A8464D98108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors1-color-right.png"; sourceTree = ""; }; - A8464D99108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors2-bw-left.png"; sourceTree = ""; }; - A8464D9A108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors2-bw-right.png"; sourceTree = ""; }; - A8464D9B108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors2-color-left.png"; sourceTree = ""; }; - A8464D9C108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-scissors2-color-right.png"; sourceTree = ""; }; - A8464DD4108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-diagonal-bw.png"; sourceTree = ""; }; - A8464DD5108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusMenuIconByDaveUlrich-diagonal-color.png"; sourceTree = ""; }; - A849BC5B0EE267C8009DF9D1 /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Japanese; path = Japanese.lproj/Preferences.xib; sourceTree = ""; }; - A86E0700119BF24200DF8A58 /* AddSnippet.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = AddSnippet.tiff; sourceTree = ""; }; - A86E0706119BF38100DF8A58 /* CheckSnippet.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = CheckSnippet.tiff; sourceTree = ""; }; - A86E0707119BF38100DF8A58 /* DeleteSnippet.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = DeleteSnippet.tiff; sourceTree = ""; }; - A86E478610B2D5E0000FB773 /* NSColor+String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSColor+String.h"; path = "Source/CocoaExtensions/NSColor+String.h"; sourceTree = ""; }; - A86E478710B2D5E0000FB773 /* NSColor+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSColor+String.m"; path = "Source/CocoaExtensions/NSColor+String.m"; sourceTree = ""; }; - A8755B4A1164B0C500465B3B /* check.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = check.png; path = resource/check.png; sourceTree = ""; }; - A878AA450EC411C400112A8E /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/Localizable.strings; sourceTree = ""; }; - A878AA8C0EC413B700112A8E /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/Preferences.strings; sourceTree = ""; }; - A87F7D04119FC41500420FF1 /* ClipMenu3.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ClipMenu3.icns; path = resource/ClipMenu3.icns; sourceTree = ""; }; - A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = Snippets.xcdatamodel; sourceTree = ""; }; - A89465E90EB97B92004ACD23 /* SnippetsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SnippetsController.h; path = Source/SnippetsController.h; sourceTree = ""; }; - A89465EA0EB97B92004ACD23 /* SnippetsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SnippetsController.m; path = Source/SnippetsController.m; sourceTree = ""; }; - A894673C0EB999B5004ACD23 /* IndexedArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IndexedArrayController.h; path = Source/IndexedArrayController.h; sourceTree = ""; }; - A894673D0EB999B5004ACD23 /* IndexedArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IndexedArrayController.m; path = Source/IndexedArrayController.m; sourceTree = ""; }; - A89716F30EA877CD005EE8E8 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = ""; }; - A89716F70EA8780B005EE8E8 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/Preferences.xib; sourceTree = ""; }; - A897231A1095C6F500676306 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Sparkle.framework; sourceTree = ""; }; - A8975E9B1087042E00973851 /* SparkleIcon.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = SparkleIcon.tif; path = resource/SparkleIcon.tif; sourceTree = ""; }; - A8A2D26E0EC1735C007DE280 /* PTHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTHotKey.h; sourceTree = ""; }; - A8A2D26F0EC1735C007DE280 /* PTHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTHotKey.m; sourceTree = ""; }; - A8A2D2700EC1735C007DE280 /* PTHotKeyCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTHotKeyCenter.h; sourceTree = ""; }; - A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTHotKeyCenter.m; sourceTree = ""; }; - A8A2D2720EC1735C007DE280 /* PTKeyCodeTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTKeyCodeTranslator.h; sourceTree = ""; }; - A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTKeyCodeTranslator.m; sourceTree = ""; }; - A8A2D2740EC1735C007DE280 /* PTKeyCombo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTKeyCombo.h; sourceTree = ""; }; - A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTKeyCombo.m; sourceTree = ""; }; - A8A6350B116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIconBySuphiAksoy_pressed.png; sourceTree = ""; }; - A8A6350C116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIconBySuphiAksoy.png; sourceTree = ""; }; - A8C53AB810AA658D001930BE /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Japanese; path = Japanese.lproj/SnippetEditor.xib; sourceTree = ""; }; - A8CEEA0410AA42B500C3823F /* SnippetEditorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SnippetEditorController.h; path = Source/SnippetEditorController.h; sourceTree = ""; }; - A8CEEA0510AA42B500C3823F /* SnippetEditorController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SnippetEditorController.m; path = Source/SnippetEditorController.m; sourceTree = ""; }; - A8CEEA4B10AA465800C3823F /* BWToolkitFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BWToolkitFramework.framework; path = Frameworks/BWToolkitFramework.framework; sourceTree = ""; }; - A8DC723210A91D61001D3E99 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/SnippetEditor.xib; sourceTree = ""; }; - A8DCABD810819C81006E02C8 /* StatusMenuIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIcon.png; sourceTree = ""; }; - A8DCABD910819C81006E02C8 /* StatusMenuIcon_pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIcon_pressed.png; sourceTree = ""; }; - A8DCABDA10819C81006E02C8 /* StatusMenuIconFirst.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIconFirst.png; sourceTree = ""; }; - A8DCABDB10819C81006E02C8 /* StatusMenuIconFirst_pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusMenuIconFirst_pressed.png; sourceTree = ""; }; - A8DF42840ED13BF000506877 /* Action.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = Action.tiff; path = resource/Action.tiff; sourceTree = ""; }; - A8DF42B00ED13E9100506877 /* ActionPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ActionPopUpButton.h; path = Source/ActionPopUpButton.h; sourceTree = ""; }; - A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ActionPopUpButton.m; path = Source/ActionPopUpButton.m; sourceTree = ""; }; - A8EBB687109190F900208A86 /* PTKeyboardIcon.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = PTKeyboardIcon.tiff; path = resource/PTKeyboardIcon.tiff; sourceTree = ""; }; - A8F30E7D1000429E006F3F9A /* NSArray_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSArray_Extensions.h; path = Source/CocoaExtensions/NSArray_Extensions.h; sourceTree = ""; }; - A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSArray_Extensions.m; path = Source/CocoaExtensions/NSArray_Extensions.m; sourceTree = ""; }; - A8F568DD10C2239D00646BDB /* SeparatorCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SeparatorCell.h; path = Source/CocoaExtensions/SeparatorCell.h; sourceTree = ""; }; - A8F568DE10C2239D00646BDB /* SeparatorCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SeparatorCell.m; path = Source/CocoaExtensions/SeparatorCell.m; sourceTree = ""; }; - A8F56B1410C272AF00646BDB /* FolderNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FolderNode.h; path = Source/FolderNode.h; sourceTree = ""; }; - A8F56B1510C272AF00646BDB /* FolderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FolderNode.m; path = Source/FolderNode.m; sourceTree = ""; }; - A8F56BB910C292D400646BDB /* NSIndexPath_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSIndexPath_Extensions.h; path = Source/CocoaExtensions/NSIndexPath_Extensions.h; sourceTree = ""; }; - A8F56BBA10C292D400646BDB /* NSIndexPath_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSIndexPath_Extensions.m; path = Source/CocoaExtensions/NSIndexPath_Extensions.m; sourceTree = ""; }; - A8F56BCE10C2942D00646BDB /* NMLoginItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NMLoginItems.h; path = ../../Library/NM/NMLoginItems.h; sourceTree = SOURCE_ROOT; }; - A8F56BCF10C2942D00646BDB /* NMLoginItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NMLoginItems.m; path = ../../Library/NM/NMLoginItems.m; sourceTree = SOURCE_ROOT; }; - A8FA6E5810AD66E200AFAB75 /* ScriptableClip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptableClip.h; sourceTree = ""; }; - A8FA6E5910AD66E200AFAB75 /* ScriptableClip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScriptableClip.m; sourceTree = ""; }; + 0016B43E0CACE631C4CC81B1 /* ClipMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipMenuItem.swift; sourceTree = ""; }; + 05040ED7DB4E9E6B59B441AB /* ` `.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "` `.js"; sourceTree = ""; }; + 091565A092F406927E15ED61 /* Convert Markdown to HTML.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Markdown to HTML.js"; sourceTree = ""; }; + 0CD6C21C72EE5244BB1D7613 /* ActionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionService.swift; sourceTree = ""; }; + 0CDD26CD466BFA583E75E608 /* ClipMenuApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipMenuApp.swift; sourceTree = ""; }; + 0E215E86DBA662D409E0C3E8 /* AppRuntime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRuntime.swift; sourceTree = ""; }; + 0F33CC09804F1E54781E0EBD /* ActionsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionsPrefsView.swift; sourceTree = ""; }; + 0FD091B978990ECF3F3D7E4E /* Encode URI component.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Encode URI component.js"; sourceTree = ""; }; + 137B169B289424AA2C053F6E /* ShortcutsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsPrefsView.swift; sourceTree = ""; }; + 175D9BC47EBD304CA4230174 /* Surround with Tags....js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Surround with Tags....js"; sourceTree = ""; }; + 179AF605EB49F693BF4AD85E /* migration.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = migration.md; sourceTree = ""; }; + 19473B9E42EE0B4041018F4D /* SnippetsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetsPrefsView.swift; sourceTree = ""; }; + 19B808EFAA8952BC9BA1CA8D /* string.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = string.js; sourceTree = ""; }; + 1AAA8A2C77102B5966216536 /* LICENSE */ = {isa = PBXFileReference; path = LICENSE; sourceTree = ""; }; + 1C7B6FEA8365FA24B2DBB906 /* Convert Character to Decimal.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Character to Decimal.js"; sourceTree = ""; }; + 1E56AEC45D95D95509478467 /* util.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = util.js; sourceTree = ""; }; + 1FD73C6C287485CB59A08FEE /* Calculate MD5 hash.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Calculate MD5 hash.js"; sourceTree = ""; }; + 268B85C5E498C2D963151455 /* Reverse.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Reverse.js; sourceTree = ""; }; + 2761ACB3529E51DE835B8478 /* GeneralPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPrefsView.swift; sourceTree = ""; }; + 29576F23AAFF791919F37AA2 /* ClipMenuSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipMenuSettings.swift; sourceTree = ""; }; + 2F809C93EED8F3156F24FC72 /* Capitalize.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Capitalize.js; sourceTree = ""; }; + 2FC43A69E4D022001DD1564A /* 『 』.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "『 』.js"; sourceTree = ""; }; + 30E03F362BFE6F8406DB1DEB /* ScriptEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptEngine.swift; sourceTree = ""; }; + 30F9D13D4936E1E652C416E4 /* enhancements.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = enhancements.md; sourceTree = ""; }; + 3E9CBA111ACE835F326FE6AE /* showdown.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = showdown.js; sourceTree = ""; }; + 419D60462A50E9A91E55BF47 /* [ ].js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "[ ].js"; sourceTree = ""; }; + 42B59EEB0DCCE6D695636F67 /* LegacyMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyMigration.swift; sourceTree = ""; }; + 4ACF487AADDB8BB33F71BBDE /* fhconvert.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = fhconvert.js; sourceTree = ""; }; + 4B34871F4041DDF5A7D98840 /* features.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = features.md; sourceTree = ""; }; + 4ED996E53C34CFD8C7D0310C /* ClipMenuApp+Scenes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ClipMenuApp+Scenes.swift"; sourceTree = ""; }; + 5669B9BE900EF523AAFE399F /* html.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = html.js; sourceTree = ""; }; + 56CED544AE6F1EF258ED10D4 /* Collapse Spaces.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Collapse Spaces.js"; sourceTree = ""; }; + 620B8F52759F74FEBF46E0F1 /* ScriptableClip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptableClip.swift; sourceTree = ""; }; + 630C393A150A0A2DD37B2D11 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 65E27B62279E4C612E6FD0AC /* Convert Decimal to Character.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Decimal to Character.js"; sourceTree = ""; }; + 6669409568F7A199CA873CC3 /* Unescape HTML characters.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Unescape HTML characters.js"; sourceTree = ""; }; + 6CA10EBC72D8E5AE80FF0F4E /* AppExclusionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppExclusionService.swift; sourceTree = ""; }; + 78D2C9749DE0976D367B4137 /* Encode to Base64.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Encode to Base64.js"; sourceTree = ""; }; + 7DF8D7A913C65A7B9D98B687 /* Convert Zenkaku katakana to Hankaku katakana.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Zenkaku katakana to Hankaku katakana.js"; sourceTree = ""; }; + 83A17B48EFB6F8C9C5953E6C /* SnippetSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetSection.swift; sourceTree = ""; }; + 8480717B6E5E00346D1A2B51 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 8CF863742DF4C9510FA75342 /* ( ).js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "( ).js"; sourceTree = ""; }; + 8D78AE8D3F92F3B8B7ACACFD /* 〔 〕.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "〔 〕.js"; sourceTree = ""; }; + 8FAC9EE3C2A3F05DB8CB82A4 /* < >.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "< >.js"; sourceTree = ""; }; + 9075790B975D02A5039621CB /* ClipboardMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardMonitor.swift; sourceTree = ""; }; + 9B06FFF1F48BED207E608272 /* Convert Hankaku katakana to Zenkaku katakana.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Hankaku katakana to Zenkaku katakana.js"; sourceTree = ""; }; + 9C3C35D89529AE5775DEA3B4 /* Convert Hankaku alphanumeric characters to Zenkaku.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Hankaku alphanumeric characters to Zenkaku.js"; sourceTree = ""; }; + 9E6321E93388B5BFB5F35292 /* ActionSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionSection.swift; sourceTree = ""; }; + A15329B57CD738C87147D390 /* “ ”.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "“ ”.js"; sourceTree = ""; }; + A44363547A3A0692BC3EB462 /* char.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = char.js; sourceTree = ""; }; + A663BD7362E0C5445528C4F1 /* ActionNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionNode.swift; sourceTree = ""; }; + A665B545F09CB77A65913253 /* scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = scripts; path = Resources/scripts; sourceTree = SOURCE_ROOT; }; + A6C2A42099A7B3FE6149753C /* " ".js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "\" \".js"; sourceTree = ""; }; + A83BE5811A4FB6A1DB019AC2 /* ClipsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipsService.swift; sourceTree = ""; }; + AA18E6BAC3B61463FBA61589 /* ClipEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipEntry.swift; sourceTree = ""; }; + AB521B6B2DB86D0ACD8DAFC7 /* Escape HTML characters.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Escape HTML characters.js"; sourceTree = ""; }; + AE6E1C2B11B47F58BD83816D /* ClipMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClipMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; + AE76319566DD96015EDF23BA /* Convert Katakana to Hiragana.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Katakana to Hiragana.js"; sourceTree = ""; }; + AF2E8D3A4198B0765F64E64C /* Decode URI component.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Decode URI component.js"; sourceTree = ""; }; + AFA02BDF56F7F5BF80C2E4AA /* < >.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "< >.js"; sourceTree = ""; }; + AFC2785BEDC95DB32BD21552 /* ClipMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipMenuView.swift; sourceTree = ""; }; + B11A04D2CD51A76FE707BEA1 /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = ""; }; + B2C402FC20A31058F679AC66 /* [ ].js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "[ ].js"; sourceTree = ""; }; + B48E46B042ACC84B0F6F1766 /* LoginItemService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginItemService.swift; sourceTree = ""; }; + B4ADF0FD762FEE65EEE8DEBC /* inflection.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = inflection.js; sourceTree = ""; }; + B60996BF476330FFB6501381 /* Snippet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Snippet.swift; sourceTree = ""; }; + B9F2FC9E1D536A30571DAAAB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + BAD0F7706C0E03012259C58E /* SnippetFolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetFolder.swift; sourceTree = ""; }; + BB3D24622C12C3B43F770963 /* { }.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "{ }.js"; sourceTree = ""; }; + BF6C0BE229E6930FA608401B /* ClipMenu.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ClipMenu.entitlements; sourceTree = ""; }; + BFFC088DE2CD462BD34AB520 /* 《 》.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "《 》.js"; sourceTree = ""; }; + C0C2DEA9193BEC16FD145658 /* 【 】.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "【 】.js"; sourceTree = ""; }; + C0F0FAA9BB77661670F28FA6 /* ( ).js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "( ).js"; sourceTree = ""; }; + C47B7A1E32A72B3C15931D0E /* Title Case.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Title Case.js"; sourceTree = ""; }; + C53F23FA57EE7251E7DC8C6E /* MenuPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuPrefsView.swift; sourceTree = ""; }; + C6107A96E18C02167CD2BF95 /* { }.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "{ }.js"; sourceTree = ""; }; + CC0D05E32BADC3B23BA7F652 /* ' '.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "' '.js"; sourceTree = ""; }; + CDB67016D05B5750B90F5809 /* ‘ ’.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "‘ ’.js"; sourceTree = ""; }; + D2071986765235444ED5C4B6 /* ActionMenuBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionMenuBuilder.swift; sourceTree = ""; }; + D443B0D12EBBA794375C2643 /* PasteService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteService.swift; sourceTree = ""; }; + D4616EE385FA381E5A043060 /* SnippetService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetService.swift; sourceTree = ""; }; + D4FBE08D6142DF084563E0A2 /* Decode from Base64.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Decode from Base64.js"; sourceTree = ""; }; + D815EE9E2833C4392A353AAD /* Trim.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Trim.js; sourceTree = ""; }; + DC267D67332120F313F7EA31 /* EnvironmentKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentKeys.swift; sourceTree = ""; }; + DD1940E394AE1A2C53BBACAC /* RTrim.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = RTrim.js; sourceTree = ""; }; + DE38FE3285C8C6542C65BD62 /* Convert Hiragana to Katakana.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Hiragana to Katakana.js"; sourceTree = ""; }; + E06CE4CEDE07D2B72D5ED51C /* LTrim.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = LTrim.js; sourceTree = ""; }; + E3B5C233715C4B6C58F8E299 /* Calculate SHA-1 hash.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Calculate SHA-1 hash.js"; sourceTree = ""; }; + E4A00A1E1A0D43947431A0E2 /* lowercase.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = lowercase.js; sourceTree = ""; }; + EBDD749FF754FE72E7DB47E6 /* HotkeyService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotkeyService.swift; sourceTree = ""; }; + EBF7A7C9E337640DC76B28CB /* Convert Zenkaku alphanumeric characters to Hankaku.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Convert Zenkaku alphanumeric characters to Hankaku.js"; sourceTree = ""; }; + EFE2D0E62C25351BA06254E5 /* UPPERCASE.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = UPPERCASE.js; sourceTree = ""; }; + F04ADA9E33388D3B40D982F8 /* Strip Tags.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "Strip Tags.js"; sourceTree = ""; }; + F0BC75442C797B6A536F1862 /* 「 」.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "「 」.js"; sourceTree = ""; }; + F20169FFCAD9D79CBE1EB179 /* 〈 〉.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "〈 〉.js"; sourceTree = ""; }; + F425B2066AB9B7524D4770CD /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 8D11072E0486CEB800E47090 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, - 3518CE070D07966B00158053 /* Carbon.framework in Frameworks */, - 35939D670D42D38F006504B3 /* WebKit.framework in Frameworks */, - A8328DCD108859AE00A54DF4 /* ShortcutRecorder.framework in Frameworks */, - A897231B1095C6F500676306 /* Sparkle.framework in Frameworks */, - A8CEEA4D10AA465800C3823F /* BWToolkitFramework.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AE10EC3F8D700096102 /* Frameworks */ = { + 05B77AFF5C116FB1281714D4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A82B8AE20EC3F8D700096102 /* Cocoa.framework in Frameworks */, - A82B8AE30EC3F8D700096102 /* Carbon.framework in Frameworks */, - A82B8AE40EC3F8D700096102 /* WebKit.framework in Frameworks */, - A8328DCE108859AE00A54DF4 /* ShortcutRecorder.framework in Frameworks */, - A897231C1095C6F500676306 /* Sparkle.framework in Frameworks */, - A8CEEA4C10AA465800C3823F /* BWToolkitFramework.framework in Frameworks */, + FD1AC14BA0BC211BB0749243 /* KeyboardShortcuts in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { + 0C31C6DB5C7D8A1F645B725C /* JS-methods */ = { isa = PBXGroup; children = ( - 356F060C0D012C68003689C0 /* AppController.h */, - 356F060D0D012C68003689C0 /* AppController.m */, - A842D3230EA97DA200DCB303 /* constants.h */, - 3542A9290D5EC6C300B3BBBD /* CMUtilities.h */, - 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */, - 3518CA970D07646B00158053 /* MenuController.h */, - 3518CA980D07646C00158053 /* MenuController.m */, - 3505FF180D7FAE0000B55D03 /* Clip */, - A83A1FA210AA3F9A002CB62A /* Snippet */, - 3505FF150D7FADC400B55D03 /* Action */, - 3505FF140D7FAD8C00B55D03 /* Preferences */, - A85DC6C310B93F25005C7925 /* CocoaExtensions */, - A8A2D26D0EC1735C007DE280 /* PTHotKeys */, - A8328E0910885FAF00A54DF4 /* DBPrefsWindowController */, + A44363547A3A0692BC3EB462 /* char.js */, + 19B808EFAA8952BC9BA1CA8D /* string.js */, ); - name = Classes; + path = "JS-methods"; sourceTree = ""; }; - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + 1142AC27F2BF296FFE246D7B /* Preferences */ = { isa = PBXGroup; children = ( - 35939D660D42D38F006504B3 /* WebKit.framework */, - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, - 3518CE060D07966B00158053 /* Carbon.framework */, - A8328DCC108859AE00A54DF4 /* ShortcutRecorder.framework */, + 0F33CC09804F1E54781E0EBD /* ActionsPrefsView.swift */, + 2761ACB3529E51DE835B8478 /* GeneralPrefsView.swift */, + C53F23FA57EE7251E7DC8C6E /* MenuPrefsView.swift */, + 137B169B289424AA2C053F6E /* ShortcutsPrefsView.swift */, + 19473B9E42EE0B4041018F4D /* SnippetsPrefsView.swift */, ); - name = "Linked Frameworks"; + path = Preferences; sourceTree = ""; }; - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + 12AB7FCEC38DF292A503660A /* Services */ = { isa = PBXGroup; children = ( - 29B97324FDCFA39411CA2CEA /* AppKit.framework */, - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, - 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + 0CD6C21C72EE5244BB1D7613 /* ActionService.swift */, + A83BE5811A4FB6A1DB019AC2 /* ClipsService.swift */, + D4616EE385FA381E5A043060 /* SnippetService.swift */, ); - name = "Other Frameworks"; + path = Services; sourceTree = ""; }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { + 199F3DF7DF875EB03BE65B06 /* doc */ = { isa = PBXGroup; children = ( - 8D1107320486CEB800E47090 /* ClipMenu.app */, - A82B8AEB0EC3F8D700096102 /* ClipMenu.app */, + 30F9D13D4936E1E652C416E4 /* enhancements.md */, + 4B34871F4041DDF5A7D98840 /* features.md */, + 179AF605EB49F693BF4AD85E /* migration.md */, ); - name = Products; + path = doc; sourceTree = ""; }; - 29B97314FDCFA39411CA2CEA /* ClipMenu */ = { + 1C3A17C357BB67EAD06E9BEC /* UI */ = { isa = PBXGroup; children = ( - A89465DB0EB97A3D004ACD23 /* Models */, - 080E96DDFE201D6D7F000001 /* Classes */, - 3542A8620D5EBE0400B3BBBD /* NaoAdditions */, - 29B97315FDCFA39411CA2CEA /* Other Source */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = ClipMenu; + D2071986765235444ED5C4B6 /* ActionMenuBuilder.swift */, + 9E6321E93388B5BFB5F35292 /* ActionSection.swift */, + 4ED996E53C34CFD8C7D0310C /* ClipMenuApp+Scenes.swift */, + 0016B43E0CACE631C4CC81B1 /* ClipMenuItem.swift */, + AFC2785BEDC95DB32BD21552 /* ClipMenuView.swift */, + F425B2066AB9B7524D4770CD /* PreferencesView.swift */, + 83A17B48EFB6F8C9C5953E6C /* SnippetSection.swift */, + 1142AC27F2BF296FFE246D7B /* Preferences */, + ); + path = UI; sourceTree = ""; }; - 29B97315FDCFA39411CA2CEA /* Other Source */ = { + 27289B40538D236AA7D6F0B7 /* Migration */ = { isa = PBXGroup; children = ( - 32CA4F630368D1EE00C91783 /* ClipMenu_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, + 42B59EEB0DCCE6D695636F67 /* LegacyMigration.swift */, ); - name = "Other Source"; - path = Source; + path = Migration; sourceTree = ""; }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { + 2C91290915A8370DC0D9711F /* Case */ = { isa = PBXGroup; children = ( - A843AB080EBDAA03005A723A /* icons */, - A8DCABD710819C81006E02C8 /* StatusMenuIcons */, - A86E06D9119BD4D600DF8A58 /* SnippetEditor */, - 35C02FFA0D6BAB8300B95FF5 /* script */, - A821F5401085696E00B25C8B /* dsa_pub.pem */, - 8D1107310486CEB800E47090 /* Info.plist */, - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, - A878AA420EC411BE00112A8E /* Localizable.strings */, - A878AA890EC413B000112A8E /* Preferences.strings */, - A8234A4F10AA9F8200EB250C /* SnippetEditor.strings */, - A89716F20EA877CD005EE8E8 /* MainMenu.xib */, - A849BC580EE267C0009DF9D1 /* Preferences.xib */, - A8C53AB510AA6585001930BE /* SnippetEditor.xib */, + 2F809C93EED8F3156F24FC72 /* Capitalize.js */, + E4A00A1E1A0D43947431A0E2 /* lowercase.js */, + C47B7A1E32A72B3C15931D0E /* Title Case.js */, + EFE2D0E62C25351BA06254E5 /* UPPERCASE.js */, ); - name = Resources; + path = Case; sourceTree = ""; }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + 401A7197EC810F93DDB971C1 /* Trim */ = { isa = PBXGroup; children = ( - A8CEEA4B10AA465800C3823F /* BWToolkitFramework.framework */, - A897231A1095C6F500676306 /* Sparkle.framework */, - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + E06CE4CEDE07D2B72D5ED51C /* LTrim.js */, + DD1940E394AE1A2C53BBACAC /* RTrim.js */, + D815EE9E2833C4392A353AAD /* Trim.js */, ); - name = Frameworks; + path = Trim; sourceTree = ""; }; - 3505FF140D7FAD8C00B55D03 /* Preferences */ = { + 407969EF539F438C8347EF38 /* action */ = { isa = PBXGroup; children = ( - 35A42CC20D7D0ABA005FFB4C /* PrefsWindowController.h */, - 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */, - 3542A8C90D5EC15000B3BBBD /* ActionNodeController.h */, - 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */, - 3551F2BD0D75224900069069 /* ActionTypeTransformer.h */, - 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */, - A8DF42B00ED13E9100506877 /* ActionPopUpButton.h */, - A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */, - A8F56BCE10C2942D00646BDB /* NMLoginItems.h */, - A8F56BCF10C2942D00646BDB /* NMLoginItems.m */, + 56CED544AE6F1EF258ED10D4 /* Collapse Spaces.js */, + 268B85C5E498C2D963151455 /* Reverse.js */, + 2C91290915A8370DC0D9711F /* Case */, + 57A362CDE6C1C45E1AA984EC /* Crypt */, + 9376A80D07E9424EC38210FD /* HTML */, + FAF86C7190D49F4D6BB2A676 /* Japanese */, + 8B08DD47603CC3768E0DB566 /* Surround with */, + D86525B3A2826CC5ECCB598F /* Surround with (Japanese) */, + 401A7197EC810F93DDB971C1 /* Trim */, + ); + path = action; + sourceTree = ""; + }; + 4117F742CD5AC010C95693B2 /* Sources */ = { + isa = PBXGroup; + children = ( + 74FEA5EF5C7BB7FFDB77A6FD /* App */, + F755ED3311A8CB452BC467EB /* Infrastructure */, + 27289B40538D236AA7D6F0B7 /* Migration */, + 8E2DCB09DBCA5860A085715A /* Models */, + F80EEF064FDAC5D578301DF2 /* Scripting */, + 12AB7FCEC38DF292A503660A /* Services */, + A208D5DF7A819084D6B276BB /* Settings */, + 1C3A17C357BB67EAD06E9BEC /* UI */, + ); + path = Sources; + sourceTree = ""; + }; + 57A362CDE6C1C45E1AA984EC /* Crypt */ = { + isa = PBXGroup; + children = ( + 1FD73C6C287485CB59A08FEE /* Calculate MD5 hash.js */, + E3B5C233715C4B6C58F8E299 /* Calculate SHA-1 hash.js */, + D4FBE08D6142DF084563E0A2 /* Decode from Base64.js */, + 78D2C9749DE0976D367B4137 /* Encode to Base64.js */, ); - name = Preferences; + path = Crypt; sourceTree = ""; }; - 3505FF150D7FADC400B55D03 /* Action */ = { + 6859B965AEE7F3DFF1841686 = { isa = PBXGroup; children = ( - 35939DA90D42D4FE006504B3 /* ActionController.h */, - 35939DAA0D42D4FE006504B3 /* ActionController.m */, - 3505FF1E0D7FAF1F00B55D03 /* ActionNodeFactory.h */, - 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */, - 3542AD6D0D62828000B3BBBD /* ActionNode.h */, - 3542AD6E0D62828000B3BBBD /* ActionNode.m */, - 3505FF1B0D7FAE8300B55D03 /* ActionFactory.h */, - 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */, - 3505FF710D7FB14A00B55D03 /* BuiltInActionController.h */, - 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */, - 3551F3700D7658EF00069069 /* JavaScriptSupport.h */, - 3551F3710D7658EF00069069 /* JavaScriptSupport.m */, - A8FA6E5810AD66E200AFAB75 /* ScriptableClip.h */, - A8FA6E5910AD66E200AFAB75 /* ScriptableClip.m */, + B9F2FC9E1D536A30571DAAAB /* Assets.xcassets */, + BF6C0BE229E6930FA608401B /* ClipMenu.entitlements */, + 1AAA8A2C77102B5966216536 /* LICENSE */, + B11A04D2CD51A76FE707BEA1 /* project.yml */, + 8480717B6E5E00346D1A2B51 /* README.md */, + 199F3DF7DF875EB03BE65B06 /* doc */, + A06183AEA97ACC53713DC2B8 /* Resources */, + 4117F742CD5AC010C95693B2 /* Sources */, + C90771EDF751C2E74AB91204 /* Products */, ); - name = Action; - path = Source; sourceTree = ""; }; - 3505FF180D7FAE0000B55D03 /* Clip */ = { + 74FEA5EF5C7BB7FFDB77A6FD /* App */ = { isa = PBXGroup; children = ( - 356F073D0D024327003689C0 /* ClipsController.h */, - 356F073E0D024327003689C0 /* ClipsController.m */, - 3593F1830D025D5500B95536 /* Clip.h */, - 3593F1840D025D5500B95536 /* Clip.m */, + 630C393A150A0A2DD37B2D11 /* AppDelegate.swift */, + 0E215E86DBA662D409E0C3E8 /* AppRuntime.swift */, + 0CDD26CD466BFA583E75E608 /* ClipMenuApp.swift */, + DC267D67332120F313F7EA31 /* EnvironmentKeys.swift */, ); - name = Clip; - path = Source; + path = App; + sourceTree = ""; + }; + 8B08DD47603CC3768E0DB566 /* Surround with */ = { + isa = PBXGroup; + children = ( + CC0D05E32BADC3B23BA7F652 /* ' '.js */, + A6C2A42099A7B3FE6149753C /* " ".js */, + 8CF863742DF4C9510FA75342 /* ( ).js */, + 419D60462A50E9A91E55BF47 /* [ ].js */, + C6107A96E18C02167CD2BF95 /* { }.js */, + 05040ED7DB4E9E6B59B441AB /* ` `.js */, + AFA02BDF56F7F5BF80C2E4AA /* < >.js */, + ); + path = "Surround with"; sourceTree = ""; }; - 3542A8620D5EBE0400B3BBBD /* NaoAdditions */ = { + 8E2DCB09DBCA5860A085715A /* Models */ = { isa = PBXGroup; children = ( - 3542A8AD0D5EBF3800B3BBBD /* NSString+NaoAdditions.h */, - 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */, + A663BD7362E0C5445528C4F1 /* ActionNode.swift */, + AA18E6BAC3B61463FBA61589 /* ClipEntry.swift */, + B60996BF476330FFB6501381 /* Snippet.swift */, + BAD0F7706C0E03012259C58E /* SnippetFolder.swift */, ); - name = NaoAdditions; - path = ../../Library/NaoAdditions; - sourceTree = SOURCE_ROOT; + path = Models; + sourceTree = ""; + }; + 9376A80D07E9424EC38210FD /* HTML */ = { + isa = PBXGroup; + children = ( + 1C7B6FEA8365FA24B2DBB906 /* Convert Character to Decimal.js */, + 65E27B62279E4C612E6FD0AC /* Convert Decimal to Character.js */, + 091565A092F406927E15ED61 /* Convert Markdown to HTML.js */, + AF2E8D3A4198B0765F64E64C /* Decode URI component.js */, + 0FD091B978990ECF3F3D7E4E /* Encode URI component.js */, + AB521B6B2DB86D0ACD8DAFC7 /* Escape HTML characters.js */, + F04ADA9E33388D3B40D982F8 /* Strip Tags.js */, + 175D9BC47EBD304CA4230174 /* Surround with Tags....js */, + 6669409568F7A199CA873CC3 /* Unescape HTML characters.js */, + ); + path = HTML; + sourceTree = ""; }; - A8328E0910885FAF00A54DF4 /* DBPrefsWindowController */ = { + A06183AEA97ACC53713DC2B8 /* Resources */ = { isa = PBXGroup; children = ( - A8328E0A10885FAF00A54DF4 /* DBPrefsWindowController.h */, - A8328E0B10885FAF00A54DF4 /* DBPrefsWindowController.m */, + A665B545F09CB77A65913253 /* scripts */, + E03CEE8F2C7117BD9BE6E1E5 /* scripts */, ); - name = DBPrefsWindowController; - path = Source/DBPrefsWindowController; + path = Resources; sourceTree = ""; }; - A83A1FA210AA3F9A002CB62A /* Snippet */ = { + A208D5DF7A819084D6B276BB /* Settings */ = { isa = PBXGroup; children = ( - A89465E90EB97B92004ACD23 /* SnippetsController.h */, - A89465EA0EB97B92004ACD23 /* SnippetsController.m */, - A8CEEA0410AA42B500C3823F /* SnippetEditorController.h */, - A8CEEA0510AA42B500C3823F /* SnippetEditorController.m */, - A8F56B1410C272AF00646BDB /* FolderNode.h */, - A8F56B1510C272AF00646BDB /* FolderNode.m */, + 29576F23AAFF791919F37AA2 /* ClipMenuSettings.swift */, ); - name = Snippet; + path = Settings; sourceTree = ""; }; - A843AB080EBDAA03005A723A /* icons */ = { + B291E9FCF52786571D3DFF2F /* lib */ = { isa = PBXGroup; children = ( - 35A473480D20E8DE00E6B842 /* ClipMenu.icns */, - A87F7D04119FC41500420FF1 /* ClipMenu3.icns */, - 35C028940D6838D600B95FF5 /* ActionIcon.tiff */, - 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */, - 3578F76F0D7E3D5E00E804BF /* Menu.png */, - A8DF42840ED13BF000506877 /* Action.tiff */, - A8EBB687109190F900208A86 /* PTKeyboardIcon.tiff */, - A8975E9B1087042E00973851 /* SparkleIcon.tif */, - A8755B4A1164B0C500465B3B /* check.png */, + 4ACF487AADDB8BB33F71BBDE /* fhconvert.js */, + B4ADF0FD762FEE65EEE8DEBC /* inflection.js */, + 3E9CBA111ACE835F326FE6AE /* showdown.js */, + 0C31C6DB5C7D8A1F645B725C /* JS-methods */, + D50E19267744B818A3EF735F /* v8cgi */, ); - name = icons; + path = lib; sourceTree = ""; }; - A85DC6C310B93F25005C7925 /* CocoaExtensions */ = { + C90771EDF751C2E74AB91204 /* Products */ = { isa = PBXGroup; children = ( - A8F30E7D1000429E006F3F9A /* NSArray_Extensions.h */, - A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */, - A8F56BB910C292D400646BDB /* NSIndexPath_Extensions.h */, - A8F56BBA10C292D400646BDB /* NSIndexPath_Extensions.m */, - A894673C0EB999B5004ACD23 /* IndexedArrayController.h */, - A894673D0EB999B5004ACD23 /* IndexedArrayController.m */, - A823495510BFE3880045C1F4 /* BaseNode.h */, - A823495610BFE3880045C1F4 /* BaseNode.m */, - A82348FB10BFDEB00045C1F4 /* ImageAndTextCell.h */, - A82348FC10BFDEB00045C1F4 /* ImageAndTextCell.m */, - A8F568DD10C2239D00646BDB /* SeparatorCell.h */, - A8F568DE10C2239D00646BDB /* SeparatorCell.m */, - A86E478610B2D5E0000FB773 /* NSColor+String.h */, - A86E478710B2D5E0000FB773 /* NSColor+String.m */, + AE6E1C2B11B47F58BD83816D /* ClipMenu.app */, ); - name = CocoaExtensions; + name = Products; sourceTree = ""; }; - A86E06D9119BD4D600DF8A58 /* SnippetEditor */ = { + D50E19267744B818A3EF735F /* v8cgi */ = { isa = PBXGroup; children = ( - A86E0700119BF24200DF8A58 /* AddSnippet.tiff */, - A86E0706119BF38100DF8A58 /* CheckSnippet.tiff */, - A86E0707119BF38100DF8A58 /* DeleteSnippet.tiff */, + 5669B9BE900EF523AAFE399F /* html.js */, + 1E56AEC45D95D95509478467 /* util.js */, ); - name = SnippetEditor; - path = resource/SnippetEditor; + path = v8cgi; sourceTree = ""; }; - A89465DB0EB97A3D004ACD23 /* Models */ = { + D86525B3A2826CC5ECCB598F /* Surround with (Japanese) */ = { isa = PBXGroup; children = ( - A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */, + CDB67016D05B5750B90F5809 /* ‘ ’.js */, + A15329B57CD738C87147D390 /* “ ”.js */, + C0F0FAA9BB77661670F28FA6 /* ( ).js */, + B2C402FC20A31058F679AC66 /* [ ].js */, + BB3D24622C12C3B43F770963 /* { }.js */, + F20169FFCAD9D79CBE1EB179 /* 〈 〉.js */, + BFFC088DE2CD462BD34AB520 /* 《 》.js */, + F0BC75442C797B6A536F1862 /* 「 」.js */, + 2FC43A69E4D022001DD1564A /* 『 』.js */, + C0C2DEA9193BEC16FD145658 /* 【 】.js */, + 8D78AE8D3F92F3B8B7ACACFD /* 〔 〕.js */, + 8FAC9EE3C2A3F05DB8CB82A4 /* < >.js */, + ); + path = "Surround with (Japanese)"; + sourceTree = ""; + }; + E03CEE8F2C7117BD9BE6E1E5 /* scripts */ = { + isa = PBXGroup; + children = ( + 407969EF539F438C8347EF38 /* action */, + B291E9FCF52786571D3DFF2F /* lib */, ); - name = Models; + path = scripts; sourceTree = ""; }; - A8A2D26D0EC1735C007DE280 /* PTHotKeys */ = { + F755ED3311A8CB452BC467EB /* Infrastructure */ = { isa = PBXGroup; children = ( - A8A2D26E0EC1735C007DE280 /* PTHotKey.h */, - A8A2D26F0EC1735C007DE280 /* PTHotKey.m */, - A8A2D2700EC1735C007DE280 /* PTHotKeyCenter.h */, - A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */, - A8A2D2720EC1735C007DE280 /* PTKeyCodeTranslator.h */, - A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */, - A8A2D2740EC1735C007DE280 /* PTKeyCombo.h */, - A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */, + 6CA10EBC72D8E5AE80FF0F4E /* AppExclusionService.swift */, + 9075790B975D02A5039621CB /* ClipboardMonitor.swift */, + EBDD749FF754FE72E7DB47E6 /* HotkeyService.swift */, + B48E46B042ACC84B0F6F1766 /* LoginItemService.swift */, + D443B0D12EBBA794375C2643 /* PasteService.swift */, ); - name = PTHotKeys; - path = Source/PTHotKeys; + path = Infrastructure; sourceTree = ""; }; - A8DCABD710819C81006E02C8 /* StatusMenuIcons */ = { + F80EEF064FDAC5D578301DF2 /* Scripting */ = { isa = PBXGroup; children = ( - A8DCABD810819C81006E02C8 /* StatusMenuIcon.png */, - A8DCABD910819C81006E02C8 /* StatusMenuIcon_pressed.png */, - A8DCABDA10819C81006E02C8 /* StatusMenuIconFirst.png */, - A8DCABDB10819C81006E02C8 /* StatusMenuIconFirst_pressed.png */, - A8464D95108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png */, - A8464D96108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png */, - A8464D97108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png */, - A8464D98108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png */, - A8464D99108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png */, - A8464D9A108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png */, - A8464D9B108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png */, - A8464D9C108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png */, - A8464DD4108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png */, - A8464DD5108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png */, - A8A6350B116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png */, - A8A6350C116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png */, + 620B8F52759F74FEBF46E0F1 /* ScriptableClip.swift */, + 30E03F362BFE6F8406DB1DEB /* ScriptEngine.swift */, ); - name = StatusMenuIcons; - path = resource/StatusMenuIcons; + path = Scripting; + sourceTree = ""; + }; + FAF86C7190D49F4D6BB2A676 /* Japanese */ = { + isa = PBXGroup; + children = ( + 9C3C35D89529AE5775DEA3B4 /* Convert Hankaku alphanumeric characters to Zenkaku.js */, + 9B06FFF1F48BED207E608272 /* Convert Hankaku katakana to Zenkaku katakana.js */, + DE38FE3285C8C6542C65BD62 /* Convert Hiragana to Katakana.js */, + AE76319566DD96015EDF23BA /* Convert Katakana to Hiragana.js */, + EBF7A7C9E337640DC76B28CB /* Convert Zenkaku alphanumeric characters to Hankaku.js */, + 7DF8D7A913C65A7B9D98B687 /* Convert Zenkaku katakana to Hankaku katakana.js */, + ); + path = Japanese; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 8D1107260486CEB800E47090 /* ClipMenu */ = { + FB571C1A5EC141AC9E873616 /* ClipMenu */ = { isa = PBXNativeTarget; - buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ClipMenu" */; + buildConfigurationList = E3B0307747AE67BBBB721575 /* Build configuration list for PBXNativeTarget "ClipMenu" */; buildPhases = ( - 8D1107290486CEB800E47090 /* Resources */, - 8D11072C0486CEB800E47090 /* Sources */, - 8D11072E0486CEB800E47090 /* Frameworks */, + CB7BD82340923C1805AF65F6 /* Sources */, + 6303DF4644DE136EBB1AF2FB /* Resources */, + 05B77AFF5C116FB1281714D4 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = ClipMenu; - productInstallPath = "$(HOME)/Applications"; - productName = ClipMenu; - productReference = 8D1107320486CEB800E47090 /* ClipMenu.app */; - productType = "com.apple.product-type.application"; - }; - A82B8AB20EC3F8D700096102 /* ClipMenu (deployment) */ = { - isa = PBXNativeTarget; - buildConfigurationList = A82B8AE80EC3F8D700096102 /* Build configuration list for PBXNativeTarget "ClipMenu (deployment)" */; - buildPhases = ( - A82B8AB30EC3F8D700096102 /* ShellScript */, - A82B8AB40EC3F8D700096102 /* Resources */, - A82B8AC20EC3F8D700096102 /* Sources */, - A82B8AE10EC3F8D700096102 /* Frameworks */, - A82B8AE60EC3F8D700096102 /* CopyFiles */, - ); - buildRules = ( + packageProductDependencies = ( + D3A2344418DAEC005417850D /* KeyboardShortcuts */, ); - dependencies = ( - ); - name = "ClipMenu (deployment)"; - productInstallPath = "$(HOME)/Applications"; productName = ClipMenu; - productReference = A82B8AEB0EC3F8D700096102 /* ClipMenu.app */; + productReference = AE6E1C2B11B47F58BD83816D /* ClipMenu.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { + C147721A06508A644C48BA07 /* Project object */ = { isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ClipMenu" */; - compatibilityVersion = "Xcode 3.2"; - hasScannedForEncodings = 1; - mainGroup = 29B97314FDCFA39411CA2CEA /* ClipMenu */; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1600; + TargetAttributes = { + FB571C1A5EC141AC9E873616 = { + DevelopmentTeam = WTWBLR82TY; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 0B71DAA28DD07193080501BD /* Build configuration list for PBXProject "ClipMenu" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 6859B965AEE7F3DFF1841686; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + 6EF56059E79D1ADDB3EB9054 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = C90771EDF751C2E74AB91204 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 8D1107260486CEB800E47090 /* ClipMenu */, - A82B8AB20EC3F8D700096102 /* ClipMenu (deployment) */, + FB571C1A5EC141AC9E873616 /* ClipMenu */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 8D1107290486CEB800E47090 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, - A878AA430EC411BE00112A8E /* Localizable.strings in Resources */, - A878AA8A0EC413B000112A8E /* Preferences.strings in Resources */, - 35A473490D20E8DE00E6B842 /* ClipMenu.icns in Resources */, - 35C028950D6838D600B95FF5 /* ActionIcon.tiff in Resources */, - 35C028DC0D683C0200B95FF5 /* ActionIconLarge.tiff in Resources */, - 35C02FFE0D6BAB8300B95FF5 /* script in Resources */, - 3578F7700D7E3D5E00E804BF /* Menu.png in Resources */, - A89716F40EA877CD005EE8E8 /* MainMenu.xib in Resources */, - A849BC590EE267C0009DF9D1 /* Preferences.xib in Resources */, - A8DF42850ED13BF000506877 /* Action.tiff in Resources */, - A8DCABDE10819C81006E02C8 /* StatusMenuIcon.png in Resources */, - A8DCABDF10819C81006E02C8 /* StatusMenuIcon_pressed.png in Resources */, - A8DCABE010819C81006E02C8 /* StatusMenuIconFirst.png in Resources */, - A8DCABE110819C81006E02C8 /* StatusMenuIconFirst_pressed.png in Resources */, - A821F5411085696E00B25C8B /* dsa_pub.pem in Resources */, - A8975E9C1087042E00973851 /* SparkleIcon.tif in Resources */, - A8464D9D108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png in Resources */, - A8464D9E108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png in Resources */, - A8464D9F108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png in Resources */, - A8464DA0108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png in Resources */, - A8464DA1108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png in Resources */, - A8464DA2108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png in Resources */, - A8464DA3108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png in Resources */, - A8464DA4108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png in Resources */, - A8464DD6108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png in Resources */, - A8464DD7108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png in Resources */, - A8EBB688109190F900208A86 /* PTKeyboardIcon.tiff in Resources */, - A8C53AB610AA6585001930BE /* SnippetEditor.xib in Resources */, - A8234A5210AA9F8200EB250C /* SnippetEditor.strings in Resources */, - A8755B4C1164B0C500465B3B /* check.png in Resources */, - A8A6350F116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png in Resources */, - A8A63510116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png in Resources */, - A86E0702119BF24200DF8A58 /* AddSnippet.tiff in Resources */, - A86E070A119BF38100DF8A58 /* CheckSnippet.tiff in Resources */, - A86E070B119BF38100DF8A58 /* DeleteSnippet.tiff in Resources */, - A87F7D06119FC41500420FF1 /* ClipMenu3.icns in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AB40EC3F8D700096102 /* Resources */ = { + 6303DF4644DE136EBB1AF2FB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A82B8AB50EC3F8D700096102 /* InfoPlist.strings in Resources */, - A878AA440EC411BE00112A8E /* Localizable.strings in Resources */, - A878AA8B0EC413B000112A8E /* Preferences.strings in Resources */, - A82B8AB70EC3F8D700096102 /* ClipMenu.icns in Resources */, - A82B8AB90EC3F8D700096102 /* ActionIcon.tiff in Resources */, - A82B8ABA0EC3F8D700096102 /* ActionIconLarge.tiff in Resources */, - A82B8ABB0EC3F8D700096102 /* script in Resources */, - A82B8ABC0EC3F8D700096102 /* Menu.png in Resources */, - A86F93910ED183C30058E899 /* Action.tiff in Resources */, - A82B8ABD0EC3F8D700096102 /* MainMenu.xib in Resources */, - A849BC5A0EE267C0009DF9D1 /* Preferences.xib in Resources */, - A8DCABE410819C81006E02C8 /* StatusMenuIcon.png in Resources */, - A8DCABE510819C81006E02C8 /* StatusMenuIcon_pressed.png in Resources */, - A8DCABE610819C81006E02C8 /* StatusMenuIconFirst.png in Resources */, - A8DCABE710819C81006E02C8 /* StatusMenuIconFirst_pressed.png in Resources */, - A821F5421085696E00B25C8B /* dsa_pub.pem in Resources */, - A8975E9D1087042E00973851 /* SparkleIcon.tif in Resources */, - A8464DA5108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-left.png in Resources */, - A8464DA6108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-bw-right.png in Resources */, - A8464DA7108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-left.png in Resources */, - A8464DA8108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors1-color-right.png in Resources */, - A8464DA9108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-left.png in Resources */, - A8464DAA108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-bw-right.png in Resources */, - A8464DAB108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-left.png in Resources */, - A8464DAC108AAC3B0040C8C6 /* StatusMenuIconByDaveUlrich-scissors2-color-right.png in Resources */, - A8464DD8108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-bw.png in Resources */, - A8464DD9108AD6A90040C8C6 /* StatusMenuIconByDaveUlrich-diagonal-color.png in Resources */, - A8EBB689109190F900208A86 /* PTKeyboardIcon.tiff in Resources */, - A8C53AB710AA6585001930BE /* SnippetEditor.xib in Resources */, - A8234A5110AA9F8200EB250C /* SnippetEditor.strings in Resources */, - A8755B4B1164B0C500465B3B /* check.png in Resources */, - A8A6350D116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy_pressed.png in Resources */, - A8A6350E116C4F0F001ED122 /* StatusMenuIconBySuphiAksoy.png in Resources */, - A86E0701119BF24200DF8A58 /* AddSnippet.tiff in Resources */, - A86E0708119BF38100DF8A58 /* CheckSnippet.tiff in Resources */, - A86E0709119BF38100DF8A58 /* DeleteSnippet.tiff in Resources */, - A87F7D05119FC41500420FF1 /* ClipMenu3.icns in Resources */, + 85CEF62003CEC8629A60FEA4 /* Assets.xcassets in Resources */, + 6A9FBD0E7674740848F7DA2A /* scripts in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - A82B8AB30EC3F8D700096102 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - comments = "日本語ローカライズを生成"; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "genstrings -o English.lproj $(find . -name \"*.m\" ! -name \"CMUtilities.m\")\nibtool --generate-strings-file English.lproj/Preferences.strings English.lproj/Preferences.xib\nrm Japanese.lproj/Preferences.xib\nibtool --strings-file Japanese.lproj/Preferences.strings --write Japanese.lproj/Preferences.xib English.lproj/Preferences.xib\nibtool --generate-strings-file English.lproj/SnippetEditor.strings English.lproj/SnippetEditor.xib\nrm Japanese.lproj/SnippetEditor.xib\nibtool --strings-file Japanese.lproj/SnippetEditor.strings --write Japanese.lproj/SnippetEditor.xib English.lproj/SnippetEditor.xib\n"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ - 8D11072C0486CEB800E47090 /* Sources */ = { + CB7BD82340923C1805AF65F6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8D11072D0486CEB800E47090 /* main.m in Sources */, - 356F060E0D012C68003689C0 /* AppController.m in Sources */, - 356F073F0D024327003689C0 /* ClipsController.m in Sources */, - 3593F1850D025D5500B95536 /* Clip.m in Sources */, - 3518CA990D07646C00158053 /* MenuController.m in Sources */, - 35939DAB0D42D4FE006504B3 /* ActionController.m in Sources */, - 3542A8AF0D5EBF3800B3BBBD /* NSString+NaoAdditions.m in Sources */, - 3542A8CB0D5EC15000B3BBBD /* ActionNodeController.m in Sources */, - 3542A92B0D5EC6C300B3BBBD /* CMUtilities.m in Sources */, - 3542AD6F0D62828000B3BBBD /* ActionNode.m in Sources */, - 3551F2BF0D75224900069069 /* ActionTypeTransformer.m in Sources */, - 3551F3720D7658EF00069069 /* JavaScriptSupport.m in Sources */, - 35A42CC40D7D0ABA005FFB4C /* PrefsWindowController.m in Sources */, - 3505FF1D0D7FAE8300B55D03 /* ActionFactory.m in Sources */, - 3505FF200D7FAF1F00B55D03 /* ActionNodeFactory.m in Sources */, - 3505FF730D7FB14A00B55D03 /* BuiltInActionController.m in Sources */, - A89465E60EB97A62004ACD23 /* Snippets.xcdatamodel in Sources */, - A89465EB0EB97B92004ACD23 /* SnippetsController.m in Sources */, - A894673E0EB999B5004ACD23 /* IndexedArrayController.m in Sources */, - A8A2D2760EC1735C007DE280 /* PTHotKey.m in Sources */, - A8A2D2770EC1735C007DE280 /* PTHotKeyCenter.m in Sources */, - A8A2D2780EC1735C007DE280 /* PTKeyCodeTranslator.m in Sources */, - A8A2D2790EC1735C007DE280 /* PTKeyCombo.m in Sources */, - A8DF42B20ED13E9100506877 /* ActionPopUpButton.m in Sources */, - A8F30E811000429E006F3F9A /* NSArray_Extensions.m in Sources */, - A8328E0C10885FAF00A54DF4 /* DBPrefsWindowController.m in Sources */, - A8CEEA0710AA42B500C3823F /* SnippetEditorController.m in Sources */, - A8FA6E5B10AD66E200AFAB75 /* ScriptableClip.m in Sources */, - A86E478910B2D5E0000FB773 /* NSColor+String.m in Sources */, - A82348FE10BFDEB00045C1F4 /* ImageAndTextCell.m in Sources */, - A823495810BFE3880045C1F4 /* BaseNode.m in Sources */, - A8F568E010C2239D00646BDB /* SeparatorCell.m in Sources */, - A8F56B1710C272AF00646BDB /* FolderNode.m in Sources */, - A8F56BBC10C292D400646BDB /* NSIndexPath_Extensions.m in Sources */, - A8F56BD110C2942D00646BDB /* NMLoginItems.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AC20EC3F8D700096102 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A86F939A0ED183FC0058E899 /* ActionPopUpButton.m in Sources */, - A82B8AC30EC3F8D700096102 /* main.m in Sources */, - A82B8AC40EC3F8D700096102 /* AppController.m in Sources */, - A82B8AC50EC3F8D700096102 /* ClipsController.m in Sources */, - A82B8AC60EC3F8D700096102 /* Clip.m in Sources */, - A82B8AC70EC3F8D700096102 /* MenuController.m in Sources */, - A82B8AC80EC3F8D700096102 /* ActionController.m in Sources */, - A82B8ACB0EC3F8D700096102 /* NSString+NaoAdditions.m in Sources */, - A82B8ACC0EC3F8D700096102 /* ActionNodeController.m in Sources */, - A82B8ACD0EC3F8D700096102 /* CMUtilities.m in Sources */, - A82B8ACE0EC3F8D700096102 /* ActionNode.m in Sources */, - A82B8AD00EC3F8D700096102 /* ActionTypeTransformer.m in Sources */, - A82B8AD10EC3F8D700096102 /* JavaScriptSupport.m in Sources */, - A82B8AD30EC3F8D700096102 /* PrefsWindowController.m in Sources */, - A82B8AD40EC3F8D700096102 /* ActionFactory.m in Sources */, - A82B8AD50EC3F8D700096102 /* ActionNodeFactory.m in Sources */, - A82B8AD60EC3F8D700096102 /* BuiltInActionController.m in Sources */, - A82B8AD90EC3F8D700096102 /* Snippets.xcdatamodel in Sources */, - A82B8ADA0EC3F8D700096102 /* SnippetsController.m in Sources */, - A82B8ADC0EC3F8D700096102 /* IndexedArrayController.m in Sources */, - A82B8ADD0EC3F8D700096102 /* PTHotKey.m in Sources */, - A82B8ADE0EC3F8D700096102 /* PTHotKeyCenter.m in Sources */, - A82B8ADF0EC3F8D700096102 /* PTKeyCodeTranslator.m in Sources */, - A82B8AE00EC3F8D700096102 /* PTKeyCombo.m in Sources */, - A8F30E831000429E006F3F9A /* NSArray_Extensions.m in Sources */, - A8328E0D10885FAF00A54DF4 /* DBPrefsWindowController.m in Sources */, - A8CEEA0610AA42B500C3823F /* SnippetEditorController.m in Sources */, - A8FA6E5A10AD66E200AFAB75 /* ScriptableClip.m in Sources */, - A86E478810B2D5E0000FB773 /* NSColor+String.m in Sources */, - A82348FD10BFDEB00045C1F4 /* ImageAndTextCell.m in Sources */, - A823495710BFE3880045C1F4 /* BaseNode.m in Sources */, - A8F568DF10C2239D00646BDB /* SeparatorCell.m in Sources */, - A8F56B1610C272AF00646BDB /* FolderNode.m in Sources */, - A8F56BBB10C292D400646BDB /* NSIndexPath_Extensions.m in Sources */, - A8F56BD010C2942D00646BDB /* NMLoginItems.m in Sources */, + EAA8E570AEAA9695CC422081 /* ActionMenuBuilder.swift in Sources */, + 00CE4E605010BDF7D2B57FCB /* ActionNode.swift in Sources */, + E3A5BEAC6D55B0DBE1B56388 /* ActionSection.swift in Sources */, + 9A4C53BF9C1CD72C0D832BAF /* ActionService.swift in Sources */, + F89987AC92544F66743A4CC7 /* ActionsPrefsView.swift in Sources */, + A976327DD179929219A27364 /* AppDelegate.swift in Sources */, + F9343715F430A05D2DD97E34 /* AppExclusionService.swift in Sources */, + 76969A92D3459A30D0C7A6E2 /* AppRuntime.swift in Sources */, + 951A172FEC26A436F6BC3232 /* ClipEntry.swift in Sources */, + 5F656B886B8F29CC5617F8BB /* ClipMenuApp+Scenes.swift in Sources */, + 80C5101B8CC05DF5E188A131 /* ClipMenuApp.swift in Sources */, + 6F1C323AB9B0297F0E353CCF /* ClipMenuItem.swift in Sources */, + 609E344BBBB03FD8514E6C91 /* ClipMenuSettings.swift in Sources */, + BA02CE3D4BA737DCD6AC686A /* ClipMenuView.swift in Sources */, + 34EB7B9526F4C2AAF8291A23 /* ClipboardMonitor.swift in Sources */, + 2F8F707D3AF29A98FCBA6CAF /* ClipsService.swift in Sources */, + 40A1F4EED97AF8553F7672B0 /* EnvironmentKeys.swift in Sources */, + 936E1E26F533AC6B39414F5D /* GeneralPrefsView.swift in Sources */, + E1DFEA8B6C7669DFC34FBC0C /* HotkeyService.swift in Sources */, + 21AD2E3FCA0D9D76AC02FA23 /* LegacyMigration.swift in Sources */, + D54B008B6D9741A0002054BB /* LoginItemService.swift in Sources */, + 529A9D03AD998DAE8ADB2A00 /* MenuPrefsView.swift in Sources */, + CBE9A7D84EC7FB0CD880BA51 /* PasteService.swift in Sources */, + B7B65D3023B9F10BA44E782E /* PreferencesView.swift in Sources */, + A4C24CFC70012228839FBA18 /* ScriptEngine.swift in Sources */, + 03BE0E0A2BE4CD13C915121A /* ScriptableClip.swift in Sources */, + 9BB7C546A30CC1666078A52B /* ShortcutsPrefsView.swift in Sources */, + 49010720EA3588BD56645417 /* Snippet.swift in Sources */, + 87A7B382426FBCFEB7553409 /* SnippetFolder.swift in Sources */, + A50FD9C591A6F8E6E86F6075 /* SnippetSection.swift in Sources */, + BDE2E92131BD9586D21FB6FD /* SnippetService.swift in Sources */, + 4611B4DE54886E009EE9970F /* SnippetsPrefsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXVariantGroup section */ - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 089C165DFE840E0CC02AAC07 /* English */, - A821F5861085DA8A00B25C8B /* Japanese */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - A8234A4F10AA9F8200EB250C /* SnippetEditor.strings */ = { - isa = PBXVariantGroup; - children = ( - A8234A5010AA9F8200EB250C /* English */, - A8234A6910AAA05E00EB250C /* Japanese */, - ); - name = SnippetEditor.strings; - sourceTree = ""; - }; - A849BC580EE267C0009DF9D1 /* Preferences.xib */ = { - isa = PBXVariantGroup; - children = ( - A89716F70EA8780B005EE8E8 /* English */, - A849BC5B0EE267C8009DF9D1 /* Japanese */, - ); - name = Preferences.xib; - sourceTree = ""; - }; - A878AA420EC411BE00112A8E /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 3578645D0D23A82400FAFFC5 /* English */, - A878AA450EC411C400112A8E /* Japanese */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - A878AA890EC413B000112A8E /* Preferences.strings */ = { - isa = PBXVariantGroup; - children = ( - A82B8A460EC3DD0A00096102 /* English */, - A878AA8C0EC413B700112A8E /* Japanese */, - ); - name = Preferences.strings; - sourceTree = ""; - }; - A89716F20EA877CD005EE8E8 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - A89716F30EA877CD005EE8E8 /* English */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; - A8C53AB510AA6585001930BE /* SnippetEditor.xib */ = { - isa = PBXVariantGroup; - children = ( - A8DC723210A91D61001D3E99 /* English */, - A8C53AB810AA658D001930BE /* Japanese */, - ); - name = SnippetEditor.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ - A82B8AE90EC3F8D700096102 /* Debug */ = { + 4D8DEF6CD0EEAA9714466483 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", - ); - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_MISSING_PARENTHESES = NO; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.5; - PRODUCT_NAME = ClipMenu; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx10.6; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; }; - name = Debug; + name = Release; }; - A82B8AEA0EC3F8D700096102 /* Release */ = { + 766973F3AF86C41151F11C36 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - DEPLOYMENT_POSTPROCESSING = YES; - FRAMEWORK_SEARCH_PATHS = ( + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; + CODE_SIGN_ENTITLEMENTS = ClipMenu.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = WTWBLR82TY; + ENABLE_HARDENED_RUNTIME = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = ClipMenu; + INFOPLIST_KEY_CFBundleIconName = AppIcon; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_LSUIElement = YES; + INFOPLIST_KEY_NSPrincipalClass = NSApplication; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", + "@executable_path/../Frameworks", ); - GCC_C_LANGUAGE_STANDARD = c99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G5; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_MISSING_PARENTHESES = NO; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.5; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0.0; + PRODUCT_BUNDLE_IDENTIFIER = app.eetr.ClipMenu; PRODUCT_NAME = ClipMenu; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx10.6; - WRAPPER_EXTENSION = app; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.9; }; name = Release; }; - C01FCF4B08A954540054247B /* Debug */ = { + 8AD49DDCE0CCCD152CD9A186 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", - ); - GCC_C_LANGUAGE_STANDARD = c99; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_MODEL_TUNING = G5; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_MISSING_PARENTHESES = NO; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.5; - PRODUCT_NAME = ClipMenu; - RUN_CLANG_STATIC_ANALYZER = NO; - SDKROOT = macosx10.6; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; - C01FCF4C08A954540054247B /* Release */ = { + F1AEEC31C7782053C3601DD8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - DEPLOYMENT_POSTPROCESSING = YES; - FRAMEWORK_SEARCH_PATHS = ( + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; + CODE_SIGN_ENTITLEMENTS = ClipMenu.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = WTWBLR82TY; + ENABLE_HARDENED_RUNTIME = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = ClipMenu; + INFOPLIST_KEY_CFBundleIconName = AppIcon; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_LSUIElement = YES; + INFOPLIST_KEY_NSPrincipalClass = NSApplication; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", + "@executable_path/../Frameworks", ); - GCC_C_LANGUAGE_STANDARD = c99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G5; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_MISSING_PARENTHESES = NO; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.5; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0.0; + PRODUCT_BUNDLE_IDENTIFIER = app.eetr.ClipMenu; PRODUCT_NAME = ClipMenu; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx10.6; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.9; }; name = Debug; }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - A82B8AE80EC3F8D700096102 /* Build configuration list for PBXNativeTarget "ClipMenu (deployment)" */ = { + 0B71DAA28DD07193080501BD /* Build configuration list for PBXProject "ClipMenu" */ = { isa = XCConfigurationList; buildConfigurations = ( - A82B8AE90EC3F8D700096102 /* Debug */, - A82B8AEA0EC3F8D700096102 /* Release */, + 8AD49DDCE0CCCD152CD9A186 /* Debug */, + 4D8DEF6CD0EEAA9714466483 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Debug; }; - C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ClipMenu" */ = { + E3B0307747AE67BBBB721575 /* Build configuration list for PBXNativeTarget "ClipMenu" */ = { isa = XCConfigurationList; buildConfigurations = ( - C01FCF4B08A954540054247B /* Debug */, - C01FCF4C08A954540054247B /* Release */, + F1AEEC31C7782053C3601DD8 /* Debug */, + 766973F3AF86C41151F11C36 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ClipMenu" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 6EF56059E79D1ADDB3EB9054 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/sindresorhus/KeyboardShortcuts"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + D3A2344418DAEC005417850D /* KeyboardShortcuts */ = { + isa = XCSwiftPackageProductDependency; + package = 6EF56059E79D1ADDB3EB9054 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */; + productName = KeyboardShortcuts; + }; +/* End XCSwiftPackageProductDependency section */ }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; + rootObject = C147721A06508A644C48BA07 /* Project object */; } diff --git a/ClipMenu.xcodeproj/project.pbxproj.orig b/ClipMenu.xcodeproj/project.pbxproj.orig deleted file mode 100644 index 53ca4c7..0000000 --- a/ClipMenu.xcodeproj/project.pbxproj.orig +++ /dev/null @@ -1,861 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 45; - objects = { - -/* Begin PBXBuildFile section */ - 3505FF1D0D7FAE8300B55D03 /* ActionFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */; }; - 3505FF200D7FAF1F00B55D03 /* ActionNodeFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */; }; - 3505FF730D7FB14A00B55D03 /* BuiltInActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */; }; - 3518CA990D07646C00158053 /* MenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3518CA980D07646C00158053 /* MenuController.m */; }; - 3518CE070D07966B00158053 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3518CE060D07966B00158053 /* Carbon.framework */; }; - 3542A8AF0D5EBF3800B3BBBD /* NSString+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */; }; - 3542A8CB0D5EC15000B3BBBD /* ActionNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */; }; - 3542A92B0D5EC6C300B3BBBD /* CMUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */; }; - 3542AD6F0D62828000B3BBBD /* ActionNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542AD6E0D62828000B3BBBD /* ActionNode.m */; }; - 3551F2BF0D75224900069069 /* ActionTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */; }; - 3551F3720D7658EF00069069 /* JavaScriptSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F3710D7658EF00069069 /* JavaScriptSupport.m */; }; - 356F060E0D012C68003689C0 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F060D0D012C68003689C0 /* AppController.m */; }; - 356F073F0D024327003689C0 /* ClipsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F073E0D024327003689C0 /* ClipsController.m */; }; - 3578F7700D7E3D5E00E804BF /* Menu.png in Resources */ = {isa = PBXBuildFile; fileRef = 3578F76F0D7E3D5E00E804BF /* Menu.png */; }; - 35939D670D42D38F006504B3 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35939D660D42D38F006504B3 /* WebKit.framework */; }; - 35939DAB0D42D4FE006504B3 /* ActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35939DAA0D42D4FE006504B3 /* ActionController.m */; }; - 3593F1850D025D5500B95536 /* Clip.m in Sources */ = {isa = PBXBuildFile; fileRef = 3593F1840D025D5500B95536 /* Clip.m */; }; - 35A42CC00D7D0A6F005FFB4C /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CBF0D7D0A6F005FFB4C /* DBPrefsWindowController.m */; }; - 35A42CC40D7D0ABA005FFB4C /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */; }; - 35A472BC0D20DEC500E6B842 /* StatusMenuIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 35A472BB0D20DEC500E6B842 /* StatusMenuIcon.png */; }; - 35A473490D20E8DE00E6B842 /* ClipMenu.icns in Resources */ = {isa = PBXBuildFile; fileRef = 35A473480D20E8DE00E6B842 /* ClipMenu.icns */; }; - 35C028950D6838D600B95FF5 /* ActionIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028940D6838D600B95FF5 /* ActionIcon.tiff */; }; - 35C028DC0D683C0200B95FF5 /* ActionIconLarge.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */; }; - 35C02FFE0D6BAB8300B95FF5 /* script in Resources */ = {isa = PBXBuildFile; fileRef = 35C02FFA0D6BAB8300B95FF5 /* script */; }; - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - A809DF6F0EAD9A3400745313 /* GTMLoginItems.m in Sources */ = {isa = PBXBuildFile; fileRef = A809DF6E0EAD9A3400745313 /* GTMLoginItems.m */; }; - A82B8AB50EC3F8D700096102 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - A82B8AB60EC3F8D700096102 /* StatusMenuIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 35A472BB0D20DEC500E6B842 /* StatusMenuIcon.png */; }; - A82B8AB70EC3F8D700096102 /* ClipMenu.icns in Resources */ = {isa = PBXBuildFile; fileRef = 35A473480D20E8DE00E6B842 /* ClipMenu.icns */; }; - A82B8AB90EC3F8D700096102 /* ActionIcon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028940D6838D600B95FF5 /* ActionIcon.tiff */; }; - A82B8ABA0EC3F8D700096102 /* ActionIconLarge.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */; }; - A82B8ABB0EC3F8D700096102 /* script in Resources */ = {isa = PBXBuildFile; fileRef = 35C02FFA0D6BAB8300B95FF5 /* script */; }; - A82B8ABC0EC3F8D700096102 /* Menu.png in Resources */ = {isa = PBXBuildFile; fileRef = 3578F76F0D7E3D5E00E804BF /* Menu.png */; }; - A82B8ABD0EC3F8D700096102 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A89716F20EA877CD005EE8E8 /* MainMenu.xib */; }; - A82B8ABF0EC3F8D700096102 /* ComposingPreferences.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A894663C0EB98949004ACD23 /* ComposingPreferences.tiff */; }; - A82B8AC00EC3F8D700096102 /* StatusMenuIcon_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A843AB1B0EBDAA4D005A723A /* StatusMenuIcon_pressed.png */; }; - A82B8AC30EC3F8D700096102 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - A82B8AC40EC3F8D700096102 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F060D0D012C68003689C0 /* AppController.m */; }; - A82B8AC50EC3F8D700096102 /* ClipsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 356F073E0D024327003689C0 /* ClipsController.m */; }; - A82B8AC60EC3F8D700096102 /* Clip.m in Sources */ = {isa = PBXBuildFile; fileRef = 3593F1840D025D5500B95536 /* Clip.m */; }; - A82B8AC70EC3F8D700096102 /* MenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3518CA980D07646C00158053 /* MenuController.m */; }; - A82B8AC80EC3F8D700096102 /* ActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35939DAA0D42D4FE006504B3 /* ActionController.m */; }; - A82B8ACB0EC3F8D700096102 /* NSString+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */; }; - A82B8ACC0EC3F8D700096102 /* ActionNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */; }; - A82B8ACD0EC3F8D700096102 /* CMUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */; }; - A82B8ACE0EC3F8D700096102 /* ActionNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3542AD6E0D62828000B3BBBD /* ActionNode.m */; }; - A82B8AD00EC3F8D700096102 /* ActionTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */; }; - A82B8AD10EC3F8D700096102 /* JavaScriptSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3551F3710D7658EF00069069 /* JavaScriptSupport.m */; }; - A82B8AD20EC3F8D700096102 /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CBF0D7D0A6F005FFB4C /* DBPrefsWindowController.m */; }; - A82B8AD30EC3F8D700096102 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */; }; - A82B8AD40EC3F8D700096102 /* ActionFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */; }; - A82B8AD50EC3F8D700096102 /* ActionNodeFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */; }; - A82B8AD60EC3F8D700096102 /* BuiltInActionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */; }; - A82B8AD70EC3F8D700096102 /* NSIndexPath+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F628D30EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m */; }; - A82B8AD80EC3F8D700096102 /* GTMLoginItems.m in Sources */ = {isa = PBXBuildFile; fileRef = A809DF6E0EAD9A3400745313 /* GTMLoginItems.m */; }; - A82B8AD90EC3F8D700096102 /* Snippets.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */; }; - A82B8ADA0EC3F8D700096102 /* SnippetsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89465EA0EB97B92004ACD23 /* SnippetsController.m */; }; - A82B8ADB0EC3F8D700096102 /* SnippetPrefsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89466900EB98C62004ACD23 /* SnippetPrefsController.m */; }; - A82B8ADC0EC3F8D700096102 /* IndexedArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = A894673D0EB999B5004ACD23 /* IndexedArrayController.m */; }; - A82B8ADD0EC3F8D700096102 /* PTHotKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D26F0EC1735C007DE280 /* PTHotKey.m */; }; - A82B8ADE0EC3F8D700096102 /* PTHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */; }; - A82B8ADF0EC3F8D700096102 /* PTKeyCodeTranslator.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */; }; - A82B8AE00EC3F8D700096102 /* PTKeyCombo.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */; }; - A82B8AE20EC3F8D700096102 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - A82B8AE30EC3F8D700096102 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3518CE060D07966B00158053 /* Carbon.framework */; }; - A82B8AE40EC3F8D700096102 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35939D660D42D38F006504B3 /* WebKit.framework */; }; - A82B8AE50EC3F8D700096102 /* ShortcutRecorder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A2D1D10EC16B61007DE280 /* ShortcutRecorder.framework */; }; - A82B8AE70EC3F8D700096102 /* ShortcutRecorder.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A8A2D1D10EC16B61007DE280 /* ShortcutRecorder.framework */; }; - A843AB1C0EBDAA4D005A723A /* StatusMenuIcon_pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A843AB1B0EBDAA4D005A723A /* StatusMenuIcon_pressed.png */; }; - A849BC590EE267C0009DF9D1 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = A849BC580EE267C0009DF9D1 /* Preferences.xib */; }; - A849BC5A0EE267C0009DF9D1 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = A849BC580EE267C0009DF9D1 /* Preferences.xib */; }; - A86F93910ED183C30058E899 /* Action.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8DF42840ED13BF000506877 /* Action.tiff */; }; - A86F939A0ED183FC0058E899 /* ActionPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */; }; - A878AA430EC411BE00112A8E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA420EC411BE00112A8E /* Localizable.strings */; }; - A878AA440EC411BE00112A8E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA420EC411BE00112A8E /* Localizable.strings */; }; - A878AA8A0EC413B000112A8E /* Preferences.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA890EC413B000112A8E /* Preferences.strings */; }; - A878AA8B0EC413B000112A8E /* Preferences.strings in Resources */ = {isa = PBXBuildFile; fileRef = A878AA890EC413B000112A8E /* Preferences.strings */; }; - A89465E60EB97A62004ACD23 /* Snippets.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */; }; - A89465EB0EB97B92004ACD23 /* SnippetsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89465EA0EB97B92004ACD23 /* SnippetsController.m */; }; - A894663D0EB98949004ACD23 /* ComposingPreferences.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A894663C0EB98949004ACD23 /* ComposingPreferences.tiff */; }; - A89466910EB98C62004ACD23 /* SnippetPrefsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A89466900EB98C62004ACD23 /* SnippetPrefsController.m */; }; - A894673E0EB999B5004ACD23 /* IndexedArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = A894673D0EB999B5004ACD23 /* IndexedArrayController.m */; }; - A89716F40EA877CD005EE8E8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A89716F20EA877CD005EE8E8 /* MainMenu.xib */; }; - A8A2D1D20EC16B61007DE280 /* ShortcutRecorder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A2D1D10EC16B61007DE280 /* ShortcutRecorder.framework */; }; - A8A2D2760EC1735C007DE280 /* PTHotKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D26F0EC1735C007DE280 /* PTHotKey.m */; }; - A8A2D2770EC1735C007DE280 /* PTHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */; }; - A8A2D2780EC1735C007DE280 /* PTKeyCodeTranslator.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */; }; - A8A2D2790EC1735C007DE280 /* PTKeyCombo.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */; }; - A8DF42850ED13BF000506877 /* Action.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A8DF42840ED13BF000506877 /* Action.tiff */; }; - A8DF42B20ED13E9100506877 /* ActionPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */; }; - A8F30E53100041BC006F3F9A /* BaseNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E4E100041BC006F3F9A /* BaseNode.m */; }; - A8F30E54100041BC006F3F9A /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E50100041BC006F3F9A /* ImageAndTextCell.m */; }; - A8F30E56100041BC006F3F9A /* BaseNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E4E100041BC006F3F9A /* BaseNode.m */; }; - A8F30E57100041BC006F3F9A /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E50100041BC006F3F9A /* ImageAndTextCell.m */; }; - A8F30E811000429E006F3F9A /* NSArray_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */; }; - A8F30E821000429E006F3F9A /* NSTreeController_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7F1000429E006F3F9A /* NSTreeController_Extensions.m */; }; - A8F30E831000429E006F3F9A /* NSArray_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */; }; - A8F30E841000429E006F3F9A /* NSTreeController_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F30E7F1000429E006F3F9A /* NSTreeController_Extensions.m */; }; - A8F628D40EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F628D30EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - A82B8AE60EC3F8D700096102 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - A82B8AE70EC3F8D700096102 /* ShortcutRecorder.framework in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* ClipMenu_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClipMenu_Prefix.pch; path = ../ClipMenu_Prefix.pch; sourceTree = ""; }; - 3505FF1B0D7FAE8300B55D03 /* ActionFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionFactory.h; sourceTree = ""; }; - 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionFactory.m; sourceTree = ""; }; - 3505FF1E0D7FAF1F00B55D03 /* ActionNodeFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionNodeFactory.h; sourceTree = ""; }; - 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionNodeFactory.m; sourceTree = ""; }; - 3505FF710D7FB14A00B55D03 /* BuiltInActionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltInActionController.h; sourceTree = ""; }; - 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuiltInActionController.m; sourceTree = ""; }; - 3518CA970D07646B00158053 /* MenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuController.h; path = Source/MenuController.h; sourceTree = ""; }; - 3518CA980D07646C00158053 /* MenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuController.m; path = Source/MenuController.m; sourceTree = ""; }; - 3518CE060D07966B00158053 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; - 3542A8650D5EBE0400B3BBBD /* NSTreeController+NaoAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTreeController+NaoAdditions.h"; sourceTree = ""; }; - 3542A8AD0D5EBF3800B3BBBD /* NSString+NaoAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+NaoAdditions.h"; sourceTree = ""; }; - 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+NaoAdditions.m"; sourceTree = ""; }; - 3542A8C90D5EC15000B3BBBD /* ActionNodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionNodeController.h; sourceTree = ""; }; - 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionNodeController.m; sourceTree = ""; }; - 3542A9290D5EC6C300B3BBBD /* CMUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMUtilities.h; path = Source/CMUtilities.h; sourceTree = ""; }; - 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CMUtilities.m; path = Source/CMUtilities.m; sourceTree = ""; }; - 3542AD6D0D62828000B3BBBD /* ActionNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionNode.h; sourceTree = ""; }; - 3542AD6E0D62828000B3BBBD /* ActionNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionNode.m; sourceTree = ""; }; - 3551F2BD0D75224900069069 /* ActionTypeTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ActionTypeTransformer.h; path = Source/ActionTypeTransformer.h; sourceTree = ""; }; - 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ActionTypeTransformer.m; path = Source/ActionTypeTransformer.m; sourceTree = ""; }; - 3551F3700D7658EF00069069 /* JavaScriptSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptSupport.h; sourceTree = ""; }; - 3551F3710D7658EF00069069 /* JavaScriptSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSupport.m; sourceTree = ""; }; - 356F060C0D012C68003689C0 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppController.h; path = Source/AppController.h; sourceTree = ""; }; - 356F060D0D012C68003689C0 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppController.m; path = Source/AppController.m; sourceTree = ""; }; - 356F073D0D024327003689C0 /* ClipsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClipsController.h; sourceTree = ""; }; - 356F073E0D024327003689C0 /* ClipsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClipsController.m; sourceTree = ""; }; - 3578645D0D23A82400FAFFC5 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; - 3578F76F0D7E3D5E00E804BF /* Menu.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Menu.png; path = resource/Menu.png; sourceTree = ""; }; - 35939D660D42D38F006504B3 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = ""; }; - 35939DA90D42D4FE006504B3 /* ActionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionController.h; sourceTree = ""; }; - 35939DAA0D42D4FE006504B3 /* ActionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionController.m; sourceTree = ""; }; - 3593F1830D025D5500B95536 /* Clip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clip.h; sourceTree = ""; }; - 3593F1840D025D5500B95536 /* Clip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clip.m; sourceTree = ""; }; - 35A42CBE0D7D0A6F005FFB4C /* DBPrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DBPrefsWindowController.h; path = ../../Vendor/DBPrefsWindowController/Source/DBPrefsWindowController.h; sourceTree = SOURCE_ROOT; }; - 35A42CBF0D7D0A6F005FFB4C /* DBPrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DBPrefsWindowController.m; path = ../../Vendor/DBPrefsWindowController/Source/DBPrefsWindowController.m; sourceTree = SOURCE_ROOT; }; - 35A42CC20D7D0ABA005FFB4C /* PrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrefsWindowController.h; path = Source/PrefsWindowController.h; sourceTree = ""; }; - 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PrefsWindowController.m; path = Source/PrefsWindowController.m; sourceTree = ""; }; - 35A472BB0D20DEC500E6B842 /* StatusMenuIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusMenuIcon.png; path = resource/StatusMenuIcon.png; sourceTree = ""; }; - 35A473480D20E8DE00E6B842 /* ClipMenu.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ClipMenu.icns; path = resource/ClipMenu.icns; sourceTree = ""; }; - 35C028940D6838D600B95FF5 /* ActionIcon.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ActionIcon.tiff; path = resource/ActionIcon.tiff; sourceTree = ""; }; - 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ActionIconLarge.tiff; path = resource/ActionIconLarge.tiff; sourceTree = ""; }; - 35C02FFA0D6BAB8300B95FF5 /* script */ = {isa = PBXFileReference; lastKnownFileType = folder; path = script; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 8D1107320486CEB800E47090 /* ClipMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClipMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A809DF6D0EAD9A3400745313 /* GTMLoginItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMLoginItems.h; path = "../../Vendor/google-toolbox-for-mac/AppKit/GTMLoginItems.h"; sourceTree = SOURCE_ROOT; }; - A809DF6E0EAD9A3400745313 /* GTMLoginItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMLoginItems.m; path = "../../Vendor/google-toolbox-for-mac/AppKit/GTMLoginItems.m"; sourceTree = SOURCE_ROOT; }; - A82B8A460EC3DD0A00096102 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Preferences.strings; sourceTree = ""; }; - A82B8AEB0EC3F8D700096102 /* ClipMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClipMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A842D3230EA97DA200DCB303 /* constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constants.h; path = Source/constants.h; sourceTree = ""; }; - A843AB1B0EBDAA4D005A723A /* StatusMenuIcon_pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusMenuIcon_pressed.png; path = resource/StatusMenuIcon_pressed.png; sourceTree = ""; }; - A849BC5B0EE267C8009DF9D1 /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Japanese; path = Japanese.lproj/Preferences.xib; sourceTree = ""; }; - A878AA450EC411C400112A8E /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/Localizable.strings; sourceTree = ""; }; - A878AA8C0EC413B700112A8E /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Japanese; path = Japanese.lproj/Preferences.strings; sourceTree = ""; }; - A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = Snippets.xcdatamodel; sourceTree = ""; }; - A89465E90EB97B92004ACD23 /* SnippetsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SnippetsController.h; path = Source/SnippetsController.h; sourceTree = ""; }; - A89465EA0EB97B92004ACD23 /* SnippetsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SnippetsController.m; path = Source/SnippetsController.m; sourceTree = ""; }; - A894663C0EB98949004ACD23 /* ComposingPreferences.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ComposingPreferences.tiff; path = resource/ComposingPreferences.tiff; sourceTree = ""; }; - A894668F0EB98C62004ACD23 /* SnippetPrefsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SnippetPrefsController.h; path = Source/SnippetPrefsController.h; sourceTree = ""; }; - A89466900EB98C62004ACD23 /* SnippetPrefsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SnippetPrefsController.m; path = Source/SnippetPrefsController.m; sourceTree = ""; }; - A894673C0EB999B5004ACD23 /* IndexedArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IndexedArrayController.h; path = Source/IndexedArrayController.h; sourceTree = ""; }; - A894673D0EB999B5004ACD23 /* IndexedArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IndexedArrayController.m; path = Source/IndexedArrayController.m; sourceTree = ""; }; - A89716F30EA877CD005EE8E8 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = ""; }; - A89716F70EA8780B005EE8E8 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/Preferences.xib; sourceTree = ""; }; - A8A2D1D10EC16B61007DE280 /* ShortcutRecorder.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ShortcutRecorder.framework; path = /Library/Frameworks/ShortcutRecorder.framework; sourceTree = ""; }; - A8A2D26E0EC1735C007DE280 /* PTHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTHotKey.h; sourceTree = ""; }; - A8A2D26F0EC1735C007DE280 /* PTHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTHotKey.m; sourceTree = ""; }; - A8A2D2700EC1735C007DE280 /* PTHotKeyCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTHotKeyCenter.h; sourceTree = ""; }; - A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTHotKeyCenter.m; sourceTree = ""; }; - A8A2D2720EC1735C007DE280 /* PTKeyCodeTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTKeyCodeTranslator.h; sourceTree = ""; }; - A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTKeyCodeTranslator.m; sourceTree = ""; }; - A8A2D2740EC1735C007DE280 /* PTKeyCombo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTKeyCombo.h; sourceTree = ""; }; - A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PTKeyCombo.m; sourceTree = ""; }; - A8DF42840ED13BF000506877 /* Action.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = Action.tiff; path = resource/Action.tiff; sourceTree = ""; }; - A8DF42B00ED13E9100506877 /* ActionPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ActionPopUpButton.h; path = Source/ActionPopUpButton.h; sourceTree = ""; }; - A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ActionPopUpButton.m; path = Source/ActionPopUpButton.m; sourceTree = ""; }; - A8F30E4D100041BC006F3F9A /* BaseNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseNode.h; sourceTree = ""; }; - A8F30E4E100041BC006F3F9A /* BaseNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseNode.m; sourceTree = ""; }; - A8F30E4F100041BC006F3F9A /* ImageAndTextCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ImageAndTextCell.h; path = Source/ImageAndTextCell.h; sourceTree = ""; }; - A8F30E50100041BC006F3F9A /* ImageAndTextCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ImageAndTextCell.m; path = Source/ImageAndTextCell.m; sourceTree = ""; }; - A8F30E7D1000429E006F3F9A /* NSArray_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSArray_Extensions.h; path = Source/CocoaExtensions/NSArray_Extensions.h; sourceTree = SOURCE_ROOT; }; - A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSArray_Extensions.m; path = Source/CocoaExtensions/NSArray_Extensions.m; sourceTree = SOURCE_ROOT; }; - A8F30E7F1000429E006F3F9A /* NSTreeController_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSTreeController_Extensions.m; path = Source/CocoaExtensions/NSTreeController_Extensions.m; sourceTree = SOURCE_ROOT; }; - A8F30E801000429E006F3F9A /* NSTreeController_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSTreeController_Extensions.h; path = Source/CocoaExtensions/NSTreeController_Extensions.h; sourceTree = SOURCE_ROOT; }; - A8F628D20EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSIndexPath+NaoAdditions.h"; sourceTree = ""; }; - A8F628D30EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSIndexPath+NaoAdditions.m"; sourceTree = ""; }; - A8FD5ABB0EAC1ED100ACD334 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = "../../Vendor/google-toolbox-for-mac/GTMDefines.h"; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 8D11072E0486CEB800E47090 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, - 3518CE070D07966B00158053 /* Carbon.framework in Frameworks */, - 35939D670D42D38F006504B3 /* WebKit.framework in Frameworks */, - A8A2D1D20EC16B61007DE280 /* ShortcutRecorder.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AE10EC3F8D700096102 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A82B8AE20EC3F8D700096102 /* Cocoa.framework in Frameworks */, - A82B8AE30EC3F8D700096102 /* Carbon.framework in Frameworks */, - A82B8AE40EC3F8D700096102 /* WebKit.framework in Frameworks */, - A82B8AE50EC3F8D700096102 /* ShortcutRecorder.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 356F060C0D012C68003689C0 /* AppController.h */, - 356F060D0D012C68003689C0 /* AppController.m */, - A842D3230EA97DA200DCB303 /* constants.h */, - 3542A9290D5EC6C300B3BBBD /* CMUtilities.h */, - 3542A92A0D5EC6C300B3BBBD /* CMUtilities.m */, - 3518CA970D07646B00158053 /* MenuController.h */, - 3518CA980D07646C00158053 /* MenuController.m */, - A89465E90EB97B92004ACD23 /* SnippetsController.h */, - A89465EA0EB97B92004ACD23 /* SnippetsController.m */, - 3505FF140D7FAD8C00B55D03 /* Preferences */, - 3505FF150D7FADC400B55D03 /* Action */, - 3505FF180D7FAE0000B55D03 /* Clip */, - 3542A8820D5EBE6000B3BBBD /* CocoaExtensions */, - A8A2D26D0EC1735C007DE280 /* PTHotKeys */, - ); - name = Classes; - sourceTree = ""; - }; - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { - isa = PBXGroup; - children = ( - 35939D660D42D38F006504B3 /* WebKit.framework */, - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, - 3518CE060D07966B00158053 /* Carbon.framework */, - ); - name = "Linked Frameworks"; - sourceTree = ""; - }; - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 29B97324FDCFA39411CA2CEA /* AppKit.framework */, - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, - 29B97325FDCFA39411CA2CEA /* Foundation.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 8D1107320486CEB800E47090 /* ClipMenu.app */, - A82B8AEB0EC3F8D700096102 /* ClipMenu.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* ClipMenu */ = { - isa = PBXGroup; - children = ( - A89465DB0EB97A3D004ACD23 /* Models */, - 080E96DDFE201D6D7F000001 /* Classes */, - 3542A8620D5EBE0400B3BBBD /* NaoAdditions */, - 35A42CAF0D7D09D0005FFB4C /* DBPrefsWindowController */, - A8FD5AB90EAC1EBB00ACD334 /* GTM */, - 29B97315FDCFA39411CA2CEA /* Other Source */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = ClipMenu; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Source */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* ClipMenu_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Source"; - path = Source; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - A843AB080EBDAA03005A723A /* icons */, - 35C02FFA0D6BAB8300B95FF5 /* script */, - 8D1107310486CEB800E47090 /* Info.plist */, - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, - A878AA420EC411BE00112A8E /* Localizable.strings */, - A878AA890EC413B000112A8E /* Preferences.strings */, - A89716F20EA877CD005EE8E8 /* MainMenu.xib */, - A849BC580EE267C0009DF9D1 /* Preferences.xib */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - A8A2D1D10EC16B61007DE280 /* ShortcutRecorder.framework */, - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = ""; - }; - 3505FF140D7FAD8C00B55D03 /* Preferences */ = { - isa = PBXGroup; - children = ( - 35A42CC20D7D0ABA005FFB4C /* PrefsWindowController.h */, - 35A42CC30D7D0ABA005FFB4C /* PrefsWindowController.m */, - 3551F2BD0D75224900069069 /* ActionTypeTransformer.h */, - 3551F2BE0D75224900069069 /* ActionTypeTransformer.m */, - A894668F0EB98C62004ACD23 /* SnippetPrefsController.h */, - A89466900EB98C62004ACD23 /* SnippetPrefsController.m */, - A894673C0EB999B5004ACD23 /* IndexedArrayController.h */, - A894673D0EB999B5004ACD23 /* IndexedArrayController.m */, - A8DF42B00ED13E9100506877 /* ActionPopUpButton.h */, - A8DF42B10ED13E9100506877 /* ActionPopUpButton.m */, - A8F30E4F100041BC006F3F9A /* ImageAndTextCell.h */, - A8F30E50100041BC006F3F9A /* ImageAndTextCell.m */, - ); - name = Preferences; - sourceTree = ""; - }; - 3505FF150D7FADC400B55D03 /* Action */ = { - isa = PBXGroup; - children = ( - 35939DA90D42D4FE006504B3 /* ActionController.h */, - 35939DAA0D42D4FE006504B3 /* ActionController.m */, - 3542A8C90D5EC15000B3BBBD /* ActionNodeController.h */, - 3542A8CA0D5EC15000B3BBBD /* ActionNodeController.m */, - 3505FF1E0D7FAF1F00B55D03 /* ActionNodeFactory.h */, - 3505FF1F0D7FAF1F00B55D03 /* ActionNodeFactory.m */, - 3542AD6D0D62828000B3BBBD /* ActionNode.h */, - 3542AD6E0D62828000B3BBBD /* ActionNode.m */, - A8F30E4D100041BC006F3F9A /* BaseNode.h */, - A8F30E4E100041BC006F3F9A /* BaseNode.m */, - 3505FF1B0D7FAE8300B55D03 /* ActionFactory.h */, - 3505FF1C0D7FAE8300B55D03 /* ActionFactory.m */, - 3505FF710D7FB14A00B55D03 /* BuiltInActionController.h */, - 3505FF720D7FB14A00B55D03 /* BuiltInActionController.m */, - 3551F3700D7658EF00069069 /* JavaScriptSupport.h */, - 3551F3710D7658EF00069069 /* JavaScriptSupport.m */, - ); - name = Action; - path = Source; - sourceTree = ""; - }; - 3505FF180D7FAE0000B55D03 /* Clip */ = { - isa = PBXGroup; - children = ( - 356F073D0D024327003689C0 /* ClipsController.h */, - 356F073E0D024327003689C0 /* ClipsController.m */, - 3593F1830D025D5500B95536 /* Clip.h */, - 3593F1840D025D5500B95536 /* Clip.m */, - ); - name = Clip; - path = Source; - sourceTree = ""; - }; - 3542A8620D5EBE0400B3BBBD /* NaoAdditions */ = { - isa = PBXGroup; - children = ( - 3542A8AD0D5EBF3800B3BBBD /* NSString+NaoAdditions.h */, - 3542A8AE0D5EBF3800B3BBBD /* NSString+NaoAdditions.m */, - 3542A8650D5EBE0400B3BBBD /* NSTreeController+NaoAdditions.h */, - A8F628D20EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.h */, - A8F628D30EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m */, - ); - name = NaoAdditions; - path = ../../Library/NaoAdditions; - sourceTree = SOURCE_ROOT; - }; - 3542A8820D5EBE6000B3BBBD /* CocoaExtensions */ = { - isa = PBXGroup; - children = ( - A8F30E7D1000429E006F3F9A /* NSArray_Extensions.h */, - A8F30E7E1000429E006F3F9A /* NSArray_Extensions.m */, - A8F30E7F1000429E006F3F9A /* NSTreeController_Extensions.m */, - A8F30E801000429E006F3F9A /* NSTreeController_Extensions.h */, - ); - name = CocoaExtensions; - path = ../../Library/CocoaExtensions; - sourceTree = SOURCE_ROOT; - }; - 35A42CAF0D7D09D0005FFB4C /* DBPrefsWindowController */ = { - isa = PBXGroup; - children = ( - 35A42CBE0D7D0A6F005FFB4C /* DBPrefsWindowController.h */, - 35A42CBF0D7D0A6F005FFB4C /* DBPrefsWindowController.m */, - ); - name = DBPrefsWindowController; - sourceTree = ""; - }; - A843AB080EBDAA03005A723A /* icons */ = { - isa = PBXGroup; - children = ( - 35A473480D20E8DE00E6B842 /* ClipMenu.icns */, - 35A472BB0D20DEC500E6B842 /* StatusMenuIcon.png */, - A843AB1B0EBDAA4D005A723A /* StatusMenuIcon_pressed.png */, - 35C028940D6838D600B95FF5 /* ActionIcon.tiff */, - 35C028DB0D683C0200B95FF5 /* ActionIconLarge.tiff */, - A894663C0EB98949004ACD23 /* ComposingPreferences.tiff */, - 3578F76F0D7E3D5E00E804BF /* Menu.png */, - A8DF42840ED13BF000506877 /* Action.tiff */, - ); - name = icons; - sourceTree = ""; - }; - A89465DB0EB97A3D004ACD23 /* Models */ = { - isa = PBXGroup; - children = ( - A89465E50EB97A62004ACD23 /* Snippets.xcdatamodel */, - ); - name = Models; - sourceTree = ""; - }; - A8A2D26D0EC1735C007DE280 /* PTHotKeys */ = { - isa = PBXGroup; - children = ( - A8A2D26E0EC1735C007DE280 /* PTHotKey.h */, - A8A2D26F0EC1735C007DE280 /* PTHotKey.m */, - A8A2D2700EC1735C007DE280 /* PTHotKeyCenter.h */, - A8A2D2710EC1735C007DE280 /* PTHotKeyCenter.m */, - A8A2D2720EC1735C007DE280 /* PTKeyCodeTranslator.h */, - A8A2D2730EC1735C007DE280 /* PTKeyCodeTranslator.m */, - A8A2D2740EC1735C007DE280 /* PTKeyCombo.h */, - A8A2D2750EC1735C007DE280 /* PTKeyCombo.m */, - ); - name = PTHotKeys; - path = Source/PTHotKeys; - sourceTree = ""; - }; - A8FD5AB90EAC1EBB00ACD334 /* GTM */ = { - isa = PBXGroup; - children = ( - A8FD5ABB0EAC1ED100ACD334 /* GTMDefines.h */, - A809DF6D0EAD9A3400745313 /* GTMLoginItems.h */, - A809DF6E0EAD9A3400745313 /* GTMLoginItems.m */, - ); - name = GTM; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 8D1107260486CEB800E47090 /* ClipMenu */ = { - isa = PBXNativeTarget; - buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ClipMenu" */; - buildPhases = ( - 8D1107290486CEB800E47090 /* Resources */, - 8D11072C0486CEB800E47090 /* Sources */, - 8D11072E0486CEB800E47090 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ClipMenu; - productInstallPath = "$(HOME)/Applications"; - productName = ClipMenu; - productReference = 8D1107320486CEB800E47090 /* ClipMenu.app */; - productType = "com.apple.product-type.application"; - }; - A82B8AB20EC3F8D700096102 /* ClipMenu (deployment) */ = { - isa = PBXNativeTarget; - buildConfigurationList = A82B8AE80EC3F8D700096102 /* Build configuration list for PBXNativeTarget "ClipMenu (deployment)" */; - buildPhases = ( - A82B8AB30EC3F8D700096102 /* ShellScript */, - A82B8AB40EC3F8D700096102 /* Resources */, - A82B8AC20EC3F8D700096102 /* Sources */, - A82B8AE10EC3F8D700096102 /* Frameworks */, - A82B8AE60EC3F8D700096102 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "ClipMenu (deployment)"; - productInstallPath = "$(HOME)/Applications"; - productName = ClipMenu; - productReference = A82B8AEB0EC3F8D700096102 /* ClipMenu.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ClipMenu" */; - compatibilityVersion = "Xcode 3.1"; - hasScannedForEncodings = 1; - mainGroup = 29B97314FDCFA39411CA2CEA /* ClipMenu */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 8D1107260486CEB800E47090 /* ClipMenu */, - A82B8AB20EC3F8D700096102 /* ClipMenu (deployment) */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 8D1107290486CEB800E47090 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, - A878AA430EC411BE00112A8E /* Localizable.strings in Resources */, - A878AA8A0EC413B000112A8E /* Preferences.strings in Resources */, - 35A472BC0D20DEC500E6B842 /* StatusMenuIcon.png in Resources */, - 35A473490D20E8DE00E6B842 /* ClipMenu.icns in Resources */, - 35C028950D6838D600B95FF5 /* ActionIcon.tiff in Resources */, - 35C028DC0D683C0200B95FF5 /* ActionIconLarge.tiff in Resources */, - 35C02FFE0D6BAB8300B95FF5 /* script in Resources */, - 3578F7700D7E3D5E00E804BF /* Menu.png in Resources */, - A89716F40EA877CD005EE8E8 /* MainMenu.xib in Resources */, - A849BC590EE267C0009DF9D1 /* Preferences.xib in Resources */, - A894663D0EB98949004ACD23 /* ComposingPreferences.tiff in Resources */, - A843AB1C0EBDAA4D005A723A /* StatusMenuIcon_pressed.png in Resources */, - A8DF42850ED13BF000506877 /* Action.tiff in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AB40EC3F8D700096102 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A82B8AB50EC3F8D700096102 /* InfoPlist.strings in Resources */, - A878AA440EC411BE00112A8E /* Localizable.strings in Resources */, - A878AA8B0EC413B000112A8E /* Preferences.strings in Resources */, - A82B8AB60EC3F8D700096102 /* StatusMenuIcon.png in Resources */, - A82B8AB70EC3F8D700096102 /* ClipMenu.icns in Resources */, - A82B8AB90EC3F8D700096102 /* ActionIcon.tiff in Resources */, - A82B8ABA0EC3F8D700096102 /* ActionIconLarge.tiff in Resources */, - A82B8ABB0EC3F8D700096102 /* script in Resources */, - A82B8ABC0EC3F8D700096102 /* Menu.png in Resources */, - A86F93910ED183C30058E899 /* Action.tiff in Resources */, - A82B8ABD0EC3F8D700096102 /* MainMenu.xib in Resources */, - A849BC5A0EE267C0009DF9D1 /* Preferences.xib in Resources */, - A82B8ABF0EC3F8D700096102 /* ComposingPreferences.tiff in Resources */, - A82B8AC00EC3F8D700096102 /* StatusMenuIcon_pressed.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - A82B8AB30EC3F8D700096102 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - comments = "日本語ローカライズを生成"; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "genstrings -o English.lproj Source/*.m \nibtool --generate-strings-file English.lproj/Preferences.strings English.lproj/Preferences.xib\nrm Japanese.lproj/Preferences.xib\nibtool --strings-file Japanese.lproj/Preferences.strings --write Japanese.lproj/Preferences.xib English.lproj/Preferences.xib"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8D11072C0486CEB800E47090 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072D0486CEB800E47090 /* main.m in Sources */, - 356F060E0D012C68003689C0 /* AppController.m in Sources */, - 356F073F0D024327003689C0 /* ClipsController.m in Sources */, - 3593F1850D025D5500B95536 /* Clip.m in Sources */, - 3518CA990D07646C00158053 /* MenuController.m in Sources */, - 35939DAB0D42D4FE006504B3 /* ActionController.m in Sources */, - 3542A8AF0D5EBF3800B3BBBD /* NSString+NaoAdditions.m in Sources */, - 3542A8CB0D5EC15000B3BBBD /* ActionNodeController.m in Sources */, - 3542A92B0D5EC6C300B3BBBD /* CMUtilities.m in Sources */, - 3542AD6F0D62828000B3BBBD /* ActionNode.m in Sources */, - 3551F2BF0D75224900069069 /* ActionTypeTransformer.m in Sources */, - 3551F3720D7658EF00069069 /* JavaScriptSupport.m in Sources */, - 35A42CC00D7D0A6F005FFB4C /* DBPrefsWindowController.m in Sources */, - 35A42CC40D7D0ABA005FFB4C /* PrefsWindowController.m in Sources */, - 3505FF1D0D7FAE8300B55D03 /* ActionFactory.m in Sources */, - 3505FF200D7FAF1F00B55D03 /* ActionNodeFactory.m in Sources */, - 3505FF730D7FB14A00B55D03 /* BuiltInActionController.m in Sources */, - A8F628D40EAB12EB006DDEAF /* NSIndexPath+NaoAdditions.m in Sources */, - A809DF6F0EAD9A3400745313 /* GTMLoginItems.m in Sources */, - A89465E60EB97A62004ACD23 /* Snippets.xcdatamodel in Sources */, - A89465EB0EB97B92004ACD23 /* SnippetsController.m in Sources */, - A89466910EB98C62004ACD23 /* SnippetPrefsController.m in Sources */, - A894673E0EB999B5004ACD23 /* IndexedArrayController.m in Sources */, - A8A2D2760EC1735C007DE280 /* PTHotKey.m in Sources */, - A8A2D2770EC1735C007DE280 /* PTHotKeyCenter.m in Sources */, - A8A2D2780EC1735C007DE280 /* PTKeyCodeTranslator.m in Sources */, - A8A2D2790EC1735C007DE280 /* PTKeyCombo.m in Sources */, - A8DF42B20ED13E9100506877 /* ActionPopUpButton.m in Sources */, - A8F30E53100041BC006F3F9A /* BaseNode.m in Sources */, - A8F30E54100041BC006F3F9A /* ImageAndTextCell.m in Sources */, - A8F30E811000429E006F3F9A /* NSArray_Extensions.m in Sources */, - A8F30E821000429E006F3F9A /* NSTreeController_Extensions.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A82B8AC20EC3F8D700096102 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A86F939A0ED183FC0058E899 /* ActionPopUpButton.m in Sources */, - A82B8AC30EC3F8D700096102 /* main.m in Sources */, - A82B8AC40EC3F8D700096102 /* AppController.m in Sources */, - A82B8AC50EC3F8D700096102 /* ClipsController.m in Sources */, - A82B8AC60EC3F8D700096102 /* Clip.m in Sources */, - A82B8AC70EC3F8D700096102 /* MenuController.m in Sources */, - A82B8AC80EC3F8D700096102 /* ActionController.m in Sources */, - A82B8ACB0EC3F8D700096102 /* NSString+NaoAdditions.m in Sources */, - A82B8ACC0EC3F8D700096102 /* ActionNodeController.m in Sources */, - A82B8ACD0EC3F8D700096102 /* CMUtilities.m in Sources */, - A82B8ACE0EC3F8D700096102 /* ActionNode.m in Sources */, - A82B8AD00EC3F8D700096102 /* ActionTypeTransformer.m in Sources */, - A82B8AD10EC3F8D700096102 /* JavaScriptSupport.m in Sources */, - A82B8AD20EC3F8D700096102 /* DBPrefsWindowController.m in Sources */, - A82B8AD30EC3F8D700096102 /* PrefsWindowController.m in Sources */, - A82B8AD40EC3F8D700096102 /* ActionFactory.m in Sources */, - A82B8AD50EC3F8D700096102 /* ActionNodeFactory.m in Sources */, - A82B8AD60EC3F8D700096102 /* BuiltInActionController.m in Sources */, - A82B8AD70EC3F8D700096102 /* NSIndexPath+NaoAdditions.m in Sources */, - A82B8AD80EC3F8D700096102 /* GTMLoginItems.m in Sources */, - A82B8AD90EC3F8D700096102 /* Snippets.xcdatamodel in Sources */, - A82B8ADA0EC3F8D700096102 /* SnippetsController.m in Sources */, - A82B8ADB0EC3F8D700096102 /* SnippetPrefsController.m in Sources */, - A82B8ADC0EC3F8D700096102 /* IndexedArrayController.m in Sources */, - A82B8ADD0EC3F8D700096102 /* PTHotKey.m in Sources */, - A82B8ADE0EC3F8D700096102 /* PTHotKeyCenter.m in Sources */, - A82B8ADF0EC3F8D700096102 /* PTKeyCodeTranslator.m in Sources */, - A82B8AE00EC3F8D700096102 /* PTKeyCombo.m in Sources */, - A8F30E56100041BC006F3F9A /* BaseNode.m in Sources */, - A8F30E57100041BC006F3F9A /* ImageAndTextCell.m in Sources */, - A8F30E831000429E006F3F9A /* NSArray_Extensions.m in Sources */, - A8F30E841000429E006F3F9A /* NSTreeController_Extensions.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 089C165DFE840E0CC02AAC07 /* English */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - A849BC580EE267C0009DF9D1 /* Preferences.xib */ = { - isa = PBXVariantGroup; - children = ( - A89716F70EA8780B005EE8E8 /* English */, - A849BC5B0EE267C8009DF9D1 /* Japanese */, - ); - name = Preferences.xib; - sourceTree = ""; - }; - A878AA420EC411BE00112A8E /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 3578645D0D23A82400FAFFC5 /* English */, - A878AA450EC411C400112A8E /* Japanese */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - A878AA890EC413B000112A8E /* Preferences.strings */ = { - isa = PBXVariantGroup; - children = ( - A82B8A460EC3DD0A00096102 /* English */, - A878AA8C0EC413B700112A8E /* Japanese */, - ); - name = Preferences.strings; - sourceTree = ""; - }; - A89716F20EA877CD005EE8E8 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - A89716F30EA877CD005EE8E8 /* English */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - A82B8AE90EC3F8D700096102 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = ClipMenu; - SDKROOT = macosx10.5; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; - }; - name = Debug; - }; - A82B8AEA0EC3F8D700096102 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = ClipMenu; - SDKROOT = macosx10.5; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4B08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = ClipMenu; - SDKROOT = macosx10.5; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; - }; - name = Debug; - }; - C01FCF4C08A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = ClipMenu; - SDKROOT = macosx10.5; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - A82B8AE80EC3F8D700096102 /* Build configuration list for PBXNativeTarget "ClipMenu (deployment)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A82B8AE90EC3F8D700096102 /* Debug */, - A82B8AEA0EC3F8D700096102 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ClipMenu" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4B08A954540054247B /* Debug */, - C01FCF4C08A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ClipMenu" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/ClipMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ClipMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ClipMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ClipMenu.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ClipMenu.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..080da46 --- /dev/null +++ b/ClipMenu.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "69c39523ac0471922b625cc56b8722155cfd2afd660bdd4f5ff67335b5b87714", + "pins" : [ + { + "identity" : "keyboardshortcuts", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sindresorhus/KeyboardShortcuts", + "state" : { + "revision" : "1aef85578fdd4f9eaeeb8d53b7b4fc31bf08fe27", + "version" : "2.4.0" + } + } + ], + "version" : 3 +} diff --git a/ClipMenu_Prefix.pch b/ClipMenu_Prefix.pch deleted file mode 100644 index 3890127..0000000 --- a/ClipMenu_Prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -// -// Prefix header for all source files of the 'ClipMenu' target in the 'ClipMenu' project -// - -#ifdef __OBJC__ - #import -#endif diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings deleted file mode 100644 index 0c7c2f6..0000000 Binary files a/English.lproj/InfoPlist.strings and /dev/null differ diff --git a/English.lproj/Localizable.strings b/English.lproj/Localizable.strings deleted file mode 100644 index 1bd2a5e..0000000 Binary files a/English.lproj/Localizable.strings and /dev/null differ diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib deleted file mode 100644 index f5b971d..0000000 --- a/English.lproj/MainMenu.xib +++ /dev/null @@ -1,1803 +0,0 @@ - - - - 1050 - 10B504 - 740 - 1038.2 - 437.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 740 - - - YES - - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - YES - - YES - - - YES - - - - YES - - - NSApplication - - - - FirstResponder - - - NSApplication - - - MainMenu - - YES - - - ClipMenu - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - submenuAction: - - ClipMenu - - YES - - - About ClipMenu - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Preferences… - , - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Services - - 1048576 - 2147483647 - - - submenuAction: - - - Services - - - YES - - _NSServicesMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Hide ClipMenu - h - 1048576 - 2147483647 - - - - - - Hide Others - h - 1572864 - 2147483647 - - - - - - Show All - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Quit ClipMenu - - 1048576 - 2147483647 - - - - - _NSAppleMenu - - - - - File - - 1048576 - 2147483647 - - - submenuAction: - - - File - - - YES - - - New - n - 1048576 - 2147483647 - - - - - - Open... - o - 1048576 - 2147483647 - - - - - - Open Recent - - 1048576 - 2147483647 - - - submenuAction: - - - Open Recent - - - YES - - - Clear Menu - - 1048576 - 2147483647 - - - - - _NSRecentDocumentsMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Close - w - 1048576 - 2147483647 - - - - - - Save - s - 1048576 - 2147483647 - - - - - - Save As… - S - 1048576 - 2147483647 - - - - - - Revert - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Page Setup… - P - 1048576 - 2147483647 - - - - - - Print… - p - 1048576 - 2147483647 - - - - - - - - - Edit - - 1048576 - 2147483647 - - - submenuAction: - - - Edit - - - YES - - - Undo - z - 1048576 - 2147483647 - - - - - - Redo - Z - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Cut - x - 1048576 - 2147483647 - - - - - - Copy - c - 1048576 - 2147483647 - - - - - - Paste - v - 1048576 - 2147483647 - - - - - - Delete - - 1048576 - 2147483647 - - - - - - Select All - a - 1048576 - 2147483647 - - - - - - - - - Help - - 1048576 - 2147483647 - - - submenuAction: - - Help - - YES - - - ClipMenu Help - ? - 1048576 - 2147483647 - - - - - - - - _NSMainMenu - - - AppController - - - - - YES - - - print: - - - - 86 - - - - runPageLayout: - - - - 87 - - - - showHelp: - - - - 122 - - - - clearRecentDocuments: - - - - 127 - - - - terminate: - - - - 139 - - - - orderFrontStandardAboutPanel: - - - - 142 - - - - hideOtherApplications: - - - - 146 - - - - hide: - - - - 152 - - - - unhideAllApplications: - - - - 153 - - - - cut: - - - - 175 - - - - paste: - - - - 176 - - - - redo: - - - - 178 - - - - selectAll: - - - - 179 - - - - undo: - - - - 180 - - - - copy: - - - - 181 - - - - performClose: - - - - 193 - - - - delete: - - - - 195 - - - - delegate - - - - 207 - - - - showPreferencePanel: - - - - 211 - - - - - YES - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - 29 - - - YES - - - - - - - MainMenu - - - 56 - - - YES - - - - - - 57 - - - YES - - - - - - - - - - - - - - - - 58 - - - - - 129 - - - - - 131 - - - YES - - - - - - 130 - - - - - 134 - - - - - 136 - - - - - 143 - - - - - 144 - - - - - 145 - - - - - 149 - - - - - 150 - - - - - 196 - - - - - 83 - - - YES - - - - - - 81 - - - YES - - - - - - - - - - - - - - - - 72 - - - - - 73 - - - - - 74 - - - - - 75 - - - - - 77 - - - - - 78 - - - - - 79 - - - - - 80 - - - - - 82 - - - - - 112 - - - - - 124 - - - YES - - - - - - 125 - - - YES - - - - - - 126 - - - - - 103 - - - YES - - - - - - 106 - - - YES - - - - - - 111 - - - - - 163 - - - YES - - - - - - 169 - - - YES - - - - - - - - - - - - - 156 - - - - - 157 - - - - - 158 - - - - - 160 - - - - - 164 - - - - - 171 - - - - - 172 - - - - - 173 - - - - - 206 - - - AppController - - - -3 - - - Application - - - - - YES - - YES - -3.IBPluginDependency - 103.IBPluginDependency - 103.ImportedFromIB2 - 106.IBEditorWindowLastContentRect - 106.IBPluginDependency - 106.ImportedFromIB2 - 111.IBPluginDependency - 111.ImportedFromIB2 - 112.IBPluginDependency - 112.ImportedFromIB2 - 124.IBPluginDependency - 124.ImportedFromIB2 - 125.IBPluginDependency - 125.ImportedFromIB2 - 126.IBPluginDependency - 126.ImportedFromIB2 - 129.IBPluginDependency - 129.ImportedFromIB2 - 130.IBPluginDependency - 130.ImportedFromIB2 - 131.IBPluginDependency - 131.ImportedFromIB2 - 134.IBPluginDependency - 134.ImportedFromIB2 - 136.IBPluginDependency - 136.ImportedFromIB2 - 143.IBPluginDependency - 143.ImportedFromIB2 - 144.IBPluginDependency - 144.ImportedFromIB2 - 145.IBPluginDependency - 145.ImportedFromIB2 - 149.IBPluginDependency - 149.ImportedFromIB2 - 150.IBPluginDependency - 150.ImportedFromIB2 - 156.IBPluginDependency - 156.ImportedFromIB2 - 157.IBPluginDependency - 157.ImportedFromIB2 - 158.IBPluginDependency - 158.ImportedFromIB2 - 160.IBPluginDependency - 160.ImportedFromIB2 - 163.IBPluginDependency - 163.ImportedFromIB2 - 164.IBPluginDependency - 164.ImportedFromIB2 - 169.IBEditorWindowLastContentRect - 169.IBPluginDependency - 169.ImportedFromIB2 - 171.IBPluginDependency - 171.ImportedFromIB2 - 172.IBPluginDependency - 172.ImportedFromIB2 - 173.IBPluginDependency - 173.ImportedFromIB2 - 196.IBPluginDependency - 196.ImportedFromIB2 - 206.ImportedFromIB2 - 29.IBEditorWindowLastContentRect - 29.IBPluginDependency - 29.ImportedFromIB2 - 56.IBPluginDependency - 56.ImportedFromIB2 - 57.IBEditorWindowLastContentRect - 57.IBPluginDependency - 57.ImportedFromIB2 - 58.IBPluginDependency - 58.ImportedFromIB2 - 72.IBPluginDependency - 72.ImportedFromIB2 - 73.IBPluginDependency - 73.ImportedFromIB2 - 74.IBPluginDependency - 74.ImportedFromIB2 - 75.IBPluginDependency - 75.ImportedFromIB2 - 77.IBPluginDependency - 77.ImportedFromIB2 - 78.IBPluginDependency - 78.ImportedFromIB2 - 79.IBPluginDependency - 79.ImportedFromIB2 - 80.IBPluginDependency - 80.ImportedFromIB2 - 81.IBEditorWindowLastContentRect - 81.IBPluginDependency - 81.ImportedFromIB2 - 82.IBPluginDependency - 82.ImportedFromIB2 - 83.IBPluginDependency - 83.ImportedFromIB2 - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - {{184, 926}, {174, 23}} - 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 - - 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 - - {{140, 796}, {154, 153}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - {{0, 949}, {245, 20}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{12, 766}, {200, 183}} - 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 - - {{98, 746}, {183, 203}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - - - YES - - - YES - - - - - YES - - - YES - - - - 211 - - - - YES - - AppController - NSObject - - YES - - YES - popUpActionMenu: - popUpClipMenu: - popUpHistoryMenu: - popUpSnippetsMenu: - selectActionMenuItem: - selectMenuItem: - selectSnippetMenuItem: - showPreferencePanel: - - - YES - id - id - id - id - id - id - id - id - - - - IBProjectSource - Source/AppController.h - - - - AppController - NSObject - - IBUserSource - - - - - FirstResponder - NSObject - - IBUserSource - - - - - - YES - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSBrowser - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSBrowser.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSDocument - NSObject - - YES - - YES - printDocument: - revertDocumentToSaved: - runPageLayout: - saveDocument: - saveDocumentAs: - saveDocumentTo: - - - YES - id - id - id - id - id - id - - - - IBFrameworkSource - AppKit.framework/Headers/NSDocument.h - - - - NSDocument - - IBFrameworkSource - AppKit.framework/Headers/NSDocumentScripting.h - - - - NSDocumentController - NSObject - - YES - - YES - clearRecentDocuments: - newDocument: - openDocument: - saveAllDocuments: - - - YES - id - id - id - id - - - - IBFrameworkSource - AppKit.framework/Headers/NSDocumentController.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSMatrix - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSMatrix.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMovieView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMovieView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderCell.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderControl.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRValidator.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSTableView - NSControl - - - - NSText - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSText.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - - 0 - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES - ../ClipMenu.xcodeproj - 3 - - diff --git a/English.lproj/Preferences.strings b/English.lproj/Preferences.strings deleted file mode 100644 index 62c9b0d..0000000 Binary files a/English.lproj/Preferences.strings and /dev/null differ diff --git a/English.lproj/Preferences.xib b/English.lproj/Preferences.xib deleted file mode 100644 index 62dedf8..0000000 --- a/English.lproj/Preferences.xib +++ /dev/null @@ -1,10878 +0,0 @@ - - - - 1050 - 10D573 - 762 - 1038.29 - 460.00 - - 762 - 1 - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - - - - - PrefsWindowController - - - FirstResponder - - - NSApplication - - - YES - - - ActionNodeController - - - - nodeTitle - action.path - action.type - - ActionNode - YES - - YES - YES - YES - children - isLeaf - - - - nodeTitle - maxHistorySize - - ActionNode - YES - - YES - YES - YES - children - isLeaf - - - SUUpdater - - - - name - - YES - - YES - YES - YES - YES - YES - - - - 256 - - - - 268 - {{129, 12}, {200, 32}} - - YES - - 67239424 - 134217728 - Define Exclude Options... - - LucidaGrande - 13 - 1044 - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{49, 48}, {210, 17}} - - YES - - 68288064 - 272634880 - Exclude Applications - - LucidaGrande-Bold - 13 - 16 - - - - 6 - System - controlColor - - 3 - MC42NjY2NjY2NjY3AA - - - - 6 - System - controlTextColor - - 3 - MAA - - - - - - - 268 - {{248, 329}, {152, 22}} - - YES - - -2076049856 - 133120 - - LucidaGrande - 11 - 3100 - - - 109199615 - 129 - - - 400 - 75 - - - Last Used - - 1048576 - 2147483647 - 1 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - Date Created - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - - 1 - 1 - YES - YES - 2 - - - - - 268 - {{49, 333}, {197, 17}} - - YES - - 68288064 - 272630784 - Sort history order by: - - - - - - - - - 268 - {{248, 235}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - LF - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - - CR+LF - - 1048576 - 2147483647 - - - _popUpItemAction: - 2 - - - - - CR - - 1048576 - 2147483647 - - - _popUpItemAction: - 3 - - - - - Tab - - 2147483647 - - - _popUpItemAction: - 4 - - - - - Space - - 2147483647 - - - _popUpItemAction: - 5 - - - - - None - - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{60, 240}, {179, 14}} - - YES - - 68288064 - 71435264 - separator: - - - - - - - - - 268 - {{298, 203}, {105, 32}} - - YES - - 67239424 - 134217728 - Export... - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{248, 260}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - Single file - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - - Multiple files - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{49, 264}, {197, 17}} - - YES - - 68288064 - 272630784 - Export clipboard history as: - - - - - - - - - 268 - {{49, 158}, {197, 17}} - - YES - - 68288064 - 272630784 - Status Bar icon style: - - - - - - - - - 268 - {{248, 151}, {71, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 129 - - - 400 - 75 - - - - - 1048576 - 2147483647 - 1 - - NSImage - StatusMenuIcon - - - - _popUpItemAction: - 1 - - - YES - - - - - - - - - 2147483647 - - NSImage - StatusMenuIconBySuphiAksoy - - - - _popUpItemAction: - 13 - - - - - - - 1048576 - 2147483647 - - NSImage - StatusMenuIconFirst - - - - _popUpItemAction: - 2 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-bw-left - - - - _popUpItemAction: - 3 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-bw-right - - - - _popUpItemAction: - 4 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-color-left - - - - _popUpItemAction: - 5 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-color-right - - - - _popUpItemAction: - 6 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-diagonal-bw - - - - _popUpItemAction: - 7 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-diagonal-color - - - - _popUpItemAction: - 8 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-bw-left - - - - _popUpItemAction: - 9 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-bw-right - - - - _popUpItemAction: - 10 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-color-left - - - - _popUpItemAction: - 11 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-color-right - - - - _popUpItemAction: - 12 - - - - - None - - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{49, 457}, {210, 17}} - - YES - - 68288064 - 272634880 - Behavior - - - - - - - - - 256 - {{49, 358}, {253, 17}} - - YES - - 67239424 - 272629760 - Max clipboard history size: - - - - - - - - - 256 - {{312, 356}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - 0 - 1 - NO - YES - 1 - AQAAAAAAAAAAAAAAAAAAAA - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - 0 - 0 - YES - NO - 1 - AAAAAAAAAAAAAAAAAAAAAA - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - textColor - - - - - - - 268 - {{361, 356}, {39, 14}} - - YES - - 68288064 - 272761856 - items - - - - - - - - - 268 - {{321, 77}, {38, 17}} - - YES - - 68288064 - 71308288 - - - LucidaGrande - 13 - 16 - - - - - - - - - - - -∞ - - - +∞ - - #,##0.### - #,##0.### - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - YES - NO - YES - - - - - - - - - 268 - {{248, 306}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - Every 30 minutes - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1800 - - - YES - - OtherViews - - - - Every minute - - 1048576 - 2147483647 - - - _popUpItemAction: - 60 - - - - - Every 5 minutes - - 1048576 - 2147483647 - - - _popUpItemAction: - 300 - - - - - Every 10 minutes - - 1048576 - 2147483647 - - - _popUpItemAction: - 600 - - - - - - Every hour - - 1048576 - 2147483647 - - - _popUpItemAction: - 3600 - - - - - Every 3 hours - - 1048576 - 2147483647 - - - _popUpItemAction: - 10800 - - - - - Every 6 hours - - 1048576 - 2147483647 - - - _popUpItemAction: - 21600 - - - - - Every 12 hours - - 1048576 - 2147483647 - - - _popUpItemAction: - 43200 - - - - - Every day - - 1048576 - 2147483647 - - - _popUpItemAction: - 86400 - - - - - Never - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - 3 - 1 - YES - YES - 2 - - - - - 268 - {{49, 311}, {197, 17}} - - YES - - 68288064 - 272630784 - Autosaving clipboard history: - - - - - - - - - 268 - {{49, 129}, {210, 17}} - - YES - - 68288064 - 272634880 - Time interval - - - - - - - - - 268 - {{49, 183}, {210, 17}} - - YES - - 68288064 - 272634880 - Appearance - - - - - - - - - 268 - {{49, 386}, {210, 17}} - - YES - - 68288064 - 272634880 - Clipboard History - - - - - - - - - 256 - {{49, 104}, {361, 17}} - - YES - - 67239424 - 272629760 - Time interval to observe the clipboard: - - - - - - - - - 256 - {{52, 76}, {264, 18}} - - YES - - 67239424 - 131072 - - - - - Helvetica - 12 - 16 - - - 1 - 0.0 - 1 - 0.0 - 5 - 1 - YES - NO - - - - - 256 - {{361, 77}, {28, 14}} - - YES - - 67239424 - 272629760 - sec. - - - - - - - - - 256 - {{50, 413}, {359, 18}} - - YES - - 67239424 - 0 - Input "⌘ + V" after menu item selection - - - 1211912703 - 2 - - NSImage - NSSwitch - - - NSSwitch - - - - 200 - 25 - - - - - 268 - {{50, 433}, {297, 18}} - - YES - - 67239424 - 0 - Launch on Login - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 287}, {359, 18}} - - YES - - 67239424 - 0 - Save clipboard history on quit - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {460, 494} - - - NSView - - NSResponder - - - - 256 - - - - 268 - {{47, 20}, {150, 17}} - - YES - - 68288064 - 272630784 - Snippets' position: - - - - - - - - - 268 - {{203, 16}, {207, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - Above the clipboard history - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - OtherViews - - - - None - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - Below the clipboard history - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 1 - 1 - YES - YES - 2 - - - - - 256 - {{50, 231}, {359, 18}} - - YES - - 67239424 - 0 - Add a menu item to clear clipboard history - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{63, 211}, {347, 18}} - - YES - - 67239424 - 0 - Show alert panel before clear history - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{49, 337}, {276, 17}} - - YES - - 67239424 - 272629760 - Number of characters in the menu: - - - - - - - - - 256 - {{322, 335}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - 0 - 1 - NO - YES - 1 - AQAAAAAAAAAAAAAAAAAAAA - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{63, 291}, {273, 18}} - - YES - - 67239424 - 0 - Menu items' title starts with 0 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{50, 311}, {297, 18}} - - YES - - 67239424 - 0 - Mark menu items with numbers - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{67, 45}, {51, 17}} - - YES - - 67239424 - 272629760 - Width: - - - - - - - - - 256 - {{212, 45}, {51, 17}} - - YES - - 67239424 - 272629760 - Height: - - - - - - - - - 256 - {{268, 43}, {43, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{117, 43}, {43, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{165, 45}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - - 256 - {{316, 45}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - - 256 - {{50, 71}, {297, 18}} - - YES - - 67239424 - 0 - Show Image - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{50, 271}, {297, 18}} - - YES - - 67239424 - 0 - Add key equivalents to numeric keys - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{49, 394}, {268, 17}} - - YES - - 68288064 - 272630784 - Number of items place inline: - - - - - - - - - 268 - {{322, 392}, {44, 22}} - - YES - - -1804468671 - -2076179456 - - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 268 - {{49, 367}, {268, 17}} - - YES - - 68288064 - 272630784 - Number of items place inside a folder: - - - - - - - - - 268 - {{322, 365}, {44, 22}} - - YES - - -1804468671 - -2076179456 - - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{50, 145}, {297, 18}} - - YES - - 67239424 - 0 - Change font size in the menu - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 251}, {301, 18}} - - YES - - 67239424 - 0 - Show labels to indicate item types - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 189}, {301, 18}} - - YES - - 67239424 - 0 - Show tool tip on a menu item - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{371, 335}, {39, 14}} - - YES - - 68288064 - 272761856 - chars - - - - - - - - - 268 - {{371, 392}, {39, 14}} - - YES - - 68288064 - 272761856 - items - - - - - - - - - 268 - {{371, 365}, {39, 14}} - - YES - - 68288064 - 272761856 - items - - - - - - - - - 256 - {{222, 102}, {16, 14}} - - YES - - 67239424 - 272629760 - pt - - - - - - - - - 256 - {{153, 97}, {68, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - LucidaGrande - 11 - 16 - - - - - - 400 - 75 - - - 9 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - 3 - YES - YES - 1 - - - - - 268 - {{70, 101}, {241, 38}} - - YES - 2 - 1 - - - -2080244224 - 0 - Fit to the icon size - - - 1211912703 - 0 - - NSRadioButton - - - - 200 - 25 - - - 67239424 - 0 - Select: - - - 1 - 1211912703 - 0 - - 549453824 - {18, 18} - - - - - - TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw -IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ -29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 -dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA -AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG -AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ -0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ -7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ -5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ -3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD -AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns -AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ -6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ -/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ -///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl -YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA -AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD -AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu -AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB -AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES -AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS -AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAAAwYAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAAMGGFw -cGwCAAAAbW50clJHQiBYWVogB9YABAADABMALAASYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAPbWAAEAAAAA0y1hcHBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA -AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAMSbmRpbgAA -BOwAAAY+ZGVzYwAACywAAABkZHNjbQAAC5AAAAAubW1vZAAAC8AAAAAoY3BydAAAC+gAAAAtWFlaIAAA -AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA -AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1 -cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD -AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH -SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF -hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8 -vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt -7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq -Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo -aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e -n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX -2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW -FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O -Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6 -ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt -rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA -AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA -AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl -A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq -DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU -HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8 -MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v -UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/ -eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj -rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn -5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh -AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK -CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY -GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95 -MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S -UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2 -d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV -pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK -0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf// -AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw -BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA -FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H -LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh -Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ -h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp -svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb -1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX -8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE -AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg -QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA - - - - - - 3 - MCAwAA - - - - 400 - 75 - - - {241, 18} - {4, 2} - 1151868928 - NSActionCell - - 67239424 - 0 - Radio - - 1211912703 - 0 - - 549453824 - {18, 18} - - - - - - TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw -IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ -29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 -dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA -AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG -AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ -0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ -7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ -5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ -3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD -AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns -AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ -6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ -/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ -///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl -YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA -AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD -AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu -AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB -AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES -AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS -AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - - - - - - - - 400 - 75 - - - - - - - - - 268 - {{67, 169}, {250, 17}} - - YES - - 68288064 - 272630784 - Max length of tool tip string: - - - - - - - - - 256 - {{322, 166}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 268 - {{371, 166}, {39, 14}} - - YES - - 68288064 - 272761856 - chars - - - - - - - - {460, 434} - - NSView - - NSResponder - - - - 268 - - - - 36 - {{45, 10}, {369, 339}} - - - - 2 - - - 256 - - - - 256 - - - - 256 - - - - 256 - {{14, 150}, {238, 18}} - - YES - - 67239424 - 0 - Plain Text - - LucidaGrande - 12 - 16 - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 130}, {238, 18}} - - YES - - 67239424 - 0 - Rich Text Format (RTF) - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 110}, {238, 18}} - - YES - - 67239424 - 0 - Rich Text Format Directory (RTFD) - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 90}, {238, 18}} - - YES - - 67239424 - 0 - PDF - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 70}, {238, 18}} - - YES - - 67239424 - 0 - Filenames - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 50}, {238, 18}} - - YES - - 67239424 - 0 - URL - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 29}, {238, 18}} - - YES - - 67239424 - 0 - TIFF Image - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{14, 9}, {238, 18}} - - YES - - 67239424 - 0 - PICT Image - - - 1211912703 - 2 - - - - 200 - 25 - - - - {{2, 2}, {325, 176}} - - - - {{6, 100}, {329, 193}} - - {0, 0} - - 67239424 - 0 - Select clipboard types to store: - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - {{10, 25}, {349, 301}} - - - Type - - - - - 1 - - - 256 - - - - 256 - {{136, 251}, {67, 22}} - - YES - - 71433792 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - 16 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - 32 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 48 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 3 - YES - YES - 1 - - - - - 256 - {{37, 257}, {97, 14}} - - YES - - 67239424 - 272760832 - Icon size: - - - - - - - - - 256 - - - - 256 - - - - 256 - {{22, 196}, {111, 14}} - - YES - - 67239424 - 272760832 - Plain Text: - - - - - - - - - 256 - {{136, 191}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 193}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 170}, {73, 14}} - - YES - - 67239424 - 272760832 - RTF: - - - - - - - - - 256 - {{136, 165}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 167}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 144}, {73, 14}} - - YES - - 67239424 - 272760832 - RTFD: - - - - - - - - - 256 - {{136, 139}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 141}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 117}, {73, 14}} - - YES - - 67239424 - 272760832 - PDF: - - - - - - - - - 256 - {{136, 112}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 114}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 91}, {111, 14}} - - YES - - 67239424 - 272760832 - Filenames: - - - - - - - - - 256 - {{136, 86}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 87}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 65}, {73, 14}} - - YES - - 67239424 - 272760832 - URL: - - - - - - - - - 256 - {{136, 60}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 62}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 39}, {73, 14}} - - YES - - 67239424 - 272760832 - TIFF: - - - - - - - - - 256 - {{136, 34}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 36}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 13}, {73, 14}} - - YES - - 67239424 - 272760832 - PICT: - - - - - - - - - 256 - {{136, 8}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - File extension - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - File type code - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 10}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - {{2, 2}, {317, 224}} - - - - {{14, 10}, {321, 241}} - - {0, 0} - - 67239424 - 0 - Icon - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 256 - {{18, 279}, {297, 18}} - - YES - - 67239424 - 131072 - Show Icon in the Menu - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{205, 256}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - {{10, 25}, {349, 301}} - - Icon - - - - - - - 134217728 - YES - YES - - - - - - {460, 366} - NSView - - - - 256 - - - - 256 - {{276, 230}, {68, 25}} - - YES - - 67239424 - 134348800 - Remove - - - -2038284033 - 34 - - - - - - 200 - 25 - - - - - 256 - {{276, 275}, {68, 23}} - - YES - - 67239424 - 134348800 - Folder - - - -2038021889 - 34 - - - - 400 - 75 - - - - - 256 - - - - 2304 - - - - 256 - {246, 266} - - YES - - - 256 - {246, 17} - - - - - - -2147483392 - {{-26, 0}, {16, 17}} - - - - - NameColumn - 243 - 38.599119999999999 - 1000 - - 75628096 - 2048 - Name - - - 3 - MC4zMzMzMzI5OQA - - - 6 - System - headerTextColor - - - - - 337772096 - 2048 - - - - 6 - System - controlBackgroundColor - - - - - 3 - YES - YES - - - - 3 - 2 - - - 6 - System - gridColor - - 3 - MC41AA - - - 17 - -633339904 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {246, 266}} - - - - - 4 - - - - -2147483392 - {{198, 17}, {15, 267}} - - - _doScroller: - 0.94680850000000005 - - - - -2147483392 - {{1, 284}, {212, 15}} - - 1 - - _doScroller: - 1 - 0.99065420000000004 - - - - 2304 - - - - {{1, 0}, {246, 17}} - - - - - 4 - - - - {{20, 42}, {248, 284}} - - - 562 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 256 - {{276, 304}, {68, 23}} - - YES - - 67239424 - 134348800 - << - - - -2038021889 - 34 - - - - 400 - 75 - - - - - 256 - - - - 2304 - - - - 256 - {246, 241} - - YES - - - 256 - {246, 17} - - - - - - -2147483392 - {{-26, 0}, {16, 17}} - - - - - NameColumn - 243 - 38.599119999999999 - 1000 - - 75628096 - 2048 - Name - - - 3 - MC4zMzMzMzI5OQA - - - - - 337772096 - 2048 - - - - - - 3 - YES - - - - 3 - 2 - - - 17 - -633339904 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {246, 241}} - - - - - 4 - - - - -2147483392 - {{-30, 17}, {15, 257}} - - - _doScroller: - 0.96616539999999995 - - - - -2147483392 - {{1, -30}, {182, 15}} - - 1 - - _doScroller: - 0.92385790000000001 - - - - 2304 - - - - {{1, 0}, {246, 17}} - - - - - 4 - - - - {{352, 42}, {248, 259}} - - - 562 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 256 - {{350, 306}, {252, 20}} - - YES - - 67239424 - 131072 - - - - - 80.333340000000007 - Built-in - YES - 2 - - - 81.333340000000007 - JavaScript - 1 - 2 - - - 81.333340000000007 - User's - 2 - 2 - - - - - - - 256 - {{18, 528}, {487, 18}} - - YES - - 67239424 - 0 - Enable Action - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{30, 508}, {475, 18}} - - YES - - 67239424 - 0 - Invoke an action immediately if only one action was registered - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 12 - {{0, 354}, {620, 5}} - - {0, 0} - - 67239424 - 0 - Box - - - - 3 - MCAwLjgwMDAwMDAxAA - - - 3 - 2 - 0 - NO - - - - 36 - - - - 256 - - - - 268 - {{15, 64}, {140, 14}} - - YES - - 68288064 - 71435264 - Shift + Click: - - - - - - - - - 268 - {{15, 89}, {140, 14}} - - YES - - 68288064 - 71435264 - Control + Click: - - - - - - - - - 268 - {{157, 35}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{15, 39}, {140, 14}} - - YES - - 68288064 - 71435264 - Option + Click: - - - - - - - - - 268 - {{157, 60}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{157, 85}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{15, 14}, {140, 14}} - - YES - - 68288064 - 71435264 - Command + Click: - - - - - - - - - 268 - {{157, 10}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - {{1, 1}, {376, 116}} - - - - {{121, 361}, {378, 132}} - - {0, 0} - - 67239424 - 0 - Modifier key + Click behaviors on history menu items - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 1 - 0 - 2 - NO - - - - 256 - {{17, 20}, {45, 14}} - - YES - - 67239424 - 71434240 - Name: - - - - - - - - - 256 - {{64, 20}, {539, 14}} - - YES - - 67239424 - 272760832 - name - - - - - - - - - 12 - {{0, 499}, {620, 5}} - - {0, 0} - - 67239424 - 0 - Box - - - - 3 - MCAwLjgwMDAwMDAxAA - - - 3 - 2 - 0 - NO - - - - 268 - {{17, 334}, {220, 14}} - - YES - - 68288064 - 272761856 - Action Menu - - LucidaGrande-Bold - 11 - 16 - - - - - - - - {620, 564} - - NSView - - NSResponder - - - - 268 - - - - 36 - - - - 256 - - - - 268 - {{15, 45}, {152, 17}} - - YES - - 68288064 - 272630784 - History Menu: - - - - - - - - - 298 - {{172, 42}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - - 268 - {{15, 75}, {152, 17}} - - YES - - 68288064 - 272630784 - Main Menu: - - - - - - - - - 298 - {{172, 72}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - - 268 - {{15, 17}, {152, 17}} - - YES - - 68288064 - 272630784 - Snippets Menu: - - - - - - - - - 298 - {{172, 14}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - {{1, 1}, {359, 104}} - - - - {{49, 24}, {361, 120}} - - {0, 0} - - 67239424 - 0 - Shortcuts - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 1 - 0 - 2 - NO - - - {460, 170} - NSView - - - - 268 - - - - 268 - {{65, 84}, {241, 18}} - - YES - - 67239424 - 0 - Include pre-releases - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{294, 99}, {116, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 129 - - - 400 - 75 - - - Daily - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 86400 - - - YES - - - - - - - Weekly - - 1048576 - 2147483647 - - - _popUpItemAction: - 604800 - - - - - Monthly - - 1048576 - 2147483647 - - - _popUpItemAction: - 2592000 - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{50, 104}, {241, 18}} - - YES - - 67239424 - 0 - Automatically check for updates: - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{163, 42}, {132, 32}} - - YES - - 67239424 - 134217728 - Check Now - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{49, 20}, {361, 14}} - - YES - - 68288064 - -2008939520 - date - - - - - - - - EEEE, MMMM d, yyyy h:mm:ss a - NO - - - - - - - - {460, 140} - NSView - - - 27 - 2 - {{140, 201}, {410, 320}} - 611845120 - Exclude Apps - NSPanel - - {1.79769e+308, 1.79769e+308} - - - 256 - - - - 289 - {{291, 12}, {105, 32}} - - YES - - 67239424 - 134217728 - Done - - - -2038284033 - 129 - - - 200 - 25 - - - - - 289 - {{186, 12}, {105, 32}} - - YES - - 67239424 - 134217728 - Cancel - - - -2038284033 - 129 - - Gw - 200 - 25 - - - - - 268 - {{17, 283}, {376, 17}} - - YES - - 68288064 - 272630784 - Exclude these applications: - - - - - - - - - 274 - - - - 2304 - - - - 256 - {368, 190} - - YES - - - -2147483392 - {{224, 0}, {16, 17}} - - - - ImageAndTextCellColumn - 365 - 40 - 1000 - - 75628096 - 2048 - - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - - - - - 3 - YES - - - - 3 - 2 - - - 17 - 1522532352 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 1}, {368, 190}} - - - - - 4 - - - - -2147483392 - {{224, 17}, {15, 102}} - - - _doScroller: - 0.99468085106382975 - - - - -2147483392 - {{1, 68}, {125, 15}} - - 1 - - _doScroller: - 0.99728997289972898 - - - {{20, 83}, {370, 192}} - - - 562 - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 292 - {{20, 55}, {21, 21}} - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSAddTemplate - - - - 400 - 75 - - - - - 292 - {{40, 55}, {21, 21}} - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSRemoveTemplate - - - - 400 - 75 - - - - {410, 320} - - {{0, 0}, {1280, 1002}} - {1.79769e+308, 1.79769e+308} - - - - - - - actionTreeController - - - - 357 - - - - actionNodeController - - - - 365 - - - - contentArray: actionNodes - - - - - - contentArray: actionNodes - contentArray - actionNodes - 2 - - - 366 - - - - reserveTreeController - - - - 372 - - - - value: values.inputPasteCommand - - - - - - value: values.inputPasteCommand - value - values.inputPasteCommand - 2 - - - 442 - - - - value: values.timeInterval - - - - - - value: values.timeInterval - value - values.timeInterval - 2 - - - 447 - - - - generalPrefsView - - - - 459 - - - - value: values.maxMenuItemTitleLength - - - - - - value: values.maxMenuItemTitleLength - value - values.maxMenuItemTitleLength - 2 - - - 542 - - - - value: values.menuItemsAreMarkedWithNumbers - - - - - - value: values.menuItemsAreMarkedWithNumbers - value - values.menuItemsAreMarkedWithNumbers - 2 - - - 544 - - - - value: values.menuItemsTitleStartWithZero - - - - - - value: values.menuItemsTitleStartWithZero - value - values.menuItemsTitleStartWithZero - 2 - - - 546 - - - - enabled: values.menuItemsAreMarkedWithNumbers - - - - - - enabled: values.menuItemsAreMarkedWithNumbers - enabled - values.menuItemsAreMarkedWithNumbers - 2 - - - 547 - - - - value: values.changeFontSize - - - - - - value: values.changeFontSize - value - values.changeFontSize - 2 - - - 549 - - - - enabled: values.changeFontSize - - - - - - enabled: values.changeFontSize - enabled - values.changeFontSize - 2 - - - 554 - - - - contentValues: fontSizePopUpMenuItems - - - - - - contentValues: fontSizePopUpMenuItems - contentValues - fontSizePopUpMenuItems - 2 - - - 556 - - - - selectedValue: values.selectedFontSize - - - - - - selectedValue: values.selectedFontSize - selectedValue - values.selectedFontSize - - 2 - - - 557 - - - - value: values.showImageInTheMenu - - - - - - value: values.showImageInTheMenu - value - values.showImageInTheMenu - 2 - - - 559 - - - - value: values.thumbnailWidth - - - - - - value: values.thumbnailWidth - value - values.thumbnailWidth - 2 - - - 561 - - - - value: values.thumbnailHeight - - - - - - value: values.thumbnailHeight - value - values.thumbnailHeight - 2 - - - 563 - - - - enabled: values.showImageInTheMenu - - - - - - enabled: values.showImageInTheMenu - enabled - values.showImageInTheMenu - 2 - - - 564 - - - - enabled: values.showImageInTheMenu - - - - - - enabled: values.showImageInTheMenu - enabled - values.showImageInTheMenu - 2 - - - 565 - - - - menuPrefsView - - - - 606 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - 2 - - - 626 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - - NSConditionallySetsEditable - - - 2 - - - 627 - - - - selectedIndex: indexOfActionTypeSegment - - - - - - selectedIndex: indexOfActionTypeSegment - selectedIndex - indexOfActionTypeSegment - 2 - - - 628 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 630 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - 2 - - - 632 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 634 - - - - actionPrefsView - - - - 635 - - - - nameField - - - - 638 - - - - reservedActionsOutlineView - - - - 641 - - - - actionsOutlineView - - - - 642 - - - - actionTypeSegmentedControll - - - - 643 - - - - dataSource - - - - 649 - - - - delegate - - - - 650 - - - - dataSource - - - - 651 - - - - delegate - - - - 652 - - - - remove: - - - - 653 - - - - add: - - - - 654 - - - - add: - - - - 655 - - - - value: values.enableAction - - - - - - value: values.enableAction - value - values.enableAction - 2 - - - 661 - - - - value: values.addNumericKeyEquivalents - - - - - - value: values.addNumericKeyEquivalents - value - values.addNumericKeyEquivalents - 2 - - - 665 - - - - value: values.showAlertBeforeClearHistory - - - - - - value: values.showAlertBeforeClearHistory - value - values.showAlertBeforeClearHistory - 2 - - - 671 - - - - value: values.addClearHistoryMenuItem - - - - - - value: values.addClearHistoryMenuItem - value - values.addClearHistoryMenuItem - 2 - - - 672 - - - - enabled: values.addClearHistoryMenuItem - - - - - - enabled: values.addClearHistoryMenuItem - enabled - values.addClearHistoryMenuItem - 2 - - - 673 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 677 - - - - enabled2: values.howToChangeFontSize - - - - - - enabled2: values.howToChangeFontSize - enabled2 - values.howToChangeFontSize - - - - - - - - 2 - - - 678 - - - - value: values.loginItem - - - - - - value: values.loginItem - value - values.loginItem - 2 - - - 771 - - - - value: values.showIconInTheMenu - - - - - - value: values.showIconInTheMenu - value - values.showIconInTheMenu - 2 - - - 1007 - - - - selectedValue: values.menuIconSize - - - - - - selectedValue: values.menuIconSize - selectedValue - values.menuIconSize - 2 - - - 1008 - - - - enabled: values.showIconInTheMenu - - - - - - enabled: values.showIconInTheMenu - enabled - values.showIconInTheMenu - 2 - - - 1009 - - - - selectedTag: values.menuIconOfFileTypeTagForString - - - - - - selectedTag: values.menuIconOfFileTypeTagForString - selectedTag - values.menuIconOfFileTypeTagForString - 2 - - - 1010 - - - - selectedTag: values.menuIconOfFileTypeTagForRTF - - - - - - selectedTag: values.menuIconOfFileTypeTagForRTF - selectedTag - values.menuIconOfFileTypeTagForRTF - 2 - - - 1011 - - - - selectedTag: values.menuIconOfFileTypeTagForRTFD - - - - - - selectedTag: values.menuIconOfFileTypeTagForRTFD - selectedTag - values.menuIconOfFileTypeTagForRTFD - 2 - - - 1012 - - - - selectedTag: values.menuIconOfFileTypeTagForPDF - - - - - - selectedTag: values.menuIconOfFileTypeTagForPDF - selectedTag - values.menuIconOfFileTypeTagForPDF - 2 - - - 1013 - - - - selectedTag: values.menuIconOfFileTypeTagForFilenames - - - - - - selectedTag: values.menuIconOfFileTypeTagForFilenames - selectedTag - values.menuIconOfFileTypeTagForFilenames - 2 - - - 1014 - - - - selectedTag: values.menuIconOfFileTypeTagForURL - - - - - - selectedTag: values.menuIconOfFileTypeTagForURL - selectedTag - values.menuIconOfFileTypeTagForURL - 2 - - - 1015 - - - - selectedTag: values.menuIconOfFileTypeTagForTIFF - - - - - - selectedTag: values.menuIconOfFileTypeTagForTIFF - selectedTag - values.menuIconOfFileTypeTagForTIFF - 2 - - - 1016 - - - - selectedTag: values.menuIconOfFileTypeTagForPICT - - - - - - selectedTag: values.menuIconOfFileTypeTagForPICT - selectedTag - values.menuIconOfFileTypeTagForPICT - 2 - - - 1017 - - - - iconPrefsView - - - - 1018 - - - - value: values.menuIconOfFileTypeForString - - - - - - value: values.menuIconOfFileTypeForString - value - values.menuIconOfFileTypeForString - 2 - - - 1019 - - - - value: values.menuIconOfFileTypeForRTF - - - - - - value: values.menuIconOfFileTypeForRTF - value - values.menuIconOfFileTypeForRTF - 2 - - - 1020 - - - - value: values.menuIconOfFileTypeForRTFD - - - - - - value: values.menuIconOfFileTypeForRTFD - value - values.menuIconOfFileTypeForRTFD - 2 - - - 1021 - - - - value: values.menuIconOfFileTypeForPDF - - - - - - value: values.menuIconOfFileTypeForPDF - value - values.menuIconOfFileTypeForPDF - 2 - - - 1022 - - - - value: values.menuIconOfFileTypeForFilenames - - - - - - value: values.menuIconOfFileTypeForFilenames - value - values.menuIconOfFileTypeForFilenames - 2 - - - 1023 - - - - value: values.menuIconOfFileTypeForURL - - - - - - value: values.menuIconOfFileTypeForURL - value - values.menuIconOfFileTypeForURL - 2 - - - 1024 - - - - value: values.menuIconOfFileTypeForTIFF - - - - - - value: values.menuIconOfFileTypeForTIFF - value - values.menuIconOfFileTypeForTIFF - 2 - - - 1025 - - - - value: values.menuIconOfFileTypeForPICT - - - - - - value: values.menuIconOfFileTypeForPICT - value - values.menuIconOfFileTypeForPICT - 2 - - - 1026 - - - - value: values.numberOfItemsPlaceInline - - - - - - value: values.numberOfItemsPlaceInline - value - values.numberOfItemsPlaceInline - 2 - - - 1036 - - - - value: values.numberOfItemsPlaceInsideFolder - - - - - - value: values.numberOfItemsPlaceInsideFolder - value - values.numberOfItemsPlaceInsideFolder - 2 - - - 1042 - - - - value: values.showLabelsInMenu - - - - - - value: values.showLabelsInMenu - value - values.showLabelsInMenu - 2 - - - 1045 - - - - value: values.saveHistoryOnQuit - - - - - - value: values.saveHistoryOnQuit - value - values.saveHistoryOnQuit - 2 - - - 1048 - - - - value: storeTypes.String - - - - - - value: storeTypes.String - value - storeTypes.String - 2 - - - 1105 - - - - value: storeTypes.RTF - - - - - - value: storeTypes.RTF - value - storeTypes.RTF - 2 - - - 1106 - - - - value: storeTypes.RTFD - - - - - - value: storeTypes.RTFD - value - storeTypes.RTFD - 2 - - - 1107 - - - - value: storeTypes.PDF - - - - - - value: storeTypes.PDF - value - storeTypes.PDF - 2 - - - 1108 - - - - value: storeTypes.Filenames - - - - - - value: storeTypes.Filenames - value - storeTypes.Filenames - 2 - - - 1109 - - - - value: storeTypes.URL - - - - - - value: storeTypes.URL - value - storeTypes.URL - 2 - - - 1110 - - - - value: storeTypes.TIFF - - - - - - value: storeTypes.TIFF - value - storeTypes.TIFF - 2 - - - 1111 - - - - value: storeTypes.PICT - - - - - - value: storeTypes.PICT - value - storeTypes.PICT - 2 - - - 1113 - - - - value: values.showToolTipOnMenuItem - - - - - - value: values.showToolTipOnMenuItem - value - values.showToolTipOnMenuItem - 2 - - - 1158 - - - - value: values.invokeActionImmediately - - - - - - value: values.invokeActionImmediately - value - values.invokeActionImmediately - 2 - - - 1159 - - - - value: values.maxHistorySize - - - - - - value: values.maxHistorySize - value - values.maxHistorySize - 2 - - - 1165 - - - - nextKeyView - - - - 1168 - - - - nextKeyView - - - - 1169 - - - - controlPopUpButton - - - - 1201 - - - - shiftPopUpButton - - - - 1210 - - - - optionPopUpButton - - - - 1216 - - - - commandPopUpButton - - - - 1222 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1227 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1228 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1229 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1230 - - - - enabled: values.changeFontSize - - - - - - enabled: values.changeFontSize - enabled - values.changeFontSize - 2 - - - 1242 - - - - selectedTag: values.howToChangeFontSize - - - - - - selectedTag: values.howToChangeFontSize - selectedTag - values.howToChangeFontSize - 2 - - - 1245 - - - - enabled: values.showToolTipOnMenuItem - - - - - - enabled: values.showToolTipOnMenuItem - enabled - values.showToolTipOnMenuItem - 2 - - - 1265 - - - - value: values.maxLengthOfToolTipKey - - - - - - value: values.maxLengthOfToolTipKey - value - values.maxLengthOfToolTipKey - 2 - - - 1266 - - - - nextKeyView - - - - 1270 - - - - nextKeyView - - - - 1271 - - - - nextKeyView - - - - 1272 - - - - nextKeyView - - - - 1273 - - - - selectedTag: values.autosaveDelay - - - - - - selectedTag: values.autosaveDelay - selectedTag - values.autosaveDelay - 2 - - - 1298 - - - - value: values.timeInterval - - - - - - value: values.timeInterval - value - values.timeInterval - 2 - - - 1301 - - - - selectedTag: values.showStatusItem - - - - - - selectedTag: values.showStatusItem - selectedTag - values.showStatusItem - 2 - - - 1319 - - - - updatesPrefsView - - - - 1325 - - - - checkForUpdates: - - - - 1333 - - - - value: lastUpdateCheckDate - - - - - - value: lastUpdateCheckDate - value - lastUpdateCheckDate - 2 - - - 1334 - - - - value: values.enableAutomaticCheck - - - - - - value: values.enableAutomaticCheck - value - values.enableAutomaticCheck - 2 - - - 1347 - - - - selectedTag: values.updateCheckInterval - - - - - - selectedTag: values.updateCheckInterval - selectedTag - values.updateCheckInterval - 2 - - - 1356 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1357 - - - - shortcutPrefsView - - - - 1365 - - - - delegate - - - - 1375 - - - - delegate - - - - 1376 - - - - shortcutRecorder - - - - 1377 - - - - exportHistory: - - - - 1411 - - - - selectedTag: values.tagOfSeparatorForExportHistoryToFile - - - - - - selectedTag: values.tagOfSeparatorForExportHistoryToFile - selectedTag - values.tagOfSeparatorForExportHistoryToFile - 2 - - - 1412 - - - - selectedTag: values.exportHistoryAsSingleFile - - - - - - selectedTag: values.exportHistoryAsSingleFile - selectedTag - values.exportHistoryAsSingleFile - 2 - - - 1413 - - - - enabled: values.exportHistoryAsSingleFile - - - - - - enabled: values.exportHistoryAsSingleFile - enabled - values.exportHistoryAsSingleFile - 2 - - - 1414 - - - - selectedIndex: values.reorderClipsAfterPasting - - - - - - selectedIndex: values.reorderClipsAfterPasting - selectedIndex - values.reorderClipsAfterPasting - 2 - - - 1424 - - - - value: values.enableAutomaticCheckPreReleaseKey - - - - - - value: values.enableAutomaticCheckPreReleaseKey - value - values.enableAutomaticCheckPreReleaseKey - 2 - - - 1427 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1429 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1430 - - - - openExcludeOptions: - - - - 1450 - - - - value: arrangedObjects.name - - - - - - value: arrangedObjects.name - value - arrangedObjects.name - 2 - - - 1482 - - - - contentArray: excludeList - - - - - - contentArray: excludeList - contentArray - excludeList - - NSDeletesObjectsOnRemove - - - 2 - - - 1484 - - - - delegate - - - - 1485 - - - - remove: - - - - 1487 - - - - excludeListController - - - - 1489 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 1490 - - - - addExcludeListButtion - - - - 1494 - - - - excludeListPanel - - - - 1495 - - - - cancelExcludeListPanel: - - - - 1496 - - - - doneExcludeListPanel: - - - - 1497 - - - - addToExcludeList: - - - - 1498 - - - - delegate - - - - 1504 - - - - snippetsShortcutRecorder - - - - 1505 - - - - historyShortCutRecorder - - - - 1506 - - - - selectedIndex: values.positionOfSnippets - - - - - - selectedIndex: values.positionOfSnippets - selectedIndex - values.positionOfSnippets - 2 - - - 1515 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - 10 - - - Shared Defaults - - - 329 - - - ActionTreeController - - - 355 - - - ActionNodeController - - - 370 - - - ReserveTreeController - - - 412 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - General - - - 420 - - - - - - - - 421 - - - - - - - - 424 - - - - - - - - 425 - - - - - - - - 460 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Menu - - - 461 - - - - - - - - 462 - - - - - - - - 464 - - - - - - - - 465 - - - - - - - - 466 - - - - - - - - 467 - - - - - - - - 468 - - - - - - - - 470 - - - - - - - - 472 - - - - - - - - 473 - - - - - - - - 524 - - - - - - - - 663 - - - - - - - - 607 - - - - - - - - - - - - - - - - - - - Action - - - 608 - - - - - - - - 609 - - - - - - - - 610 - - - - - - - - - - - 611 - - - - - - - - 612 - - - - - - - - 613 - - - - - - - - 622 - - - - - - - - - - - 623 - - - - - - - - 624 - - - - - - - - 625 - - - - - - - - 656 - - - - - - - - 674 - - - - - - - - 686 - - - - - 687 - - - - - 689 - - - - - 690 - - - - - 703 - - - - - 704 - - - - - - - - 705 - - - - - 706 - - - - - 707 - - - - - 708 - - - - - 709 - - - - - - - - 710 - - - - - - - - 711 - - - - - 712 - - - - - 737 - - - - - 743 - - - - - 746 - - - - - 747 - - - - - 748 - - - - - 755 - - - - - 756 - - - - - 757 - - - - - 759 - - - - - 760 - - - - - 463 - - - - - 469 - - - - - 471 - - - - - 761 - - - - - 762 - - - - - 763 - - - - - 764 - - - - - 765 - - - - - 766 - - - - - -3 - - - Application - - - 767 - - - - - - - - 768 - - - - - 921 - - - - - - Type - - - 1027 - - - - - - - - 1028 - - - - - 1029 - - - - - - - - 1030 - - - - - - - - 1031 - - - - - - - - 1032 - - - - - - - - 1033 - - - - - - - - 1034 - - - - - 533 - - - - - - - - 744 - - - - - 1038 - - - - - 1039 - - - - - 1043 - - - - - - - - 1044 - - - - - 1046 - - - - - - - - 1047 - - - - - 1083 - - - - - - - - - 1084 - - - - - - - - 1085 - - - - - - - - - - - - 1086 - - - - - - - - 1087 - - - - - - - - 925 - - - - - - - - 928 - - - - - - - - 929 - - - - - - - - - - 932 - - - - - 931 - - - - - 930 - - - - - 924 - - - - - - - - 933 - - - - - 922 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 935 - - - - - - - - 938 - - - - - - - - 941 - - - - - - - - 944 - - - - - - - - 947 - - - - - - - - 950 - - - - - - - - 953 - - - - - - - - 956 - - - - - - - - 958 - - - - - - - - 957 - - - - - - - - 955 - - - - - - - - 954 - - - - - - - - 952 - - - - - - - - 951 - - - - - - - - 949 - - - - - - - - 948 - - - - - - - - 946 - - - - - - - - 945 - - - - - - - - 943 - - - - - - - - 942 - - - - - - - - 940 - - - - - - - - 939 - - - - - - - - 937 - - - - - - - - 936 - - - - - - - - 1002 - - - - - - - - 1003 - - - - - - - - - 1005 - - - - - 1004 - - - - - 1001 - - - - - 996 - - - - - - - - 997 - - - - - - - - - 999 - - - - - 998 - - - - - 995 - - - - - 990 - - - - - - - - 991 - - - - - - - - - 993 - - - - - 992 - - - - - 989 - - - - - 984 - - - - - - - - 985 - - - - - - - - - 987 - - - - - 986 - - - - - 983 - - - - - 978 - - - - - - - - 979 - - - - - - - - - 981 - - - - - 980 - - - - - 977 - - - - - 972 - - - - - - - - 973 - - - - - - - - - 975 - - - - - 974 - - - - - 971 - - - - - 966 - - - - - - - - 967 - - - - - - - - - 969 - - - - - 968 - - - - - 965 - - - - - 960 - - - - - - - - 961 - - - - - - - - - 963 - - - - - 962 - - - - - 959 - - - - - 964 - - - - - 970 - - - - - 976 - - - - - 982 - - - - - 988 - - - - - 994 - - - - - 1000 - - - - - 1006 - - - - - 923 - - - - - - - - 934 - - - - - 926 - - - - - - - - 927 - - - - - 1088 - - - - - - - - - - - - - - - 1089 - - - - - - - - 1090 - - - - - - - - 1091 - - - - - - - - 1092 - - - - - - - - 1093 - - - - - - - - 1094 - - - - - - - - 1095 - - - - - - - - 1096 - - - - - - - - 1097 - - - - - 1098 - - - - - 1099 - - - - - 1100 - - - - - 1101 - - - - - 1102 - - - - - 1103 - - - - - 1104 - - - - - 1124 - - - - - 1156 - - - - - - - - 1157 - - - - - 1172 - - - - - - - - 1173 - - - - - 1174 - - - - - - - - 1175 - - - - - 1176 - - - - - - - - 1177 - - - - - 1223 - - - - - - - - - - - - - - - 1205 - - - - - - - - 1209 - - - - - 1189 - - - - - - - - 1190 - - - - - 1212 - - - - - - - - 1213 - - - - - - - - 1214 - - - - - 1211 - - - - - - - - 1215 - - - - - 1206 - - - - - - - - 1207 - - - - - - - - 1208 - - - - - 1191 - - - - - - - - 1192 - - - - - - - - 1193 - - - - - 1217 - - - - - - - - 1221 - - - - - 1218 - - - - - - - - 1219 - - - - - - - - 1220 - - - - - 619 - - - - - - - - 752 - - - - - 617 - - - - - - - - 750 - - - - - 1224 - - - - - 1231 - - - - - - - - 1232 - - - - - 540 - - - - - - - - 742 - - - - - 537 - - - - - - - - 745 - - - - - - - - 538 - - - - - - - - 539 - - - - - 1237 - - - - - - - - - - 1238 - - - - - 1239 - - - - - 1240 - - - - - 1255 - - - - - - - - 1256 - - - - - 1257 - - - - - - - - 1258 - - - - - - - - 1259 - - - - - 1260 - - - - - - - - 1263 - - - - - 1274 - - - - - - - - 1275 - - - - - 1276 - - - - - - - - 1277 - - - - - 1278 - - - - - - - - 1279 - - - - - 1280 - - - - - - - - 1281 - - - - - 1282 - - - - - - - - 1283 - - - - - - - - 1284 - - - - - - - - - - - - - - - - - 1285 - - - - - 1286 - - - - - 1287 - - - - - 1289 - - - - - 1290 - - - - - 1291 - - - - - 1292 - - - - - 1293 - - - - - 1294 - - - - - 1295 - - - - - 1299 - - - - - - - - 1300 - - - - - - - - 1303 - - - - - 1170 - - - - - - - - 1171 - - - - - 1161 - - - - - - - - 1162 - - - - - - - - 1163 - - - - - 1160 - - - - - - - - 1164 - - - - - 669 - - - - - - - - 702 - - - - - 666 - - - - - - - - 701 - - - - - 1304 - - - - - - - - 1305 - - - - - 1309 - - - - - - - - 1310 - - - - - - - - 1311 - - - - - - - - - - - - - - - - - - - - - 1312 - - - - - 1313 - - - - - 1315 - - - - - - - - 1316 - - - - - 1318 - - - - - 1320 - - - - - 1321 - - - - - 1322 - - - - - 1323 - - - - - 1324 - - - - - - - - - - Updates - - - 1328 - - - - - - - - 1329 - - - - - - - - 1330 - - - - - - - - 1331 - - - - - 1332 - - - - - 1335 - - - - - 1336 - - - - - - - - 1337 - - - - - 1350 - - - - - - - - 1351 - - - - - - - - 1352 - - - - - - - - - - 1353 - - - - - 1354 - - - - - 1355 - - - - - 1358 - - - - - 1359 - - - - - 1360 - - - - - 1361 - - - - - 1362 - - - - - 1363 - - - - - 1364 - - - - - - Shortcuts - - - 1366 - - - - - - - - - - - - - 1367 - - - - - - - - 1368 - - - - - - - - 1369 - - - - - - - - 1370 - - - - - - - - 1371 - - - - - 1372 - - - - - 1373 - - - - - 1374 - - - - - 1379 - - - - - - - - 1380 - - - - - 1381 - - - - - - - - 1382 - - - - - - - - 1383 - - - - - - - - - 1384 - - - - - 1385 - - - - - 1389 - - - - - - - - 1390 - - - - - 1395 - - - - - - - - 1396 - - - - - 1401 - - - - - - - - 1402 - - - - - - - - 1403 - - - - - - - - - - - - - 1404 - - - - - 1405 - - - - - 1406 - - - - - 1407 - - - - - 1408 - - - - - 1410 - - - - - 1416 - - - - - - - - 1417 - - - - - 1418 - - - - - - - - 1419 - - - - - - - - 1420 - - - - - - - - - 1421 - - - - - 1422 - - - - - 1425 - - - - - - - - 1426 - - - - - 1445 - - - - - - - - 1446 - - - - - 1447 - - - - - - - - 1448 - - - - - 1451 - - - - - - ExcludeListPanel (Window) - - - 1452 - - - - - - - - - - - - - 1453 - - - - - - - - 1454 - - - - - 1455 - - - - - - - - 1456 - - - - - 1458 - - - - - - - - 1459 - - - - - 1463 - - - - - - - - - - 1464 - - - - - 1465 - - - - - 1466 - - - - - - - - 1468 - - - - - - - - 1471 - - - - - 1472 - - - - - - - - 1473 - - - - - 1474 - - - - - - - - 1475 - - - - - 1481 - - - ExcludeList Controller - - - 1500 - - - - - - - - 1501 - - - - - - - - 1502 - - - - - 1503 - - - - - 1507 - - - - - - - - 1508 - - - - - - - - 1509 - - - - - 1510 - - - - - - - - 1511 - - - - - - - - - - 1512 - - - - - 1513 - - - - - 1514 - - - - - 1516 - - - - - - - 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 - 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 - 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 - - 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 - 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 - 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 - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - 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 - 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 - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{360, 484}, {152, 173}} - 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 - 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 - {{392, 338}, {109, 284}} - 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 - {{217, 688}, {460, 140}} - 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 - {{468, 750}, {121, 63}} - 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 - {{371, 645}, {460, 170}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - net.wafflesoftware.ShortcutRecorder.IB.Leopard - 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 - {{392, 690}, {152, 37}} - 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 - {{360, 597}, {152, 105}} - 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 - {{392, 759}, {152, 37}} - 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 - {{151, 556}, {410, 320}} - com.apple.InterfaceBuilder.CocoaPlugin - {{151, 556}, {410, 320}} - - 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 - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - ActionPopUpButton - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{553, 425}, {208, 54}} - 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 - - {{155, 445}, {460, 494}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{361, 441}, {460, 434}} - 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 - - - - 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 - - {{244, 338}, {620, 564}} - 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 - - 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 - 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 - 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 - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - - ImageAndTextCell - 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 - {{359, 104}, {460, 366}} - 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 - - 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 - - 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 - - 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 - {{406, 470}, {138, 37}} - 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 - 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 - 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 - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - - - - - 1516 - - - - - ActionNodeController - NSObject - - id - id - - - NSTreeController - NSOutlineView - NSTextField - NSTextField - NSTreeController - NSOutlineView - NSTextField - - - IBProjectSource - Source/ActionNodeController.h - - - - ActionNodeController - NSObject - - actionTypeSegmentedControll - NSSegmentedControl - - - IBUserSource - - - - - ActionPopUpButton - NSButton - - IBProjectSource - Source/ActionPopUpButton.h - - - - DBPrefsWindowController - NSWindowController - - IBProjectSource - Source/DBPrefsWindowController/DBPrefsWindowController.h - - - - DBPrefsWindowController - NSWindowController - - IBUserSource - - - - - FirstResponder - NSObject - - IBUserSource - - - - - ImageAndTextCell - NSTextFieldCell - - IBProjectSource - Source/CocoaExtensions/ImageAndTextCell.h - - - - NSSegmentedControl - NSControl - - IBUserSource - - - - - PrefsWindowController - DBPrefsWindowController - - id - id - id - id - id - - - ActionNodeController - NSView - ActionPopUpButton - NSPopUpButton - NSPopUpButton - NSArrayController - NSPanel - NSView - SRRecorderControl - NSView - NSView - NSPopUpButton - NSPopUpButton - NSView - SRRecorderControl - SRRecorderControl - NSView - - - IBProjectSource - Source/PrefsWindowController.h - - - - PrefsWindowController - DBPrefsWindowController - - IBUserSource - - - - - - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSApplication - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSApplication+BWAdditions.h - - - - NSArrayController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSArrayController.h - - - - NSBox - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSBox.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSController - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSController.h - - - - NSDateFormatter - NSFormatter - - IBFrameworkSource - Foundation.framework/Headers/NSDateFormatter.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSManagedObjectContext - NSObject - - IBFrameworkSource - CoreData.framework/Headers/NSManagedObjectContext.h - - - - NSMatrix - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSMatrix.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMenuItemCell - NSButtonCell - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItemCell.h - - - - NSNumberFormatter - NSFormatter - - IBFrameworkSource - Foundation.framework/Headers/NSNumberFormatter.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderCell.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderControl.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRValidator.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSObjectController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSObjectController.h - - - - NSOutlineView - NSTableView - - - - NSPanel - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSPanel.h - - - - NSPopUpButton - NSButton - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButton.h - - - - NSPopUpButtonCell - NSMenuItemCell - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButtonCell.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSegmentedCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedCell.h - - - - NSSegmentedControl - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedControl.h - - - - NSSlider - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSSlider.h - - - - NSSliderCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSSliderCell.h - - - - NSTabView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTabView.h - - - - NSTabViewItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTabViewItem.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableHeaderView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTableHeaderView.h - - - - NSTableView - NSControl - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSTreeController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSTreeController.h - - - - NSUserDefaultsController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSUserDefaultsController.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSView+BWAdditions.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSWindow+BWAdditions.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - - SRRecorderCell - NSActionCell - - delegate - id - - - - - SRRecorderControl - NSControl - - delegate - id - - - - - SUUpdater - NSObject - - checkForUpdates: - id - - - delegate - id - - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - YES - ../ClipMenu.xcodeproj - 3 - - {8, 8} - {9, 8} - {7, 2} - {8, 8} - {15, 15} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18.2227, 18.2227} - {18, 18} - - - diff --git a/English.lproj/SnippetEditor.strings b/English.lproj/SnippetEditor.strings deleted file mode 100644 index 96285fa..0000000 Binary files a/English.lproj/SnippetEditor.strings and /dev/null differ diff --git a/English.lproj/SnippetEditor.xib b/English.lproj/SnippetEditor.xib deleted file mode 100644 index f276253..0000000 --- a/English.lproj/SnippetEditor.xib +++ /dev/null @@ -1,3046 +0,0 @@ - - - - 1060 - 10D578 - 762 - 1038.29 - 460.00 - - 762 - 1.2.5 - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.brandonwalkin.BWToolkit - - - - - SnippetEditorController - - - FirstResponder - - - NSApplication - - - - title - nodeTitle - snippets - count - isEnabled - folder - - FolderNode - YES - YES - - Folder - - YES - YES - YES - children - isLeaf - - - - title - enabled - snippets - isEnabled - - Folder - YES - YES - - Folder - - YES - YES - YES - YES - YES - YES - - - - enabled - content - title - folder - - YES - YES - - Snippet - - YES - YES - YES - YES - YES - YES - - - 15 - 2 - {{212, 496}, {640, 480}} - 611844096 - Snippet Editor - NSWindow - - - 85FAC2A8-501B-4845-9B3C-05CDCCFFD4F0 - - - YES - YES - YES - YES - 1 - 1 - - - - 0242B2D4-DD8C-42CE-BDD9-36F4B857D01F - - Search - Search - - - - 259 - {{0, 14}, {182, 22}} - - - YES - - 341966400 - 1024 - - LucidaGrande - 13 - 1044 - - All - - YES - 1 - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - controlTextColor - - 3 - MAA - - - - 130560 - 0 - search - - _searchFieldSearch: - - 138690815 - 0 - - 400 - 75 - - - -2147353088 - 0 - clear - - - cancel - - - - _searchFieldCancel: - - 138428671 - 0 - - 400 - 75 - - 255 - - - - - - {182, 19} - {182, 22} - YES - YES - 0 - YES - 0 - - - - 52BD21E1-AE24-47C2-A614-3988942099B1 - - Add Snippet - Add Snippet - Add Snippet - - - NSImage - AddSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - - DCABAF9F-0E80-4BBC-B624-9BA7F5113A25 - - Delete Snippet - Delete Snippet - Delete Snippet - - - NSImage - DeleteSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - - F54CF4F2-7F9E-428F-9DD3-48BFEE1132BD - - Enable/Disable - Enable/Disable - Enable/Disable Snippet - - - NSImage - CheckSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - NSToolbarCustomizeToolbarItem - Customize - Customize - Customize Toolbar - - - NSImage - NSToolbarCustomizeToolbarItemImage - - - runToolbarCustomizationPalette: - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - NSToolbarFlexibleSpaceItem - - Flexible Space - - - - - - {1, 5} - {20000, 32} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - - - - NSToolbarSeparatorItem - - Separator - - - - - - {12, 5} - {12, 1000} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - - - - - NSToolbarSpaceItem - - Space - - - - - - {32, 5} - {32, 32} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - - - - - - - - - - - - - - - - - - - - - - - - {1.79769e+308, 1.79769e+308} - - - 256 - - - - 274 - - - - 258 - - - - 4370 - - - - 2304 - - - - 4352 - {243, 459} - - YES - - - -2147483392 - {{229, 0}, {16, 17}} - - - - ImageAndTextCellColumn - 240 - 16 - 1000 - - 75628096 - 2048 - Title - - LucidaGrande - 11 - 3100 - - - 3 - MC4zMzMzMzI5ODU2AA - - - 6 - System - headerTextColor - - - - - 337772096 - 2048 - Text Cell - - - - 6 - System - controlBackgroundColor - - 3 - MC42NjY2NjY2NjY3AA - - - - - 3 - YES - YES - - - - 3 - 0.0 - - 6 - System - _sourceListBackgroundColor - - 1 - MC44MzkyMTU2OTU5IDAuODY2NjY2Njc0NiAwLjg5ODAzOTIyMTgAA - - - - 6 - System - gridColor - - 3 - MC41AA - - - 20 - -633339904 - - - 4 - 15 - 0 - YES - 1 - 1 - 14 - - - {{1, 1}, {243, 459}} - - - - - 4 - - - - -2147483392 - {{229, 17}, {15, 427}} - - - _doScroller: - 0.9978213507625272 - - - - -2147483392 - {{1, 444}, {243, 15}} - - 1 - - _doScroller: - 0.99590163934426235 - - - {{-1, 20}, {245, 461}} - - - 562 - - - - QSAAAEEgAABBoAAAQaAAAA - - - - 4370 - - - - 2304 - - - - 4352 - {248, 457} - - YES - - - -2147483392 - {{224, 0}, {16, 17}} - - - 3 - 2 - - 1 - MC44NzQ1MDk4MDM5IDAuODkwMTk2MDc4NCAwLjkxNzY0NzA1ODgAA - - - 17 - -700448768 - - - 4 - 15 - 0 - YES - 1 - 1 - - - {{1, 1}, {248, 457}} - - - - - 4 - - - - -2147483392 - {{234, 1}, {15, 442}} - - - _doScroller: - 0.48253275109170307 - - - - -2147483392 - {{1, 443}, {233, 15}} - - 1 - - _doScroller: - 0.99581589958159 - - - {{-1, 22}, {250, 459}} - - - 562 - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 258 - - - - 268 - {{-1, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - NSAddTemplate - - - - 200 - 25 - - - - - 268 - {{30, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - NSRemoveTemplate - - - - 200 - 25 - - - - - 268 - {{61, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - check - - - - 200 - 25 - - - - - 268 - {{92, -1}, {32, 24}} - - YES - - -2076049856 - 134350848 - - LucidaGrande - 13 - 16 - - - -2038284033 - 163 - - - 400 - 75 - - - YES - - - 1048576 - 2147483647 - 1 - - NSImage - NSActionTemplate - - - - _popUpItemAction: - - - YES - - OtherViews - - - - - Import Snippets... - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Export Snippets... - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - YES - 1 - YES - YES - 2 - - - - {244, 23} - - YES - YES - NO - 0 - - - {244, 480} - - NSView - - - - 258 - - - - 274 - - - - 272 - - - - 4370 - - - - 2304 - - - - 4352 - {395, 223} - - YES - - - 256 - {395, 17} - - - - - - -2147483392 - {{380, 0}, {16, 17}} - - - - - ImageAndTextCellColumn - 372 - 40 - 1000 - - 75628096 - 2048 - Title - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - - - - - 3 - YES - YES - - - - 3 - 2 - - - 17 - -1698693120 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {395, 223}} - - - - - 4 - - - - -2147483392 - {{380, 17}, {15, 223}} - - - _doScroller: - 37 - 0.1947367936372757 - - - - -2147483392 - {{-100, -100}, {114, 15}} - - 1 - - _doScroller: - 0.77551020408163263 - - - - 2304 - - - - {{1, 0}, {395, 17}} - - - - - 4 - - - - {{-1, -5}, {397, 241}} - - - 530 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - {395, 235} - - NSView - - - - 272 - - - - 4370 - - - - 2304 - - - - 6418 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple PNG pasteboard type - Apple URL pasteboard type - CorePasteboardFlavorType 0x6D6F6F76 - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT Encapsulated PostScript v1.2 pasteboard type - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - NeXT font pasteboard type - NeXT ruler pasteboard type - WebURLsWithTitlesPboardType - public.url - - {380, 16} - - - - - - content - - - - Helvetica - 13 - 16 - - - 4 - - - - - - - - - 134 - - - - 380 - 1 - - - 4003 - 0 - - - - - 6 - System - selectedTextBackgroundColor - - - - 6 - System - selectedTextColor - - - - - - - 1 - MCAwIDEAA - - - {8, -8} - 13 - - - - - - 6 - {775, 1e+07} - {223, 0} - - - - {380, 235} - - - - - - {4, -5} - 1 - - 4 - - - - 256 - {{380, 0}, {15, 220}} - - - _doScroller: - 1 - 0.85256409645080566 - - - - -2147483392 - {{-100, -100}, {87, 18}} - - 1 - - _doScroller: - 1 - 0.94565218687057495 - - - {395, 235} - - - 16 - - - - - - {{0, 245}, {395, 235}} - - NSView - - - {395, 480} - - 3 - SnippetEditorHorizontalDivider - - NO - - - - - - - - - - - 0 - NO - - - {{245, 0}, {395, 480}} - - NSView - - - {640, 480} - - YES - 2 - SnippetEditorVerticalDivider - - NO - - - - - - - - - - - 0 - NO - - - {640, 480} - - - {{0, 0}, {1280, 1002}} - {1.79769e+308, 1.79769e+308} - SnippetEditorWindow - - - - - - - folderArrayController - - - - 152 - - - - managedObjectContext: snippetsController.managedObjectContext - - - - - - managedObjectContext: snippetsController.managedObjectContext - managedObjectContext - snippetsController.managedObjectContext - 2 - - - 153 - - - - managedObjectContext: snippetsController.managedObjectContext - - - - - - managedObjectContext: snippetsController.managedObjectContext - managedObjectContext - snippetsController.managedObjectContext - 2 - - - 157 - - - - snippetArrayController - - - - 160 - - - - delegate - - - - 194 - - - - predicate: filterPredicate - - - - - - predicate: filterPredicate - predicate - filterPredicate - - All - (index.description contains[c] $value) or (title contains[c] $value) or (content contains[c] $value) - - 2 - - - 207 - - - - predicate2: filterPredicate - - - - - - predicate2: filterPredicate - predicate2 - filterPredicate - - Title - title contains[c] $value - - - 2 - - - 208 - - - - predicate3: filterPredicate - - - - - - predicate3: filterPredicate - predicate3 - filterPredicate - - Content - content contains[c] $value - - - 2 - - - 209 - - - - dataSource - - - - 280 - - - - delegate - - - - 281 - - - - nextKeyView - - - - 282 - - - - folderTreeController - - - - 286 - - - - dataSource - - - - 299 - - - - delegate - - - - 300 - - - - folderOutlineView - - - - 301 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - 2 - - - 304 - - - - dataSource - - - - 305 - - - - delegate - - - - 306 - - - - nextKeyView - - - - 309 - - - - snippetTableView - - - - 310 - - - - value: arrangedObjects.title - - - - - - value: arrangedObjects.title - value - arrangedObjects.title - 2 - - - 311 - - - - contentSet: selection.snippets - - - - - - contentSet: selection.snippets - contentSet - selection.snippets - - NSDeletesObjectsOnRemove - - - 2 - - - 320 - - - - value: selection.content - - - - - - value: selection.content - value - selection.content - 2 - - - 321 - - - - addFolder: - - - - 322 - - - - window - - - - 323 - - - - removeFolder: - - - - 324 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 328 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 337 - - - - selectionIndexPaths: selectionIndexPaths - - - - - - selectionIndexPaths: selectionIndexPaths - selectionIndexPaths - selectionIndexPaths - - 2 - - - 339 - - - - remove: - - - - 395 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 396 - - - - contentArray: sourceList - - - - - - contentArray: sourceList - contentArray - sourceList - 2 - - - 426 - - - - addSnippet: - - - - 443 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - 2 - - - 450 - - - - toggleFolderEnabled: - - - - 452 - - - - enabled: arrangedObjects.enabled - - - - - - enabled: arrangedObjects.enabled - enabled - arrangedObjects.enabled - 2 - - - 469 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 471 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - - NSValueTransformerName - NSIsNotNil - - 2 - - - 492 - - - - toggleSnippetEnabled: - - - - 504 - - - - enabled: hasFolders - - - - - - enabled: hasFolders - enabled - hasFolders - 2 - - - 506 - - - - exportSnippets: - - - - 507 - - - - importSnippets: - - - - 508 - - - - nextKeyView - - - - 509 - - - - nextKeyView - - - - 510 - - - - enabled: selection.folder - - - - - - enabled: selection.folder - enabled - selection.folder - - NSValueTransformerName - NSIsNotNil - - 2 - - - 517 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 156 - - - Snippet Array Controller - - - 192 - - - - - - - - - 193 - - - - - - - - 195 - - - - - - - - - - - - - - - 196 - - - - - - - - 197 - - - - - 198 - - - - - 199 - - - - - 201 - - - - - 204 - - - - - - - - 205 - - - - - 213 - - - - - - - - - 214 - - - - - - - - - - 215 - - - - - - - - 216 - - - - - - - - - - - 226 - - - - - - - - - 227 - - - - - - - - 228 - - - - - - - - 238 - - - - - - - - - - 239 - - - - - 240 - - - - - 241 - - - - - 268 - - - - - - - - 269 - - - - - 270 - - - - - - - - 271 - - - - - 272 - - - - - - - - 273 - - - - - 274 - - - - - - - - 275 - - - - - - - - 276 - - - - - - - - - - 277 - - - - - 278 - - - - - 279 - - - - - 217 - - - - - - - - - - 220 - - - - - - 219 - - - - - 218 - - - - - 285 - - - Folder Tree Controller - - - 290 - - - - - - - - - - 291 - - - - - 292 - - - - - 293 - - - - - - - - 295 - - - - - - - - 298 - - - - - 394 - - - - - 441 - - - - - 472 - - - - - 151 - - - Folder Array Controller - - - 229 - - - - - - - - - - - 230 - - - - - 231 - - - - - 232 - - - - - - - - 235 - - - - - - - - 236 - - - - - 233 - - - - - - - IndexedArrayController - com.apple.InterfaceBuilder.CocoaPlugin - IndexedArrayController - com.apple.InterfaceBuilder.CocoaPlugin - {{215, 339}, {640, 480}} - com.apple.InterfaceBuilder.CocoaPlugin - {{215, 339}, {640, 480}} - - com.apple.InterfaceBuilder.CocoaPlugin - {{227, 819}, {616, 0}} - 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.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Add Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - - ToolTip - - ToolTip - - Delete Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - - ToolTip - - ToolTip - - Enable/Disable Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - {{296, 308}, {156, 54}} - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - DeleteSnippet - com.apple.InterfaceBuilder.CocoaPlugin - AddSnippet - com.apple.InterfaceBuilder.CocoaPlugin - CheckSnippet - - - - - - 523 - - - - - ImageAndTextCell - NSTextFieldCell - - IBProjectSource - Source/CocoaExtensions/ImageAndTextCell.h - - - - IndexedArrayController - NSArrayController - - IBProjectSource - Source/IndexedArrayController.h - - - - SnippetEditorController - NSWindowController - - id - id - id - id - id - id - id - - - IndexedArrayController - NSOutlineView - NSTreeController - IndexedArrayController - NSTableView - - - IBProjectSource - Source/SnippetEditorController.h - - - - - - BWAnchoredButton - NSButton - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButton.h - - - - BWAnchoredButtonBar - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButtonBar.h - - - - BWAnchoredButtonCell - NSButtonCell - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButtonCell.h - - - - BWAnchoredPopUpButton - NSPopUpButton - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredPopUpButton.h - - - - BWAnchoredPopUpButtonCell - NSPopUpButtonCell - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredPopUpButtonCell.h - - - - BWSplitView - NSSplitView - - toggleCollapse: - id - - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWSplitView.h - - - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSApplication - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSApplication+BWAdditions.h - - - - NSArrayController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSArrayController.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSController - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSController.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSManagedObjectContext - NSObject - - IBFrameworkSource - CoreData.framework/Headers/NSManagedObjectContext.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMenuItemCell - NSButtonCell - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItemCell.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderCell.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderControl.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRValidator.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSObjectController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSObjectController.h - - - - NSOutlineView - NSTableView - - - - NSPopUpButton - NSButton - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButton.h - - - - NSPopUpButtonCell - NSMenuItemCell - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButtonCell.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSearchField - NSTextField - - IBFrameworkSource - AppKit.framework/Headers/NSSearchField.h - - - - NSSearchFieldCell - NSTextFieldCell - - IBFrameworkSource - AppKit.framework/Headers/NSSearchFieldCell.h - - - - NSSplitView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSSplitView.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableHeaderView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTableHeaderView.h - - - - NSTableView - NSControl - - - - NSText - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSText.h - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSTextView - NSText - - IBFrameworkSource - AppKit.framework/Headers/NSTextView.h - - - - NSToolbar - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbar.h - - - - NSToolbarItem - NSObject - - - - NSTreeController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSTreeController.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSView+BWAdditions.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSWindow+BWAdditions.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - YES - ../ClipMenu.xcodeproj - 3 - - {32, 32} - {32, 32} - {32, 32} - {10, 10} - {8, 8} - {9, 8} - {7, 2} - {8, 8} - {32, 32} - {8, 8} - - - diff --git a/Info.plist b/Info.plist deleted file mode 100644 index 64cc323..0000000 --- a/Info.plist +++ /dev/null @@ -1,53 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleGetInfoString - 0.4.4a13, © 2008-2010 Naotaka Morimoto. - CFBundleIconFile - ClipMenu3 - CFBundleIdentifier - com.naotaka.ClipMenu - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.4.4a13 - CFBundleSignature - ???? - CFBundleVersion - 0.4.4a13 - LSMinimumSystemVersion - 10.5.0 - LSMinimumSystemVersionByArchitecture - - i386 - 10.5.0 - ppc - 10.5.0 - ppc64 - 10.6.0 - x86_64 - 10.6.0 - - LSUIElement - 1 - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - SUFeedURL - http://feeds.feedburner.com/clipmenu-appcast - SUPreReleaseFeedURL - http://feeds.feedburner.com/clipmenu-pre-appcast - SUPublicDSAKeyFile - dsa_pub.pem - - diff --git a/Japanese.lproj/InfoPlist.strings b/Japanese.lproj/InfoPlist.strings deleted file mode 100644 index 1bdb009..0000000 Binary files a/Japanese.lproj/InfoPlist.strings and /dev/null differ diff --git a/Japanese.lproj/Localizable.strings b/Japanese.lproj/Localizable.strings deleted file mode 100644 index a028ec5..0000000 --- a/Japanese.lproj/Localizable.strings +++ /dev/null @@ -1,195 +0,0 @@ -/* Hot Keys: Key Combo text for 'empty' combo */ -"(None)" = "(None)"; - -/* No comment provided by engineer. */ -"About ClipMenu" = "ClipMenu について"; - -/* No comment provided by engineer. */ -"Action" = "アクション"; - -/* No comment provided by engineer. */ -"Add" = "追加"; - -/* No comment provided by engineer. */ -"Are you sure you want to clear your clipboard history?" = "本当にクリップボード履歴をクリアしますか?"; - -/* No comment provided by engineer. */ -"Built-in" = "内蔵"; - -/* No comment provided by engineer. */ -"Cancel" = "キャンセル"; - -/* No comment provided by engineer. */ -"Case" = "Case"; - -/* No comment provided by engineer. */ -"Clear History" = "履歴をクリア"; - -/* No comment provided by engineer. */ -"Could not save changes while quitting. Quit anyway?" = "変更点を保存できませんでした。それでも終了しますか?"; - -/* No comment provided by engineer. */ -"Could not save your clipboard history to file." = "クリップボード履歴をファイルに保存できませんでした"; - -/* No comment provided by engineer. */ -"Could not write document out..." = "ドキュメントの書き出しができません..."; - -/* No comment provided by engineer. */ -"Don't Launch" = "起動しない"; - -/* No comment provided by engineer. */ -"Edit Snippets..." = "スニペットを編集..."; - -/* No comment provided by engineer. */ -"Error" = "エラー"; - -/* No comment provided by engineer. */ -"Failed to evaluate script" = "スクリプトの実行に失敗しました"; - -/* No comment provided by engineer. */ -"Failed to export history" = "履歴の書き出しに失敗しました"; - -/* No comment provided by engineer. */ -"Failed to parse XML file" = "XMLファイルの解析に失敗しました"; - -/* No comment provided by engineer. */ -"General" = "一般"; - -/* No comment provided by engineer. */ -"History" = "履歴"; - -/* No comment provided by engineer. */ -"JavaScript" = "JavaScript"; - -/* No comment provided by engineer. */ -"Launch ClipMenu on system startup?" = "システム起動時にClipMenuを起動しますか?"; - -/* No comment provided by engineer. */ -"Launch on system startup" = "起動する"; - -/* No comment provided by engineer. */ -"Menu" = "メニュー"; - -/* No comment provided by engineer. */ -"None" = "なし"; - -/* No comment provided by engineer. */ -"OK" = "OK"; - -/* No comment provided by engineer. */ -"Other..." = "その他..."; - -/* No comment provided by engineer. */ -"Paste as File Path" = "ファイルパスとしてペースト"; - -/* No comment provided by engineer. */ -"Paste as HFS File Path" = "HFSファイルパスとしてペースト"; - -/* No comment provided by engineer. */ -"Paste as Plain Text" = "プレーンテキストとしてペースト"; - -/* No comment provided by engineer. */ -"Paste the clip as HFS File Path" = "HFSファイルパスとしてペースト"; - -/* No comment provided by engineer. */ -"Paste the clip as Plain Text" = "プレーンテキストとしてペースト"; - -/* No comment provided by engineer. */ -"Paste the clip as POSIX File Path" = "POSIXファイルパスとしてペースト"; - -/* No comment provided by engineer. */ -"Pop up Action Menu" = "アクションメニューをポップアップ"; - -/* No comment provided by engineer. */ -"Preferences..." = "環境設定..."; - -/* No comment provided by engineer. */ -"Quit anyway" = "それでも終了"; - -/* No comment provided by engineer. */ -"Quit ClipMenu" = "ClipMenuを終了"; - -/* No comment provided by engineer. */ -"Remove" = "削除"; - -/* No comment provided by engineer. */ -"Remove the clip from the clipboard history" = "クリップボード履歴から削除"; - -/* No comment provided by engineer. */ -"Script Error" = "スクリプトエラー"; - -/* No comment provided by engineer. */ -"Script error has occurred" = "スクリプトエラーが起こりました"; - -/* No comment provided by engineer. */ -"Script Exception Raised" = "スクリプトで例外が発生しました"; - -/* No comment provided by engineer. */ -"Select" = "選択"; - -/* No comment provided by engineer. */ -"Shortcuts" = "ショートカット"; - -/* No comment provided by engineer. */ -"Snippet" = "スニペット"; - -/* No comment provided by engineer. */ -"Snippets" = "スニペット"; - -/* No comment provided by engineer. */ -"The script you selected does not exist" = "選択したスクリプトが見つかりません"; - -/* No comment provided by engineer. */ -"Trim" = "Trim"; - -/* No comment provided by engineer. */ -"Type" = "対応形式"; - -/* No comment provided by engineer. */ -"Unable to end editing" = "編集できません"; - -/* No comment provided by engineer. */ -"Unable to load script" = "スクリプトを読み込めません"; - -/* No comment provided by engineer. */ -"untitled snippet" = "untitled snippet"; - -/* No comment provided by engineer. */ -"Updates" = "アップデート"; - -/* No comment provided by engineer. */ -"You can change this setting in the Preferences if you want." = "この設定は、いつでも変更できます。"; - -/* No comment provided by engineer. */ -"Your script file does not exist." = "スクリプトファイルが見つかりませんでした"; - -/* JavaScript actions */ -"Collapse Spaces" = "空白を縮める"; -"Reverse" = "逆順にする"; - -"Japanese" = "日本語"; -"Convert Hankaku alphanumeric characters to Zenkaku" = "半角英数字 → 全角"; -"Convert Zenkaku alphanumeric characters to Hankaku" = "全角英数字 → 半角"; -"Convert Hankaku katakana to Zenkaku katakana" = "半角カタカナ → 全角"; -"Convert Zenkaku katakana to Hankaku katakana" = "全角カタカナ → 半角"; -"Convert Hiragana to Katakana" = "ひらがな → カタカナ"; -"Convert Katakana to Hiragana" = "カタカナ → ひらがな"; - -"Crypt" = "暗号"; -"Calculate MD5 hash" = "MD5ハッシュを計算"; -"Calculate SHA-1 hash" = "SHA-1ハッシュを計算"; -"Decode from Base64" = "Base64からデコード"; -"Encode to Base64" = "Base64にエンコード"; - -"Convert Character to Decimal" = "文字 → 数値文字参照"; -"Convert Decimal to Character" = "数値文字参照 → 文字"; -"Convert Markdown to HTML" = "Markdown → HTML"; -"Decode URI component" = "URIコンポーネントをデコード"; -"Encode URI component" = "URIコンポーネントをエンコード"; -"Escape HTML characters" = "HTML文字実体参照にエスケープ"; -"Unescape HTML characters" = "HTML文字実体参照からアンエスケープ"; -"Strip Tags" = "タグを除去"; -"Surround with Tags..." = "タグで囲む..."; - -"Surround with" = "囲む"; -"Surround with (Japanese)" = "囲む(全角)"; diff --git a/Japanese.lproj/Preferences.strings b/Japanese.lproj/Preferences.strings deleted file mode 100644 index cc75595..0000000 --- a/Japanese.lproj/Preferences.strings +++ /dev/null @@ -1,502 +0,0 @@ - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "538"; */ -"538.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "9"; ObjectID = "539"; */ -"539.title" = "9"; - -/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "612"; */ -"612.headerCell.title" = "名前"; - -/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "624"; */ -"624.headerCell.title" = "名前"; - -/* Class = "NSTextFieldCell"; title = "Time interval to observe the clipboard:"; ObjectID = "686"; */ -"686.title" = "クリップボードを監視する間隔:"; - -/* Class = "NSTextFieldCell"; title = "sec."; ObjectID = "689"; */ -"689.title" = "秒"; - -/* Class = "NSButtonCell"; title = "Input \"⌘ + V\" after menu item selection"; ObjectID = "690"; */ -"690.title" = "メニュー項目選択後に \"⌘ + V\" を入力"; - -/* Class = "NSButtonCell"; title = "Add a menu item to clear clipboard history"; ObjectID = "701"; */ -"701.title" = "履歴をクリアするメニュー項目を追加"; - -/* Class = "NSButtonCell"; title = "Show alert panel before clear history"; ObjectID = "702"; */ -"702.title" = "履歴クリアの前に警告パネルを表示"; - -/* Class = "NSTextFieldCell"; title = "Number of characters in the menu:"; ObjectID = "703"; */ -"703.title" = "メニューに表示する文字数:"; - -/* Class = "NSButtonCell"; title = "Menu items' title starts with 0"; ObjectID = "705"; */ -"705.title" = "メニュー項目のタイトルを 0 で始める"; - -/* Class = "NSButtonCell"; title = "Mark menu items with numbers"; ObjectID = "706"; */ -"706.title" = "メニュー項目の先頭に数字を付加"; - -/* Class = "NSTextFieldCell"; title = "Width:"; ObjectID = "707"; */ -"707.title" = "幅:"; - -/* Class = "NSTextFieldCell"; title = "Height:"; ObjectID = "708"; */ -"708.title" = "高さ:"; - -/* Class = "NSTextFieldCell"; title = "pixel"; ObjectID = "711"; */ -"711.title" = "pixel"; - -/* Class = "NSTextFieldCell"; title = "pixel"; ObjectID = "712"; */ -"712.title" = "pixel"; - -/* Class = "NSButtonCell"; title = "Show Image"; ObjectID = "737"; */ -"737.title" = "画像を表示"; - -/* Class = "NSTextFieldCell"; title = "pt"; ObjectID = "742"; */ -"742.title" = "pt"; - -/* Class = "NSButtonCell"; title = "Add key equivalents to numeric keys"; ObjectID = "743"; */ -"743.title" = "数字キーを使ったショートカットを追加"; - -/* Class = "NSButtonCell"; title = "Change font size in the menu"; ObjectID = "744"; */ -"744.title" = "メニューのフォントサイズを変更"; - -/* Class = "NSButtonCell"; title = "Remove"; ObjectID = "746"; */ -"746.title" = "削除"; - -/* Class = "NSButtonCell"; title = "Folder"; ObjectID = "747"; */ -"747.title" = "フォルダ"; - -/* Class = "NSButtonCell"; title = "<<"; ObjectID = "748"; */ -"748.title" = "<<"; - -/* Class = "NSTextFieldCell"; title = "name"; ObjectID = "750"; */ -"750.title" = "名前"; - -/* Class = "NSTextFieldCell"; title = "Name:"; ObjectID = "752"; */ -"752.title" = "名前:"; - -/* Class = "NSSegmentedCell"; 755.labels[0] = "Built-in"; ObjectID = "755"; */ -"755.labels[0]" = "内蔵"; - -/* Class = "NSSegmentedCell"; 755.labels[1] = "Scripts"; ObjectID = "755"; */ -"755.labels[1]" = "Scripts"; - -/* Class = "NSSegmentedCell"; 755.labels[2] = "User's"; ObjectID = "755"; */ -"755.labels[2]" = "User's"; - -/* Class = "NSButtonCell"; title = "Enable Action"; ObjectID = "756"; */ -"756.title" = "アクションを使用する"; - -/* Class = "NSButtonCell"; title = "Invoke an action immediately if only one action was registered"; ObjectID = "757"; */ - -"757.title" = "登録したアクションが一つだけなら、即座にアクションを実行する"; - -/* Class = "NSButtonCell"; title = "Launch on Login"; ObjectID = "768"; */ -"768.title" = "ログイン時に起動"; - -/* Class = "NSBox"; title = "Icon"; ObjectID = "922"; */ -"922.title" = "アイコン"; - -/* Class = "NSTextFieldCell"; title = "pixel"; ObjectID = "927"; */ -"927.title" = "pixel"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "929"; */ -"929.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "16"; ObjectID = "930"; */ -"930.title" = "16"; - -/* Class = "NSMenuItem"; title = "32"; ObjectID = "931"; */ -"931.title" = "32"; - -/* Class = "NSMenuItem"; title = "48"; ObjectID = "932"; */ -"932.title" = "48"; - -/* Class = "NSTextFieldCell"; title = "Icon size:"; ObjectID = "933"; */ -"933.title" = "アイコンの大きさ:"; - -/* Class = "NSButtonCell"; title = "Show Icon in the Menu"; ObjectID = "934"; */ -"934.title" = "メニューにアイコンを表示"; - -/* Class = "NSTextFieldCell"; title = "Plain Text:"; ObjectID = "959"; */ -"959.title" = "プレーンテキスト:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "961"; */ -"961.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "962"; */ -"962.title" = "タイプコード"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "963"; */ -"963.title" = "ファイル拡張子"; - -/* Class = "NSTextFieldCell"; title = "RTF:"; ObjectID = "965"; */ -"965.title" = "RTF:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "967"; */ -"967.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "968"; */ -"968.title" = "ファイル拡張子"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "969"; */ -"969.title" = "タイプコード"; - -/* Class = "NSTextFieldCell"; title = "RTFD:"; ObjectID = "971"; */ -"971.title" = "RTFD:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "973"; */ -"973.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "974"; */ -"974.title" = "ファイル拡張子"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "975"; */ -"975.title" = "タイプコード"; - -/* Class = "NSTextFieldCell"; title = "PDF:"; ObjectID = "977"; */ -"977.title" = "PDF:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "979"; */ -"979.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "980"; */ -"980.title" = "ファイル拡張子"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "981"; */ -"981.title" = "タイプコード"; - -/* Class = "NSTextFieldCell"; title = "Filenames:"; ObjectID = "983"; */ -"983.title" = "ファイル名:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "985"; */ -"985.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "986"; */ -"986.title" = "タイプコード"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "987"; */ -"987.title" = "ファイル拡張子"; - -/* Class = "NSTextFieldCell"; title = "URL:"; ObjectID = "989"; */ -"989.title" = "URL:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "991"; */ -"991.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "992"; */ -"992.title" = "タイプコード"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "993"; */ -"993.title" = "ファイル拡張子"; - -/* Class = "NSTextFieldCell"; title = "TIFF:"; ObjectID = "995"; */ -"995.title" = "TIFF:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "997"; */ -"997.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "998"; */ -"998.title" = "タイプコード"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "999"; */ -"999.title" = "ファイル拡張子"; - -/* Class = "NSTextFieldCell"; title = "PICT:"; ObjectID = "1001"; */ -"1001.title" = "PICT:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1003"; */ -"1003.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "File type code"; ObjectID = "1004"; */ -"1004.title" = "タイプコード"; - -/* Class = "NSMenuItem"; title = "File extension"; ObjectID = "1005"; */ -"1005.title" = "ファイル拡張子"; - -/* Class = "NSTextFieldCell"; title = "Number of items place inline:"; ObjectID = "1028"; */ -"1028.title" = "インライン表示する項目の数:"; - -/* Class = "NSTextFieldCell"; title = "Number of items place inside a folder:"; ObjectID = "1034"; */ -"1034.title" = "フォルダに内包する項目の数:"; - -/* Class = "NSButtonCell"; title = "Show labels to indicate item types"; ObjectID = "1044"; */ -"1044.title" = "種類を示すラベルを表示"; - -/* Class = "NSButtonCell"; title = "Save clipboard history on quit"; ObjectID = "1047"; */ -"1047.title" = "終了時にクリップボード履歴を保存"; - -/* Class = "NSTabViewItem"; label = "Icon"; ObjectID = "1084"; */ -"1084.label" = "アイコン"; - -/* Class = "NSTabViewItem"; label = "Type"; ObjectID = "1086"; */ -"1086.label" = "対応形式"; - -/* Class = "NSBox"; title = "Select clipboard types to store:"; ObjectID = "1088"; */ -"1088.title" = "保存するクリップボードの種類を選択:"; - -/* Class = "NSButtonCell"; title = "Plain Text"; ObjectID = "1097"; */ -"1097.title" = "プレーンテキスト"; - -/* Class = "NSButtonCell"; title = "Rich Text Format (RTF)"; ObjectID = "1098"; */ -"1098.title" = "Rich Text Format (RTF)"; - -/* Class = "NSButtonCell"; title = "PDF"; ObjectID = "1099"; */ -"1099.title" = "PDF"; - -/* Class = "NSButtonCell"; title = "Filenames"; ObjectID = "1100"; */ -"1100.title" = "ファイル名"; - -/* Class = "NSButtonCell"; title = "URL"; ObjectID = "1101"; */ -"1101.title" = "URL"; - -/* Class = "NSButtonCell"; title = "TIFF Image"; ObjectID = "1102"; */ -"1102.title" = "TIFF画像"; - -/* Class = "NSButtonCell"; title = "PICT Image"; ObjectID = "1103"; */ -"1103.title" = "PICT画像"; - -/* Class = "NSButtonCell"; title = "Rich Text Format Directory (RTFD)"; ObjectID = "1104"; */ -"1104.title" = "Rich Text Format Directory (RTFD)"; - -/* Class = "NSBox"; title = "Box"; ObjectID = "1124"; */ -"1124.title" = "Box"; - -/* Class = "NSButtonCell"; title = "Show tool tip on a menu item"; ObjectID = "1157"; */ -"1157.title" = "メニュー項目上にツールチップを表示"; - -/* Class = "NSTextFieldCell"; title = "Max clipboard history size:"; ObjectID = "1164"; */ -"1164.title" = "記憶する履歴の数:"; - -/* Class = "NSTextFieldCell"; title = "items"; ObjectID = "1171"; */ -"1171.title" = "項目"; - -/* Class = "NSTextFieldCell"; title = "chars"; ObjectID = "1173"; */ -"1173.title" = "文字"; - -/* Class = "NSTextFieldCell"; title = "items"; ObjectID = "1175"; */ -"1175.title" = "項目"; - -/* Class = "NSTextFieldCell"; title = "items"; ObjectID = "1177"; */ -"1177.title" = "項目"; - -/* Class = "NSTextFieldCell"; title = "Control + Click:"; ObjectID = "1190"; */ -"1190.title" = "Control + クリック:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1193"; */ -"1193.title" = "OtherViews"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1208"; */ -"1208.title" = "OtherViews"; - -/* Class = "NSTextFieldCell"; title = "Shift + Click:"; ObjectID = "1209"; */ -"1209.title" = "Shift + クリック:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1214"; */ -"1214.title" = "OtherViews"; - -/* Class = "NSTextFieldCell"; title = "Option + Click:"; ObjectID = "1215"; */ -"1215.title" = "Option + クリック:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1220"; */ -"1220.title" = "OtherViews"; - -/* Class = "NSTextFieldCell"; title = "Command + Click:"; ObjectID = "1221"; */ -"1221.title" = "Command + クリック:"; - -/* Class = "NSBox"; title = "Modifier key + Click behaviors"; ObjectID = "1223"; */ -"1223.title" = "履歴メニュー項目上での、修飾キー + クリック の動作"; - -/* Class = "NSBox"; title = "Box"; ObjectID = "1224"; */ -"1224.title" = "Box"; - -/* Class = "NSTextFieldCell"; title = "Action Menu"; ObjectID = "1232"; */ -"1232.title" = "アクションメニュー"; - -/* Class = "NSButtonCell"; title = "Fit to the icon size"; ObjectID = "1238"; */ -"1238.title" = "アイコンの大きさに合わせる"; - -/* Class = "NSButtonCell"; title = "Select:"; ObjectID = "1239"; */ -"1239.title" = "選択:"; - -/* Class = "NSButtonCell"; title = "Radio"; ObjectID = "1240"; */ -"1240.title" = "Radio"; - -/* Class = "NSTextFieldCell"; title = "Max length of tool tip string:"; ObjectID = "1256"; */ -"1256.title" = "ツールチップに表示する文字列の長さ:"; - -/* Class = "NSTextFieldCell"; title = "chars"; ObjectID = "1259"; */ -"1259.title" = "文字"; - -/* Class = "NSTextFieldCell"; title = "Clipboard History"; ObjectID = "1275"; */ -"1275.title" = "クリップボード履歴"; - -/* Class = "NSTextFieldCell"; title = "Appearance"; ObjectID = "1277"; */ -"1277.title" = "アピアランス"; - -/* Class = "NSTextFieldCell"; title = "Time interval"; ObjectID = "1279"; */ -"1279.title" = "時間間隔"; - -/* Class = "NSTextFieldCell"; title = "Autosaving clipboard history:"; ObjectID = "1281"; */ -"1281.title" = "クリップボード履歴を自動保存:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1284"; */ -"1284.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "Never"; ObjectID = "1285"; */ -"1285.title" = "しない"; - -/* Class = "NSMenuItem"; title = "Every minute"; ObjectID = "1286"; */ -"1286.title" = "毎分"; - -/* Class = "NSMenuItem"; title = "Every 5 minutes"; ObjectID = "1287"; */ -"1287.title" = "5 分ごと"; - -/* Class = "NSMenuItem"; title = "Every 30 minutes"; ObjectID = "1289"; */ -"1289.title" = "30 分ごと"; - -/* Class = "NSMenuItem"; title = "Every 10 minutes"; ObjectID = "1290"; */ -"1290.title" = "10 分ごと"; - -/* Class = "NSMenuItem"; title = "Every hour"; ObjectID = "1291"; */ -"1291.title" = "毎時"; - -/* Class = "NSMenuItem"; title = "Every 3 hours"; ObjectID = "1292"; */ -"1292.title" = "3 時間ごと"; - -/* Class = "NSMenuItem"; title = "Every 6 hours"; ObjectID = "1293"; */ -"1293.title" = "6 時間ごと"; - -/* Class = "NSMenuItem"; title = "Every 12 hours"; ObjectID = "1294"; */ -"1294.title" = "12 時間ごと"; - -/* Class = "NSMenuItem"; title = "Every day"; ObjectID = "1295"; */ -"1295.title" = "毎日"; - -/* Class = "NSTextFieldCell"; title = "0"; ObjectID = "1300"; */ -"1300.title" = "0"; - -/* Class = "NSTextFieldCell"; title = "Behavior"; ObjectID = "1305"; */ -"1305.title" = "動作"; - -/* Class = "NSTextFieldCell"; title = "Status Bar icon style:"; ObjectID = "1316"; */ -"1316.title" = "ステータスバー・アイコン:"; - -/* Class = "NSMenuItem"; title = "None"; ObjectID = "1318"; */ -"1318.title" = "なし"; - -/* Class = "NSButtonCell"; title = "Check Now"; ObjectID = "1331"; */ -"1331.title" = "今すぐチェック"; - -/* Class = "NSButtonCell"; title = "Automatically check for updates:"; ObjectID = "1337"; */ -"1337.title" = "アップデートを自動的にチェック:"; - -/* Class = "NSMenuItem"; title = "Daily"; ObjectID = "1353"; */ -"1353.title" = "毎日"; - -/* Class = "NSMenuItem"; title = "Weekly"; ObjectID = "1354"; */ -"1354.title" = "毎週"; - -/* Class = "NSMenuItem"; title = "Monthly"; ObjectID = "1355"; */ -"1355.title" = "毎月"; - -/* Class = "NSBox"; title = "Shortcuts"; ObjectID = "1366"; */ -"1366.title" = "ショートカット"; - -/* Class = "NSTextFieldCell"; title = "Main Menu:"; ObjectID = "1371"; */ -"1371.title" = "メインメニュー:"; - -/* Class = "NSTextFieldCell"; title = "History Menu:"; ObjectID = "1372"; */ -"1372.title" = "履歴メニュー:"; - -/* Class = "NSTextFieldCell"; title = "Export clipboard history as:"; ObjectID = "1380"; */ -"1380.title" = "クリップボード履歴を書き出す:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1383"; */ -"1383.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "Single file"; ObjectID = "1384"; */ -"1384.title" = "単一ファイル"; - -/* Class = "NSMenuItem"; title = "Multiple files"; ObjectID = "1385"; */ -"1385.title" = "複数ファイル"; - -/* Class = "NSButtonCell"; title = "Export..."; ObjectID = "1390"; */ -"1390.title" = "書き出し..."; - -/* Class = "NSTextFieldCell"; title = "separator:"; ObjectID = "1396"; */ -"1396.title" = "セパレータ:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1403"; */ -"1403.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "LF"; ObjectID = "1404"; */ -"1404.title" = "LF"; - -/* Class = "NSMenuItem"; title = "CR+LF"; ObjectID = "1405"; */ -"1405.title" = "CR+LF"; - -/* Class = "NSMenuItem"; title = "CR"; ObjectID = "1406"; */ -"1406.title" = "CR"; - -/* Class = "NSMenuItem"; title = "Tab"; ObjectID = "1407"; */ -"1407.title" = "タブ"; - -/* Class = "NSMenuItem"; title = "None"; ObjectID = "1408"; */ -"1408.title" = "なし"; - -/* Class = "NSMenuItem"; title = "Space"; ObjectID = "1410"; */ -"1410.title" = "空白"; - -/* Class = "NSTextFieldCell"; title = "Sort history order by:"; ObjectID = "1417"; */ -"1417.title" = "履歴のソート順:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1420"; */ -"1420.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "Date Created"; ObjectID = "1421"; */ -"1421.title" = "作成日"; - -/* Class = "NSMenuItem"; title = "Last Used"; ObjectID = "1422"; */ -"1422.title" = "最終使用日"; - -/* Class = "NSButtonCell"; title = "Include pre-releases"; ObjectID = "1426"; */ -"1426.title" = "プレリリース版も含める"; - -/* Class = "NSTextFieldCell"; title = "Exclude Applications"; ObjectID = "1446"; */ -"1446.title" = "除外アプリケーション"; - -/* Class = "NSButtonCell"; title = "Define Exclude Options..."; ObjectID = "1448"; */ -"1448.title" = "除外設定..."; - -/* Class = "NSPanel"; title = "Exclude Apps"; ObjectID = "1451"; */ -"1451.title" = "除外アプリケーション"; - -/* Class = "NSButtonCell"; title = "Done"; ObjectID = "1454"; */ -"1454.title" = "完了"; - -/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "1456"; */ -"1456.title" = "キャンセル"; - -/* Class = "NSTextFieldCell"; title = "Exclude these applications:"; ObjectID = "1459"; */ -"1459.title" = "除外するアプリケーション:"; - -/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "1471"; */ -"1471.title" = "Text Cell"; - -/* Class = "NSTextFieldCell"; title = "Snippets Menu:"; ObjectID = "1503"; */ -"1503.title" = "スニペットメニュー:"; - -/* Class = "NSTextFieldCell"; title = "Snippets' position:"; ObjectID = "1509"; */ -"1509.title" = "スニペットの表示位置:"; - -/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "1511"; */ -"1511.title" = "OtherViews"; - -/* Class = "NSMenuItem"; title = "None"; ObjectID = "1512"; */ -"1512.title" = "表示しない"; - -/* Class = "NSMenuItem"; title = "Below the clipboard history"; ObjectID = "1513"; */ -"1513.title" = "クリップボード履歴の下"; - -/* Class = "NSMenuItem"; title = "Above the clipboard history"; ObjectID = "1514"; */ -"1514.title" = "クリップボード履歴の上"; diff --git a/Japanese.lproj/Preferences.xib b/Japanese.lproj/Preferences.xib deleted file mode 100644 index 784a4a5..0000000 --- a/Japanese.lproj/Preferences.xib +++ /dev/null @@ -1,10935 +0,0 @@ - - - - 1050 - 10F569 - 788 - 1038.29 - 461.00 - - 788 - 1 - - - - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - - - - - PrefsWindowController - - - FirstResponder - - - NSApplication - - - YES - - - ActionNodeController - - - - nodeTitle - action.path - action.type - - ActionNode - YES - - YES - YES - YES - children - isLeaf - - - - nodeTitle - maxHistorySize - - ActionNode - YES - - YES - YES - YES - children - isLeaf - - - SUUpdater - - - - name - - YES - - YES - YES - YES - YES - YES - - - - 256 - - - - 268 - {{129, 12}, {200, 32}} - - YES - - 67239424 - 134217728 - 除外設定... - - LucidaGrande - 13 - 1044 - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{49, 48}, {210, 17}} - - YES - - 68288064 - 272634880 - 除外アプリケーション - - LucidaGrande-Bold - 13 - 16 - - - - 6 - System - controlColor - - 3 - MC42NjY2NjY2NjY3AA - - - - 6 - System - controlTextColor - - 3 - MAA - - - - - - - 268 - {{248, 329}, {152, 22}} - - YES - - -2076049856 - 133120 - - LucidaGrande - 11 - 3100 - - - 109199615 - 129 - - - 400 - 75 - - - 最終使用日 - - 1048576 - 2147483647 - 1 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - 作成日 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - - 1 - 1 - YES - YES - 2 - - - - - 268 - {{49, 333}, {197, 17}} - - YES - - 68288064 - 272630784 - 履歴のソート順: - - - - - - - - - 268 - {{248, 235}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - LF - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - - CR+LF - - 1048576 - 2147483647 - - - _popUpItemAction: - 2 - - - - - CR - - 1048576 - 2147483647 - - - _popUpItemAction: - 3 - - - - - タブ - - 2147483647 - - - _popUpItemAction: - 4 - - - - - 空白 - - 2147483647 - - - _popUpItemAction: - 5 - - - - - なし - - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{60, 240}, {179, 14}} - - YES - - 68288064 - 71435264 - セパレータ: - - - - - - - - - 268 - {{298, 203}, {105, 32}} - - YES - - 67239424 - 134217728 - 書き出し... - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{248, 260}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - 単一ファイル - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1 - - - YES - - OtherViews - - - - - 複数ファイル - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{49, 264}, {197, 17}} - - YES - - 68288064 - 272630784 - クリップボード履歴を書き出す: - - - - - - - - - 268 - {{49, 158}, {197, 17}} - - YES - - 68288064 - 272630784 - ステータスバー・アイコン: - - - - - - - - - 268 - {{248, 151}, {71, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 129 - - - 400 - 75 - - - - - 1048576 - 2147483647 - 1 - - NSImage - StatusMenuIcon - - - - _popUpItemAction: - 1 - - - YES - - - - - - - - - 2147483647 - - NSImage - StatusMenuIconBySuphiAksoy - - - - _popUpItemAction: - 13 - - - - - - - 1048576 - 2147483647 - - NSImage - StatusMenuIconFirst - - - - _popUpItemAction: - 2 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-bw-left - - - - _popUpItemAction: - 3 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-bw-right - - - - _popUpItemAction: - 4 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-color-left - - - - _popUpItemAction: - 5 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors1-color-right - - - - _popUpItemAction: - 6 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-diagonal-bw - - - - _popUpItemAction: - 7 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-diagonal-color - - - - _popUpItemAction: - 8 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-bw-left - - - - _popUpItemAction: - 9 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-bw-right - - - - _popUpItemAction: - 10 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-color-left - - - - _popUpItemAction: - 11 - - - - - - - 2147483647 - - NSImage - StatusMenuIconByDaveUlrich-scissors2-color-right - - - - _popUpItemAction: - 12 - - - - - なし - - 2147483647 - - - _popUpItemAction: - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{49, 457}, {210, 17}} - - YES - - 68288064 - 272634880 - 動作 - - - - - - - - - 256 - {{49, 358}, {253, 17}} - - YES - - 67239424 - 272629760 - 記憶する履歴の数: - - - - - - - - - 256 - {{312, 356}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - 0 - 1 - NO - YES - 1 - AQAAAAAAAAAAAAAAAAAAAA - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - 0 - 0 - YES - NO - 1 - AAAAAAAAAAAAAAAAAAAAAA - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - textColor - - - - - - - 268 - {{361, 356}, {39, 14}} - - YES - - 68288064 - 272761856 - 項目 - - - - - - - - - 268 - {{321, 77}, {38, 17}} - - YES - - 68288064 - 71308288 - - - LucidaGrande - 13 - 16 - - - - - - - - - - - -∞ - - - +∞ - - #,##0.### - #,##0.### - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - YES - NO - YES - - - - - - - - - 268 - {{248, 306}, {152, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - 30 分ごと - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 1800 - - - YES - - OtherViews - - - - 毎分 - - 1048576 - 2147483647 - - - _popUpItemAction: - 60 - - - - - 5 分ごと - - 1048576 - 2147483647 - - - _popUpItemAction: - 300 - - - - - 10 分ごと - - 1048576 - 2147483647 - - - _popUpItemAction: - 600 - - - - - - 毎時 - - 1048576 - 2147483647 - - - _popUpItemAction: - 3600 - - - - - 3 時間ごと - - 1048576 - 2147483647 - - - _popUpItemAction: - 10800 - - - - - 6 時間ごと - - 1048576 - 2147483647 - - - _popUpItemAction: - 21600 - - - - - 12 時間ごと - - 1048576 - 2147483647 - - - _popUpItemAction: - 43200 - - - - - 毎日 - - 1048576 - 2147483647 - - - _popUpItemAction: - 86400 - - - - - しない - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - 3 - 1 - YES - YES - 2 - - - - - 268 - {{49, 311}, {197, 17}} - - YES - - 68288064 - 272630784 - クリップボード履歴を自動保存: - - - - - - - - - 268 - {{49, 129}, {210, 17}} - - YES - - 68288064 - 272634880 - 時間間隔 - - - - - - - - - 268 - {{49, 183}, {210, 17}} - - YES - - 68288064 - 272634880 - アピアランス - - - - - - - - - 268 - {{49, 386}, {210, 17}} - - YES - - 68288064 - 272634880 - クリップボード履歴 - - - - - - - - - 256 - {{49, 104}, {361, 17}} - - YES - - 67239424 - 272629760 - クリップボードを監視する間隔: - - - - - - - - - 256 - {{52, 76}, {264, 18}} - - YES - - 67239424 - 131072 - - - - - Helvetica - 12 - 16 - - - 1 - 0.0 - 1 - 0.0 - 5 - 1 - YES - NO - - - - - 256 - {{361, 77}, {28, 14}} - - YES - - 67239424 - 272629760 - - - - - - - - - - 256 - {{50, 413}, {359, 18}} - - YES - - 67239424 - 0 - メニュー項目選択後に "⌘ + V" を入力 - - - 1211912703 - 2 - - NSImage - NSSwitch - - - NSSwitch - - - - 200 - 25 - - - - - 268 - {{50, 433}, {297, 18}} - - YES - - 67239424 - 0 - ログイン時に起動 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 287}, {359, 18}} - - YES - - 67239424 - 0 - 終了時にクリップボード履歴を保存 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {460, 494} - - NSView - - NSResponder - - - - 256 - - - - 268 - {{47, 20}, {150, 17}} - - YES - - 68288064 - 272630784 - スニペットの表示位置: - - - - - - - - - 268 - {{203, 16}, {207, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - - クリップボード履歴の上 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - OtherViews - - - - 表示しない - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - クリップボード履歴の下 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 1 - 1 - YES - YES - 2 - - - - - 256 - {{50, 231}, {359, 18}} - - YES - - 67239424 - 0 - 履歴をクリアするメニュー項目を追加 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{63, 211}, {347, 18}} - - YES - - 67239424 - 0 - 履歴クリアの前に警告パネルを表示 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{49, 337}, {276, 17}} - - YES - - 67239424 - 272629760 - メニューに表示する文字数: - - - - - - - - - 256 - {{322, 335}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - 0 - 1 - NO - YES - 1 - AQAAAAAAAAAAAAAAAAAAAA - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{63, 291}, {273, 18}} - - YES - - 67239424 - 0 - メニュー項目のタイトルを 0 で始める - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{50, 311}, {297, 18}} - - YES - - 67239424 - 0 - メニュー項目の先頭に数字を付加 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{67, 45}, {51, 17}} - - YES - - 67239424 - 272629760 - 幅: - - - - - - - - - 256 - {{212, 45}, {51, 17}} - - YES - - 67239424 - 272629760 - 高さ: - - - - - - - - - 256 - {{268, 43}, {43, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{117, 43}, {43, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{165, 45}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - - 256 - {{316, 45}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - - 256 - {{50, 71}, {297, 18}} - - YES - - 67239424 - 0 - 画像を表示 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{50, 271}, {297, 18}} - - YES - - 67239424 - 0 - 数字キーを使ったショートカットを追加 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{49, 394}, {268, 17}} - - YES - - 68288064 - 272630784 - インライン表示する項目の数: - - - - - - - - - 268 - {{322, 392}, {44, 22}} - - YES - - -1804468671 - -2076179456 - - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 268 - {{49, 367}, {268, 17}} - - YES - - 68288064 - 272630784 - フォルダに内包する項目の数: - - - - - - - - - 268 - {{322, 365}, {44, 22}} - - YES - - -1804468671 - -2076179456 - - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 256 - {{50, 145}, {297, 18}} - - YES - - 67239424 - 0 - メニューのフォントサイズを変更 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 251}, {301, 18}} - - YES - - 67239424 - 0 - 種類を示すラベルを表示 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{50, 189}, {301, 18}} - - YES - - 67239424 - 0 - メニュー項目上にツールチップを表示 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{371, 335}, {39, 14}} - - YES - - 68288064 - 272761856 - 文字 - - - - - - - - - 268 - {{371, 392}, {39, 14}} - - YES - - 68288064 - 272761856 - 項目 - - - - - - - - - 268 - {{371, 365}, {39, 14}} - - YES - - 68288064 - 272761856 - 項目 - - - - - - - - - 256 - {{222, 102}, {16, 14}} - - YES - - 67239424 - 272629760 - pt - - - - - - - - - 256 - {{153, 97}, {68, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - LucidaGrande - 11 - 16 - - - - - - 400 - 75 - - - 9 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - 3 - YES - YES - 1 - - - - - 268 - {{70, 101}, {241, 38}} - - YES - 2 - 1 - - - -2080244224 - 0 - アイコンの大きさに合わせる - - - 1211912703 - 0 - - NSImage - NSRadioButton - - - NSRadioButton - - - - 200 - 25 - - - 67239424 - 0 - 選択: - - - 1 - 1211912703 - 0 - - - - 400 - 75 - - - {241, 18} - {4, 2} - 1151868928 - NSActionCell - - 67239424 - 0 - Radio - - 1211912703 - 0 - - - - 400 - 75 - - - - - - - - - 268 - {{67, 169}, {250, 17}} - - YES - - 68288064 - 272630784 - ツールチップに表示する文字列の長さ: - - - - - - - - - 256 - {{322, 166}, {44, 22}} - - YES - - -1804468671 - 71304192 - - - - - - - - -∞ - - - +∞ - - # - # - - - - - - - - NaN - - - - - - 3 - YES - YES - YES - - . - , - NO - YES - YES - - - YES - - - - - - - 268 - {{371, 166}, {39, 14}} - - YES - - 68288064 - 272761856 - 文字 - - - - - - - - {460, 434} - - NSView - - NSResponder - - - - 268 - - - - 36 - {{45, 10}, {369, 339}} - - - - 2 - - - 256 - - - - 256 - - - - 256 - - - - 256 - {{14, 150}, {238, 18}} - - YES - - 67239424 - 0 - プレーンテキスト - - LucidaGrande - 12 - 16 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 130}, {238, 18}} - - YES - - 67239424 - 0 - Rich Text Format (RTF) - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 110}, {238, 18}} - - YES - - 67239424 - 0 - Rich Text Format Directory (RTFD) - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 90}, {238, 18}} - - YES - - 67239424 - 0 - PDF - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 70}, {238, 18}} - - YES - - 67239424 - 0 - ファイル名 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 50}, {238, 18}} - - YES - - 67239424 - 0 - URL - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 29}, {238, 18}} - - YES - - 67239424 - 0 - TIFF画像 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{14, 9}, {238, 18}} - - YES - - 67239424 - 0 - PICT画像 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {{2, 2}, {325, 176}} - - - - {{6, 100}, {329, 193}} - - {0, 0} - - 67239424 - 0 - 保存するクリップボードの種類を選択: - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - {{10, 25}, {349, 301}} - - - 対応形式 - - - - - 1 - - - 256 - - - - 256 - {{136, 251}, {67, 22}} - - YES - - 71433792 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - 16 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - 32 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 48 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 3 - YES - YES - 1 - - - - - 256 - {{37, 257}, {97, 14}} - - YES - - 67239424 - 272760832 - アイコンの大きさ: - - - - - - - - - 256 - - - - 256 - - - - 256 - {{22, 196}, {111, 14}} - - YES - - 67239424 - 272760832 - プレーンテキスト: - - - - - - - - - 256 - {{136, 191}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 193}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 170}, {73, 14}} - - YES - - 67239424 - 272760832 - RTF: - - - - - - - - - 256 - {{136, 165}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 167}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 144}, {73, 14}} - - YES - - 67239424 - 272760832 - RTFD: - - - - - - - - - 256 - {{136, 139}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 141}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 117}, {73, 14}} - - YES - - 67239424 - 272760832 - PDF: - - - - - - - - - 256 - {{136, 112}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 114}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 91}, {111, 14}} - - YES - - 67239424 - 272760832 - ファイル名: - - - - - - - - - 256 - {{136, 86}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 87}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 65}, {73, 14}} - - YES - - 67239424 - 272760832 - URL: - - - - - - - - - 256 - {{136, 60}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 62}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 39}, {73, 14}} - - YES - - 67239424 - 272760832 - TIFF: - - - - - - - - - 256 - {{136, 34}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 36}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - - 256 - {{22, 13}, {73, 14}} - - YES - - 67239424 - 272760832 - PICT: - - - - - - - - - 256 - {{136, 8}, {115, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 1 - - - - - - 400 - 75 - - - ファイル拡張子 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - - - - タイプコード - - 1048576 - 2147483647 - - - _popUpItemAction: - 1 - - - - - 3 - YES - YES - 1 - - - - - 256 - {{256, 10}, {36, 19}} - - YES - - -1804468671 - 272761856 - - - - YES - - - - - - {{2, 2}, {317, 224}} - - - - {{14, 10}, {321, 241}} - - {0, 0} - - 67239424 - 0 - アイコン - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 256 - {{18, 279}, {297, 18}} - - YES - - 67239424 - 131072 - メニューにアイコンを表示 - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{205, 256}, {32, 14}} - - YES - - 67239424 - 272629760 - pixel - - - - - - - - {{10, 25}, {349, 301}} - - アイコン - - - - - - - 134217728 - YES - YES - - - - - - {460, 366} - NSView - - - - 256 - - - - 256 - {{276, 230}, {68, 25}} - - YES - - 67239424 - 134348800 - 削除 - - - -2038284033 - 34 - - - - - - 200 - 25 - - - - - 256 - {{276, 275}, {68, 23}} - - YES - - 67239424 - 134348800 - フォルダ - - - -2038021889 - 34 - - - - 400 - 75 - - - - - 256 - - - - 2304 - - - - 256 - {246, 266} - - YES - - - 256 - {246, 17} - - - - - - -2147483392 - {{-26, 0}, {16, 17}} - - - - - NameColumn - 243 - 38.599119999999999 - 1000 - - 75628096 - 2048 - 名前 - - - 3 - MC4zMzMzMzI5OQA - - - 6 - System - headerTextColor - - - - - 337772096 - 2048 - - - - 6 - System - controlBackgroundColor - - - - - 3 - YES - YES - - - - 3 - 2 - - - 6 - System - gridColor - - 3 - MC41AA - - - 17 - -633339904 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {246, 266}} - - - - - 4 - - - - -2147483392 - {{198, 17}, {15, 267}} - - - _doScroller: - 0.94680850000000005 - - - - -2147483392 - {{1, 284}, {212, 15}} - - 1 - - _doScroller: - 1 - 0.99065420000000004 - - - - 2304 - - - - {{1, 0}, {246, 17}} - - - - - 4 - - - - {{20, 42}, {248, 284}} - - - 562 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 256 - {{276, 304}, {68, 23}} - - YES - - 67239424 - 134348800 - << - - - -2038021889 - 34 - - - - 400 - 75 - - - - - 256 - - - - 2304 - - - - 256 - {246, 241} - - YES - - - 256 - {246, 17} - - - - - - -2147483392 - {{-26, 0}, {16, 17}} - - - - - NameColumn - 243 - 38.599119999999999 - 1000 - - 75628096 - 2048 - 名前 - - - 3 - MC4zMzMzMzI5OQA - - - - - 337772096 - 2048 - - - - - - 3 - YES - - - - 3 - 2 - - - 17 - -633339904 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {246, 241}} - - - - - 4 - - - - -2147483392 - {{-30, 17}, {15, 257}} - - - _doScroller: - 0.96616539999999995 - - - - -2147483392 - {{1, -30}, {182, 15}} - - 1 - - _doScroller: - 0.92385790000000001 - - - - 2304 - - - - {{1, 0}, {246, 17}} - - - - - 4 - - - - {{352, 42}, {248, 259}} - - - 562 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 256 - {{350, 306}, {252, 20}} - - YES - - 67239424 - 131072 - - - - - 80.333340000000007 - 内蔵 - YES - 2 - - - 81.333340000000007 - Scripts - 1 - 2 - - - 81.333340000000007 - User's - 2 - 2 - - - - - - - 256 - {{18, 528}, {487, 18}} - - YES - - 67239424 - 0 - アクションを使用する - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{30, 508}, {475, 18}} - - YES - - 67239424 - 0 - 登録したアクションが一つだけなら、即座にアクションを実行する - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 12 - {{0, 354}, {620, 5}} - - {0, 0} - - 67239424 - 0 - Box - - - - 3 - MCAwLjgwMDAwMDAxAA - - - 3 - 2 - 0 - NO - - - - 36 - - - - 256 - - - - 268 - {{15, 64}, {140, 14}} - - YES - - 68288064 - 71435264 - Shift + クリック: - - - - - - - - - 268 - {{15, 89}, {140, 14}} - - YES - - 68288064 - 71435264 - Control + クリック: - - - - - - - - - 268 - {{157, 35}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{15, 39}, {140, 14}} - - YES - - 68288064 - 71435264 - Option + クリック: - - - - - - - - - 268 - {{157, 60}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{157, 85}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - - 268 - {{15, 14}, {140, 14}} - - YES - - 68288064 - 71435264 - Command + クリック: - - - - - - - - - 268 - {{157, 10}, {204, 22}} - - YES - - -2076049856 - 133120 - - - 109199615 - 129 - - - 400 - 75 - - YES - - OtherViews - - - -1 - 1 - YES - YES - 2 - - - - {{1, 1}, {376, 116}} - - - - {{121, 361}, {378, 132}} - - {0, 0} - - 67239424 - 0 - 履歴メニュー項目上での、修飾キー + クリック の動作 - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 1 - 0 - 2 - NO - - - - 256 - {{17, 20}, {45, 14}} - - YES - - 67239424 - 71434240 - 名前: - - - - - - - - - 256 - {{64, 20}, {539, 14}} - - YES - - 67239424 - 272760832 - 名前 - - - - - - - - - 12 - {{0, 499}, {620, 5}} - - {0, 0} - - 67239424 - 0 - Box - - - - 3 - MCAwLjgwMDAwMDAxAA - - - 3 - 2 - 0 - NO - - - - 268 - {{17, 334}, {220, 14}} - - YES - - 68288064 - 272761856 - アクションメニュー - - LucidaGrande-Bold - 11 - 16 - - - - - - - - {620, 564} - - NSView - - NSResponder - - - - 268 - - - - 36 - - - - 256 - - - - 268 - {{15, 45}, {152, 17}} - - YES - - 68288064 - 272630784 - 履歴メニュー: - - - - - - - - - 298 - {{172, 42}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - - 268 - {{15, 75}, {152, 17}} - - YES - - 68288064 - 272630784 - メインメニュー: - - - - - - - - - 298 - {{172, 72}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - - 268 - {{15, 17}, {152, 17}} - - YES - - 68288064 - 272630784 - スニペットメニュー: - - - - - - - - - 298 - {{172, 14}, {169, 22}} - - YES - - 130560 - 0 - - - - - - - - - - - - - - {{1, 1}, {359, 104}} - - - - {{49, 24}, {361, 120}} - - {0, 0} - - 67239424 - 0 - ショートカット - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 1 - 0 - 2 - NO - - - {460, 170} - NSView - - - - 268 - - - - 268 - {{65, 84}, {241, 18}} - - YES - - 67239424 - 0 - プレリリース版も含める - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{294, 99}, {116, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 129 - - - 400 - 75 - - - 毎日 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - 86400 - - - YES - - - - - - - 毎週 - - 1048576 - 2147483647 - - - _popUpItemAction: - 604800 - - - - - 毎月 - - 1048576 - 2147483647 - - - _popUpItemAction: - 2592000 - - - - - - 1 - YES - YES - 2 - - - - - 268 - {{50, 104}, {241, 18}} - - YES - - 67239424 - 0 - アップデートを自動的にチェック: - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 268 - {{163, 42}, {132, 32}} - - YES - - 67239424 - 134217728 - 今すぐチェック - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{49, 20}, {361, 14}} - - YES - - 68288064 - -2008939520 - date - - - - - - - - EEEE, MMMM d, yyyy h:mm:ss a - NO - - - - - - - - {460, 140} - NSView - - - 27 - 2 - {{140, 201}, {410, 320}} - 611845120 - 除外アプリケーション - NSPanel - - {1.79769e+308, 1.79769e+308} - - - 256 - - - - 289 - {{291, 12}, {105, 32}} - - YES - - 67239424 - 134217728 - 完了 - - - -2038284033 - 129 - - - 200 - 25 - - - - - 289 - {{186, 12}, {105, 32}} - - YES - - 67239424 - 134217728 - キャンセル - - - -2038284033 - 129 - - Gw - 200 - 25 - - - - - 268 - {{17, 283}, {376, 17}} - - YES - - 68288064 - 272630784 - 除外するアプリケーション: - - - - - - - - - 274 - - - - 2304 - - - - 256 - {368, 190} - - YES - - - -2147483392 - {{224, 0}, {16, 17}} - - - - ImageAndTextCellColumn - 365 - 40 - 1000 - - 75628096 - 2048 - - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - - - - - 3 - YES - - - - 3 - 2 - - - 17 - 1522532352 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 1}, {368, 190}} - - - - - 4 - - - - -2147483392 - {{224, 17}, {15, 102}} - - - _doScroller: - 0.99468085106382975 - - - - -2147483392 - {{1, 68}, {125, 15}} - - 1 - - _doScroller: - 0.99728997289972898 - - - {{20, 83}, {370, 192}} - - - 562 - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 292 - {{20, 55}, {21, 21}} - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSAddTemplate - - - - 400 - 75 - - - - - 292 - {{40, 55}, {21, 21}} - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSRemoveTemplate - - - - 400 - 75 - - - - {410, 320} - - {{0, 0}, {1280, 1002}} - {1.79769e+308, 1.79769e+308} - - - - - - - actionTreeController - - - - 357 - - - - actionNodeController - - - - 365 - - - - contentArray: actionNodes - - - - - - contentArray: actionNodes - contentArray - actionNodes - 2 - - - 366 - - - - reserveTreeController - - - - 372 - - - - value: values.inputPasteCommand - - - - - - value: values.inputPasteCommand - value - values.inputPasteCommand - 2 - - - 442 - - - - value: values.timeInterval - - - - - - value: values.timeInterval - value - values.timeInterval - 2 - - - 447 - - - - generalPrefsView - - - - 459 - - - - value: values.maxMenuItemTitleLength - - - - - - value: values.maxMenuItemTitleLength - value - values.maxMenuItemTitleLength - 2 - - - 542 - - - - value: values.menuItemsAreMarkedWithNumbers - - - - - - value: values.menuItemsAreMarkedWithNumbers - value - values.menuItemsAreMarkedWithNumbers - 2 - - - 544 - - - - value: values.menuItemsTitleStartWithZero - - - - - - value: values.menuItemsTitleStartWithZero - value - values.menuItemsTitleStartWithZero - 2 - - - 546 - - - - enabled: values.menuItemsAreMarkedWithNumbers - - - - - - enabled: values.menuItemsAreMarkedWithNumbers - enabled - values.menuItemsAreMarkedWithNumbers - 2 - - - 547 - - - - value: values.changeFontSize - - - - - - value: values.changeFontSize - value - values.changeFontSize - 2 - - - 549 - - - - enabled: values.changeFontSize - - - - - - enabled: values.changeFontSize - enabled - values.changeFontSize - 2 - - - 554 - - - - contentValues: fontSizePopUpMenuItems - - - - - - contentValues: fontSizePopUpMenuItems - contentValues - fontSizePopUpMenuItems - 2 - - - 556 - - - - selectedValue: values.selectedFontSize - - - - - - selectedValue: values.selectedFontSize - selectedValue - values.selectedFontSize - - 2 - - - 557 - - - - value: values.showImageInTheMenu - - - - - - value: values.showImageInTheMenu - value - values.showImageInTheMenu - 2 - - - 559 - - - - value: values.thumbnailWidth - - - - - - value: values.thumbnailWidth - value - values.thumbnailWidth - 2 - - - 561 - - - - value: values.thumbnailHeight - - - - - - value: values.thumbnailHeight - value - values.thumbnailHeight - 2 - - - 563 - - - - enabled: values.showImageInTheMenu - - - - - - enabled: values.showImageInTheMenu - enabled - values.showImageInTheMenu - 2 - - - 564 - - - - enabled: values.showImageInTheMenu - - - - - - enabled: values.showImageInTheMenu - enabled - values.showImageInTheMenu - 2 - - - 565 - - - - menuPrefsView - - - - 606 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - 2 - - - 626 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - - NSConditionallySetsEditable - - - 2 - - - 627 - - - - selectedIndex: indexOfActionTypeSegment - - - - - - selectedIndex: indexOfActionTypeSegment - selectedIndex - indexOfActionTypeSegment - 2 - - - 628 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 630 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - 2 - - - 632 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 634 - - - - actionPrefsView - - - - 635 - - - - nameField - - - - 638 - - - - reservedActionsOutlineView - - - - 641 - - - - actionsOutlineView - - - - 642 - - - - actionTypeSegmentedControll - - - - 643 - - - - dataSource - - - - 649 - - - - delegate - - - - 650 - - - - dataSource - - - - 651 - - - - delegate - - - - 652 - - - - remove: - - - - 653 - - - - add: - - - - 654 - - - - add: - - - - 655 - - - - value: values.enableAction - - - - - - value: values.enableAction - value - values.enableAction - 2 - - - 661 - - - - value: values.addNumericKeyEquivalents - - - - - - value: values.addNumericKeyEquivalents - value - values.addNumericKeyEquivalents - 2 - - - 665 - - - - value: values.showAlertBeforeClearHistory - - - - - - value: values.showAlertBeforeClearHistory - value - values.showAlertBeforeClearHistory - 2 - - - 671 - - - - value: values.addClearHistoryMenuItem - - - - - - value: values.addClearHistoryMenuItem - value - values.addClearHistoryMenuItem - 2 - - - 672 - - - - enabled: values.addClearHistoryMenuItem - - - - - - enabled: values.addClearHistoryMenuItem - enabled - values.addClearHistoryMenuItem - 2 - - - 673 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 677 - - - - enabled2: values.howToChangeFontSize - - - - - - enabled2: values.howToChangeFontSize - enabled2 - values.howToChangeFontSize - - - - - - - - 2 - - - 678 - - - - value: values.loginItem - - - - - - value: values.loginItem - value - values.loginItem - 2 - - - 771 - - - - value: values.showIconInTheMenu - - - - - - value: values.showIconInTheMenu - value - values.showIconInTheMenu - 2 - - - 1007 - - - - selectedValue: values.menuIconSize - - - - - - selectedValue: values.menuIconSize - selectedValue - values.menuIconSize - 2 - - - 1008 - - - - enabled: values.showIconInTheMenu - - - - - - enabled: values.showIconInTheMenu - enabled - values.showIconInTheMenu - 2 - - - 1009 - - - - selectedTag: values.menuIconOfFileTypeTagForString - - - - - - selectedTag: values.menuIconOfFileTypeTagForString - selectedTag - values.menuIconOfFileTypeTagForString - 2 - - - 1010 - - - - selectedTag: values.menuIconOfFileTypeTagForRTF - - - - - - selectedTag: values.menuIconOfFileTypeTagForRTF - selectedTag - values.menuIconOfFileTypeTagForRTF - 2 - - - 1011 - - - - selectedTag: values.menuIconOfFileTypeTagForRTFD - - - - - - selectedTag: values.menuIconOfFileTypeTagForRTFD - selectedTag - values.menuIconOfFileTypeTagForRTFD - 2 - - - 1012 - - - - selectedTag: values.menuIconOfFileTypeTagForPDF - - - - - - selectedTag: values.menuIconOfFileTypeTagForPDF - selectedTag - values.menuIconOfFileTypeTagForPDF - 2 - - - 1013 - - - - selectedTag: values.menuIconOfFileTypeTagForFilenames - - - - - - selectedTag: values.menuIconOfFileTypeTagForFilenames - selectedTag - values.menuIconOfFileTypeTagForFilenames - 2 - - - 1014 - - - - selectedTag: values.menuIconOfFileTypeTagForURL - - - - - - selectedTag: values.menuIconOfFileTypeTagForURL - selectedTag - values.menuIconOfFileTypeTagForURL - 2 - - - 1015 - - - - selectedTag: values.menuIconOfFileTypeTagForTIFF - - - - - - selectedTag: values.menuIconOfFileTypeTagForTIFF - selectedTag - values.menuIconOfFileTypeTagForTIFF - 2 - - - 1016 - - - - selectedTag: values.menuIconOfFileTypeTagForPICT - - - - - - selectedTag: values.menuIconOfFileTypeTagForPICT - selectedTag - values.menuIconOfFileTypeTagForPICT - 2 - - - 1017 - - - - iconPrefsView - - - - 1018 - - - - value: values.menuIconOfFileTypeForString - - - - - - value: values.menuIconOfFileTypeForString - value - values.menuIconOfFileTypeForString - 2 - - - 1019 - - - - value: values.menuIconOfFileTypeForRTF - - - - - - value: values.menuIconOfFileTypeForRTF - value - values.menuIconOfFileTypeForRTF - 2 - - - 1020 - - - - value: values.menuIconOfFileTypeForRTFD - - - - - - value: values.menuIconOfFileTypeForRTFD - value - values.menuIconOfFileTypeForRTFD - 2 - - - 1021 - - - - value: values.menuIconOfFileTypeForPDF - - - - - - value: values.menuIconOfFileTypeForPDF - value - values.menuIconOfFileTypeForPDF - 2 - - - 1022 - - - - value: values.menuIconOfFileTypeForFilenames - - - - - - value: values.menuIconOfFileTypeForFilenames - value - values.menuIconOfFileTypeForFilenames - 2 - - - 1023 - - - - value: values.menuIconOfFileTypeForURL - - - - - - value: values.menuIconOfFileTypeForURL - value - values.menuIconOfFileTypeForURL - 2 - - - 1024 - - - - value: values.menuIconOfFileTypeForTIFF - - - - - - value: values.menuIconOfFileTypeForTIFF - value - values.menuIconOfFileTypeForTIFF - 2 - - - 1025 - - - - value: values.menuIconOfFileTypeForPICT - - - - - - value: values.menuIconOfFileTypeForPICT - value - values.menuIconOfFileTypeForPICT - 2 - - - 1026 - - - - value: values.numberOfItemsPlaceInline - - - - - - value: values.numberOfItemsPlaceInline - value - values.numberOfItemsPlaceInline - 2 - - - 1036 - - - - value: values.numberOfItemsPlaceInsideFolder - - - - - - value: values.numberOfItemsPlaceInsideFolder - value - values.numberOfItemsPlaceInsideFolder - 2 - - - 1042 - - - - value: values.showLabelsInMenu - - - - - - value: values.showLabelsInMenu - value - values.showLabelsInMenu - 2 - - - 1045 - - - - value: values.saveHistoryOnQuit - - - - - - value: values.saveHistoryOnQuit - value - values.saveHistoryOnQuit - 2 - - - 1048 - - - - value: storeTypes.String - - - - - - value: storeTypes.String - value - storeTypes.String - 2 - - - 1105 - - - - value: storeTypes.RTF - - - - - - value: storeTypes.RTF - value - storeTypes.RTF - 2 - - - 1106 - - - - value: storeTypes.RTFD - - - - - - value: storeTypes.RTFD - value - storeTypes.RTFD - 2 - - - 1107 - - - - value: storeTypes.PDF - - - - - - value: storeTypes.PDF - value - storeTypes.PDF - 2 - - - 1108 - - - - value: storeTypes.Filenames - - - - - - value: storeTypes.Filenames - value - storeTypes.Filenames - 2 - - - 1109 - - - - value: storeTypes.URL - - - - - - value: storeTypes.URL - value - storeTypes.URL - 2 - - - 1110 - - - - value: storeTypes.TIFF - - - - - - value: storeTypes.TIFF - value - storeTypes.TIFF - 2 - - - 1111 - - - - value: storeTypes.PICT - - - - - - value: storeTypes.PICT - value - storeTypes.PICT - 2 - - - 1113 - - - - value: values.showToolTipOnMenuItem - - - - - - value: values.showToolTipOnMenuItem - value - values.showToolTipOnMenuItem - 2 - - - 1158 - - - - value: values.invokeActionImmediately - - - - - - value: values.invokeActionImmediately - value - values.invokeActionImmediately - 2 - - - 1159 - - - - value: values.maxHistorySize - - - - - - value: values.maxHistorySize - value - values.maxHistorySize - 2 - - - 1165 - - - - nextKeyView - - - - 1168 - - - - nextKeyView - - - - 1169 - - - - controlPopUpButton - - - - 1201 - - - - shiftPopUpButton - - - - 1210 - - - - optionPopUpButton - - - - 1216 - - - - commandPopUpButton - - - - 1222 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1227 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1228 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1229 - - - - enabled: values.enableAction - - - - - - enabled: values.enableAction - enabled - values.enableAction - 2 - - - 1230 - - - - enabled: values.changeFontSize - - - - - - enabled: values.changeFontSize - enabled - values.changeFontSize - 2 - - - 1242 - - - - selectedTag: values.howToChangeFontSize - - - - - - selectedTag: values.howToChangeFontSize - selectedTag - values.howToChangeFontSize - 2 - - - 1245 - - - - enabled: values.showToolTipOnMenuItem - - - - - - enabled: values.showToolTipOnMenuItem - enabled - values.showToolTipOnMenuItem - 2 - - - 1265 - - - - value: values.maxLengthOfToolTipKey - - - - - - value: values.maxLengthOfToolTipKey - value - values.maxLengthOfToolTipKey - 2 - - - 1266 - - - - nextKeyView - - - - 1270 - - - - nextKeyView - - - - 1271 - - - - nextKeyView - - - - 1272 - - - - nextKeyView - - - - 1273 - - - - selectedTag: values.autosaveDelay - - - - - - selectedTag: values.autosaveDelay - selectedTag - values.autosaveDelay - 2 - - - 1298 - - - - value: values.timeInterval - - - - - - value: values.timeInterval - value - values.timeInterval - 2 - - - 1301 - - - - selectedTag: values.showStatusItem - - - - - - selectedTag: values.showStatusItem - selectedTag - values.showStatusItem - 2 - - - 1319 - - - - updatesPrefsView - - - - 1325 - - - - checkForUpdates: - - - - 1333 - - - - value: lastUpdateCheckDate - - - - - - value: lastUpdateCheckDate - value - lastUpdateCheckDate - 2 - - - 1334 - - - - value: values.enableAutomaticCheck - - - - - - value: values.enableAutomaticCheck - value - values.enableAutomaticCheck - 2 - - - 1347 - - - - selectedTag: values.updateCheckInterval - - - - - - selectedTag: values.updateCheckInterval - selectedTag - values.updateCheckInterval - 2 - - - 1356 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1357 - - - - shortcutPrefsView - - - - 1365 - - - - delegate - - - - 1375 - - - - delegate - - - - 1376 - - - - shortcutRecorder - - - - 1377 - - - - exportHistory: - - - - 1411 - - - - selectedTag: values.tagOfSeparatorForExportHistoryToFile - - - - - - selectedTag: values.tagOfSeparatorForExportHistoryToFile - selectedTag - values.tagOfSeparatorForExportHistoryToFile - 2 - - - 1412 - - - - selectedTag: values.exportHistoryAsSingleFile - - - - - - selectedTag: values.exportHistoryAsSingleFile - selectedTag - values.exportHistoryAsSingleFile - 2 - - - 1413 - - - - enabled: values.exportHistoryAsSingleFile - - - - - - enabled: values.exportHistoryAsSingleFile - enabled - values.exportHistoryAsSingleFile - 2 - - - 1414 - - - - selectedIndex: values.reorderClipsAfterPasting - - - - - - selectedIndex: values.reorderClipsAfterPasting - selectedIndex - values.reorderClipsAfterPasting - 2 - - - 1424 - - - - value: values.enableAutomaticCheckPreReleaseKey - - - - - - value: values.enableAutomaticCheckPreReleaseKey - value - values.enableAutomaticCheckPreReleaseKey - 2 - - - 1427 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1429 - - - - enabled: values.enableAutomaticCheck - - - - - - enabled: values.enableAutomaticCheck - enabled - values.enableAutomaticCheck - 2 - - - 1430 - - - - openExcludeOptions: - - - - 1450 - - - - value: arrangedObjects.name - - - - - - value: arrangedObjects.name - value - arrangedObjects.name - 2 - - - 1482 - - - - contentArray: excludeList - - - - - - contentArray: excludeList - contentArray - excludeList - - NSDeletesObjectsOnRemove - - - 2 - - - 1484 - - - - delegate - - - - 1485 - - - - remove: - - - - 1487 - - - - excludeListController - - - - 1489 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 1490 - - - - addExcludeListButtion - - - - 1494 - - - - excludeListPanel - - - - 1495 - - - - cancelExcludeListPanel: - - - - 1496 - - - - doneExcludeListPanel: - - - - 1497 - - - - addToExcludeList: - - - - 1498 - - - - delegate - - - - 1504 - - - - snippetsShortcutRecorder - - - - 1505 - - - - historyShortCutRecorder - - - - 1506 - - - - selectedIndex: values.positionOfSnippets - - - - - - selectedIndex: values.positionOfSnippets - selectedIndex - values.positionOfSnippets - 2 - - - 1515 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - 10 - - - Shared Defaults - - - 329 - - - ActionTreeController - - - 355 - - - ActionNodeController - - - 370 - - - ReserveTreeController - - - 412 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - General - - - 420 - - - - - - - - 421 - - - - - - - - 424 - - - - - - - - 425 - - - - - - - - 460 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Menu - - - 461 - - - - - - - - 462 - - - - - - - - 464 - - - - - - - - 465 - - - - - - - - 466 - - - - - - - - 467 - - - - - - - - 468 - - - - - - - - 470 - - - - - - - - 472 - - - - - - - - 473 - - - - - - - - 524 - - - - - - - - 663 - - - - - - - - 607 - - - - - - - - - - - - - - - - - - - Action - - - 608 - - - - - - - - 609 - - - - - - - - 610 - - - - - - - - - - - 611 - - - - - - - - 612 - - - - - - - - 613 - - - - - - - - 622 - - - - - - - - - - - 623 - - - - - - - - 624 - - - - - - - - 625 - - - - - - - - 656 - - - - - - - - 674 - - - - - - - - 686 - - - - - 687 - - - - - 689 - - - - - 690 - - - - - 703 - - - - - 704 - - - - - - - - 705 - - - - - 706 - - - - - 707 - - - - - 708 - - - - - 709 - - - - - - - - 710 - - - - - - - - 711 - - - - - 712 - - - - - 737 - - - - - 743 - - - - - 746 - - - - - 747 - - - - - 748 - - - - - 755 - - - - - 756 - - - - - 757 - - - - - 759 - - - - - 760 - - - - - 463 - - - - - 469 - - - - - 471 - - - - - 761 - - - - - 762 - - - - - 763 - - - - - 764 - - - - - 765 - - - - - 766 - - - - - -3 - - - Application - - - 767 - - - - - - - - 768 - - - - - 921 - - - - - - Type - - - 1027 - - - - - - - - 1028 - - - - - 1029 - - - - - - - - 1030 - - - - - - - - 1031 - - - - - - - - 1032 - - - - - - - - 1033 - - - - - - - - 1034 - - - - - 533 - - - - - - - - 744 - - - - - 1038 - - - - - 1039 - - - - - 1043 - - - - - - - - 1044 - - - - - 1046 - - - - - - - - 1047 - - - - - 1083 - - - - - - - - - 1084 - - - - - - - - 1085 - - - - - - - - - - - - 1086 - - - - - - - - 1087 - - - - - - - - 925 - - - - - - - - 928 - - - - - - - - 929 - - - - - - - - - - 932 - - - - - 931 - - - - - 930 - - - - - 924 - - - - - - - - 933 - - - - - 922 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 935 - - - - - - - - 938 - - - - - - - - 941 - - - - - - - - 944 - - - - - - - - 947 - - - - - - - - 950 - - - - - - - - 953 - - - - - - - - 956 - - - - - - - - 958 - - - - - - - - 957 - - - - - - - - 955 - - - - - - - - 954 - - - - - - - - 952 - - - - - - - - 951 - - - - - - - - 949 - - - - - - - - 948 - - - - - - - - 946 - - - - - - - - 945 - - - - - - - - 943 - - - - - - - - 942 - - - - - - - - 940 - - - - - - - - 939 - - - - - - - - 937 - - - - - - - - 936 - - - - - - - - 1002 - - - - - - - - 1003 - - - - - - - - - 1005 - - - - - 1004 - - - - - 1001 - - - - - 996 - - - - - - - - 997 - - - - - - - - - 999 - - - - - 998 - - - - - 995 - - - - - 990 - - - - - - - - 991 - - - - - - - - - 993 - - - - - 992 - - - - - 989 - - - - - 984 - - - - - - - - 985 - - - - - - - - - 987 - - - - - 986 - - - - - 983 - - - - - 978 - - - - - - - - 979 - - - - - - - - - 981 - - - - - 980 - - - - - 977 - - - - - 972 - - - - - - - - 973 - - - - - - - - - 975 - - - - - 974 - - - - - 971 - - - - - 966 - - - - - - - - 967 - - - - - - - - - 969 - - - - - 968 - - - - - 965 - - - - - 960 - - - - - - - - 961 - - - - - - - - - 963 - - - - - 962 - - - - - 959 - - - - - 964 - - - - - 970 - - - - - 976 - - - - - 982 - - - - - 988 - - - - - 994 - - - - - 1000 - - - - - 1006 - - - - - 923 - - - - - - - - 934 - - - - - 926 - - - - - - - - 927 - - - - - 1088 - - - - - - - - - - - - - - - 1089 - - - - - - - - 1090 - - - - - - - - 1091 - - - - - - - - 1092 - - - - - - - - 1093 - - - - - - - - 1094 - - - - - - - - 1095 - - - - - - - - 1096 - - - - - - - - 1097 - - - - - 1098 - - - - - 1099 - - - - - 1100 - - - - - 1101 - - - - - 1102 - - - - - 1103 - - - - - 1104 - - - - - 1124 - - - - - 1156 - - - - - - - - 1157 - - - - - 1172 - - - - - - - - 1173 - - - - - 1174 - - - - - - - - 1175 - - - - - 1176 - - - - - - - - 1177 - - - - - 1223 - - - - - - - - - - - - - - - 1205 - - - - - - - - 1209 - - - - - 1189 - - - - - - - - 1190 - - - - - 1212 - - - - - - - - 1213 - - - - - - - - 1214 - - - - - 1211 - - - - - - - - 1215 - - - - - 1206 - - - - - - - - 1207 - - - - - - - - 1208 - - - - - 1191 - - - - - - - - 1192 - - - - - - - - 1193 - - - - - 1217 - - - - - - - - 1221 - - - - - 1218 - - - - - - - - 1219 - - - - - - - - 1220 - - - - - 619 - - - - - - - - 752 - - - - - 617 - - - - - - - - 750 - - - - - 1224 - - - - - 1231 - - - - - - - - 1232 - - - - - 540 - - - - - - - - 742 - - - - - 537 - - - - - - - - 745 - - - - - - - - 538 - - - - - - - - 539 - - - - - 1237 - - - - - - - - - - 1238 - - - - - 1239 - - - - - 1240 - - - - - 1255 - - - - - - - - 1256 - - - - - 1257 - - - - - - - - 1258 - - - - - - - - 1259 - - - - - 1260 - - - - - - - - 1263 - - - - - 1274 - - - - - - - - 1275 - - - - - 1276 - - - - - - - - 1277 - - - - - 1278 - - - - - - - - 1279 - - - - - 1280 - - - - - - - - 1281 - - - - - 1282 - - - - - - - - 1283 - - - - - - - - 1284 - - - - - - - - - - - - - - - - - 1285 - - - - - 1286 - - - - - 1287 - - - - - 1289 - - - - - 1290 - - - - - 1291 - - - - - 1292 - - - - - 1293 - - - - - 1294 - - - - - 1295 - - - - - 1299 - - - - - - - - 1300 - - - - - - - - 1303 - - - - - 1170 - - - - - - - - 1171 - - - - - 1161 - - - - - - - - 1162 - - - - - - - - 1163 - - - - - 1160 - - - - - - - - 1164 - - - - - 669 - - - - - - - - 702 - - - - - 666 - - - - - - - - 701 - - - - - 1304 - - - - - - - - 1305 - - - - - 1309 - - - - - - - - 1310 - - - - - - - - 1311 - - - - - - - - - - - - - - - - - - - - - 1312 - - - - - 1313 - - - - - 1315 - - - - - - - - 1316 - - - - - 1318 - - - - - 1320 - - - - - 1321 - - - - - 1322 - - - - - 1323 - - - - - 1324 - - - - - - - - - - Updates - - - 1328 - - - - - - - - 1329 - - - - - - - - 1330 - - - - - - - - 1331 - - - - - 1332 - - - - - 1335 - - - - - 1336 - - - - - - - - 1337 - - - - - 1350 - - - - - - - - 1351 - - - - - - - - 1352 - - - - - - - - - - 1353 - - - - - 1354 - - - - - 1355 - - - - - 1358 - - - - - 1359 - - - - - 1360 - - - - - 1361 - - - - - 1362 - - - - - 1363 - - - - - 1364 - - - - - - Shortcuts - - - 1366 - - - - - - - - - - - - - 1367 - - - - - - - - 1368 - - - - - - - - 1369 - - - - - - - - 1370 - - - - - - - - 1371 - - - - - 1372 - - - - - 1373 - - - - - 1374 - - - - - 1379 - - - - - - - - 1380 - - - - - 1381 - - - - - - - - 1382 - - - - - - - - 1383 - - - - - - - - - 1384 - - - - - 1385 - - - - - 1389 - - - - - - - - 1390 - - - - - 1395 - - - - - - - - 1396 - - - - - 1401 - - - - - - - - 1402 - - - - - - - - 1403 - - - - - - - - - - - - - 1404 - - - - - 1405 - - - - - 1406 - - - - - 1407 - - - - - 1408 - - - - - 1410 - - - - - 1416 - - - - - - - - 1417 - - - - - 1418 - - - - - - - - 1419 - - - - - - - - 1420 - - - - - - - - - 1421 - - - - - 1422 - - - - - 1425 - - - - - - - - 1426 - - - - - 1445 - - - - - - - - 1446 - - - - - 1447 - - - - - - - - 1448 - - - - - 1451 - - - - - - ExcludeListPanel (Window) - - - 1452 - - - - - - - - - - - - - 1453 - - - - - - - - 1454 - - - - - 1455 - - - - - - - - 1456 - - - - - 1458 - - - - - - - - 1459 - - - - - 1463 - - - - - - - - - - 1464 - - - - - 1465 - - - - - 1466 - - - - - - - - 1468 - - - - - - - - 1471 - - - - - 1472 - - - - - - - - 1473 - - - - - 1474 - - - - - - - - 1475 - - - - - 1481 - - - ExcludeList Controller - - - 1500 - - - - - - - - 1501 - - - - - - - - 1502 - - - - - 1503 - - - - - 1507 - - - - - - - - 1508 - - - - - - - - 1509 - - - - - 1510 - - - - - - - - 1511 - - - - - - - - - - 1512 - - - - - 1513 - - - - - 1514 - - - - - 1516 - - - - - - - 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 - 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 - 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 - - 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 - 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 - 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 - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{319, 408}, {117, 4}} - 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 - 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 - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{360, 484}, {152, 173}} - 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 - 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 - {{392, 338}, {109, 284}} - 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 - {{217, 688}, {460, 140}} - 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 - {{468, 750}, {121, 63}} - 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 - {{371, 645}, {460, 170}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - net.wafflesoftware.ShortcutRecorder.IB.Leopard - 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 - {{392, 690}, {152, 37}} - 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 - {{360, 597}, {152, 105}} - 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 - {{392, 759}, {152, 37}} - 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 - {{151, 556}, {410, 320}} - com.apple.InterfaceBuilder.CocoaPlugin - {{151, 556}, {410, 320}} - - {1.79769e+308, 1.79769e+308} - {0, 0} - 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 - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - ActionPopUpButton - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - net.wafflesoftware.ShortcutRecorder.IB.Leopard - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{553, 425}, {208, 54}} - 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 - - {{155, 445}, {460, 494}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{361, 441}, {460, 434}} - 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 - - - - 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 - - {{244, 338}, {620, 564}} - 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 - - 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 - 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 - 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 - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - - ImageAndTextCell - 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 - {{359, 104}, {460, 366}} - 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 - - 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 - - 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 - - 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 - {{406, 470}, {138, 37}} - 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 - 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 - 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 - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - - - - - 1516 - - - - - ActionNodeController - NSObject - - id - id - - - - add: - id - - - remove: - id - - - - NSTreeController - NSOutlineView - NSTextField - NSTextField - NSTreeController - NSOutlineView - NSTextField - - - - actionTreeController - NSTreeController - - - actionsOutlineView - NSOutlineView - - - nameField - NSTextField - - - pathField - NSTextField - - - reserveTreeController - NSTreeController - - - reservedActionsOutlineView - NSOutlineView - - - typeField - NSTextField - - - - IBProjectSource - Source/ActionNodeController.h - - - - ActionNodeController - NSObject - - actionTypeSegmentedControll - NSSegmentedControl - - - actionTypeSegmentedControll - - actionTypeSegmentedControll - NSSegmentedControl - - - - IBUserSource - - - - - ActionPopUpButton - NSButton - - IBProjectSource - Source/ActionPopUpButton.h - - - - DBPrefsWindowController - NSWindowController - - IBProjectSource - Source/DBPrefsWindowController/DBPrefsWindowController.h - - - - DBPrefsWindowController - NSWindowController - - IBUserSource - - - - - FirstResponder - NSObject - - IBUserSource - - - - - ImageAndTextCell - NSTextFieldCell - - IBProjectSource - Source/CocoaExtensions/ImageAndTextCell.h - - - - NSSegmentedControl - NSControl - - IBUserSource - - - - - PrefsWindowController - DBPrefsWindowController - - id - id - id - id - id - - - - addToExcludeList: - id - - - cancelExcludeListPanel: - id - - - doneExcludeListPanel: - id - - - exportHistory: - id - - - openExcludeOptions: - id - - - - ActionNodeController - NSView - ActionPopUpButton - NSPopUpButton - NSPopUpButton - NSArrayController - NSPanel - NSView - SRRecorderControl - NSView - NSView - NSPopUpButton - NSPopUpButton - NSView - SRRecorderControl - SRRecorderControl - NSView - - - - actionNodeController - ActionNodeController - - - actionPrefsView - NSView - - - addExcludeListButtion - ActionPopUpButton - - - commandPopUpButton - NSPopUpButton - - - controlPopUpButton - NSPopUpButton - - - excludeListController - NSArrayController - - - excludeListPanel - NSPanel - - - generalPrefsView - NSView - - - historyShortCutRecorder - SRRecorderControl - - - iconPrefsView - NSView - - - menuPrefsView - NSView - - - optionPopUpButton - NSPopUpButton - - - shiftPopUpButton - NSPopUpButton - - - shortcutPrefsView - NSView - - - shortcutRecorder - SRRecorderControl - - - snippetsShortcutRecorder - SRRecorderControl - - - updatesPrefsView - NSView - - - - IBProjectSource - Source/PrefsWindowController.h - - - - PrefsWindowController - DBPrefsWindowController - - IBUserSource - - - - - - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSApplication - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSApplication+BWAdditions.h - - - - NSArrayController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSArrayController.h - - - - NSBox - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSBox.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSController - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSController.h - - - - NSDateFormatter - NSFormatter - - IBFrameworkSource - Foundation.framework/Headers/NSDateFormatter.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSManagedObjectContext - NSObject - - IBFrameworkSource - CoreData.framework/Headers/NSManagedObjectContext.h - - - - NSMatrix - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSMatrix.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMenuItemCell - NSButtonCell - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItemCell.h - - - - NSNumberFormatter - NSFormatter - - IBFrameworkSource - Foundation.framework/Headers/NSNumberFormatter.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderCell.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderControl.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRValidator.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSObjectController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSObjectController.h - - - - NSOutlineView - NSTableView - - - - NSPanel - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSPanel.h - - - - NSPopUpButton - NSButton - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButton.h - - - - NSPopUpButtonCell - NSMenuItemCell - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButtonCell.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSegmentedCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedCell.h - - - - NSSegmentedControl - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedControl.h - - - - NSSlider - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSSlider.h - - - - NSSliderCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSSliderCell.h - - - - NSTabView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTabView.h - - - - NSTabViewItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTabViewItem.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableHeaderView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTableHeaderView.h - - - - NSTableView - NSControl - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSTreeController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSTreeController.h - - - - NSUserDefaultsController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSUserDefaultsController.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSView+BWAdditions.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSWindow+BWAdditions.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - showWindow: - - showWindow: - id - - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - - SRRecorderCell - NSActionCell - - delegate - id - - - delegate - - delegate - id - - - - - - SRRecorderControl - NSControl - - delegate - id - - - delegate - - delegate - id - - - - - - SUUpdater - NSObject - - checkForUpdates: - id - - - checkForUpdates: - - checkForUpdates: - id - - - - delegate - id - - - delegate - - delegate - id - - - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - YES - ../ClipMenu.xcodeproj - 3 - - {8, 8} - {9, 8} - {7, 2} - {16, 15} - {8, 8} - {15, 15} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18, 18} - {18.2227, 18.2227} - {18, 18} - - - diff --git a/Japanese.lproj/SnippetEditor.strings b/Japanese.lproj/SnippetEditor.strings deleted file mode 100644 index 4a136d4..0000000 Binary files a/Japanese.lproj/SnippetEditor.strings and /dev/null differ diff --git a/Japanese.lproj/SnippetEditor.xib b/Japanese.lproj/SnippetEditor.xib deleted file mode 100644 index b8e035c..0000000 --- a/Japanese.lproj/SnippetEditor.xib +++ /dev/null @@ -1,3109 +0,0 @@ - - - - 1060 - 10F569 - 788 - 1038.29 - 461.00 - - 788 - 1.2.5 - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.brandonwalkin.BWToolkit - - - - - SnippetEditorController - - - FirstResponder - - - NSApplication - - - - title - nodeTitle - snippets - count - isEnabled - folder - - FolderNode - YES - YES - - Folder - - YES - YES - YES - children - isLeaf - - - - title - enabled - snippets - isEnabled - - Folder - YES - YES - - Folder - - YES - YES - YES - YES - YES - YES - - - - enabled - content - title - folder - - YES - YES - - Snippet - - YES - YES - YES - YES - YES - YES - - - 15 - 2 - {{212, 496}, {640, 480}} - 611844096 - スニペット・エディタ - NSWindow - - - 85FAC2A8-501B-4845-9B3C-05CDCCFFD4F0 - - - YES - YES - YES - YES - 1 - 1 - - - - 0242B2D4-DD8C-42CE-BDD9-36F4B857D01F - - 検索 - 検索 - - - - 259 - {{0, 14}, {182, 22}} - YES - - 341966400 - 1024 - - LucidaGrande - 13 - 1044 - - すべて - - YES - 1 - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - controlTextColor - - 3 - MAA - - - - 130560 - 0 - search - - _searchFieldSearch: - - 138690815 - 0 - - 400 - 75 - - - -2147353088 - 0 - clear - - - cancel - - - - _searchFieldCancel: - - 138428671 - 0 - - 400 - 75 - - 255 - - - - - - {182, 19} - {182, 22} - YES - YES - 0 - YES - 0 - - - - 52BD21E1-AE24-47C2-A614-3988942099B1 - - スニペットを追加 - スニペットを追加 - Add Snippet - - - NSImage - AddSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - - DCABAF9F-0E80-4BBC-B624-9BA7F5113A25 - - スニペットを削除 - スニペットを削除 - Delete Snippet - - - NSImage - DeleteSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - - F54CF4F2-7F9E-428F-9DD3-48BFEE1132BD - - 有効/無効 - 有効/無効 - Enable/Disable Snippet - - - NSImage - CheckSnippet - - - - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - NSToolbarCustomizeToolbarItem - Customize - Customize - Customize Toolbar - - - NSImage - NSToolbarCustomizeToolbarItemImage - - - runToolbarCustomizationPalette: - {0, 0} - {0, 0} - YES - YES - -1 - YES - 0 - - - NSToolbarFlexibleSpaceItem - - Flexible Space - - - - - - {1, 5} - {20000, 32} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - - - - NSToolbarSeparatorItem - - Separator - - - - - - {12, 5} - {12, 1000} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - - - - - NSToolbarSpaceItem - - Space - - - - - - {32, 5} - {32, 32} - YES - YES - -1 - YES - 0 - - YES - YES - - - 1048576 - 2147483647 - - - - - - - - - - - - - - - - - - - - - - - - - {1.79769e+308, 1.79769e+308} - - - 256 - - - - 274 - - - - 258 - - - - 4370 - - - - 2304 - - - - 4352 - {243, 459} - - YES - - - -2147483392 - {{229, 0}, {16, 17}} - - - - ImageAndTextCellColumn - 240 - 16 - 1000 - - 75628096 - 2048 - タイトル - - LucidaGrande - 11 - 3100 - - - 3 - MC4zMzMzMzI5ODU2AA - - - 6 - System - headerTextColor - - - - - 337772096 - 2048 - Text Cell - - - - 6 - System - controlBackgroundColor - - 3 - MC42NjY2NjY2NjY3AA - - - - - 3 - YES - YES - - - - 3 - 0.0 - - 6 - System - _sourceListBackgroundColor - - 1 - MC44MzkyMTU2OTU5IDAuODY2NjY2Njc0NiAwLjg5ODAzOTIyMTgAA - - - - 6 - System - gridColor - - 3 - MC41AA - - - 20 - -633339904 - - - 4 - 15 - 0 - YES - 1 - 1 - 14 - - - {{1, 1}, {243, 459}} - - - - - 4 - - - - -2147483392 - {{229, 17}, {15, 427}} - - - _doScroller: - 0.9978213507625272 - - - - -2147483392 - {{1, 444}, {243, 15}} - - 1 - - _doScroller: - 0.99590163934426235 - - - {{-1, 20}, {245, 461}} - - - 562 - - - - QSAAAEEgAABBoAAAQaAAAA - - - - 4370 - - - - 2304 - - - - 4352 - {248, 457} - - YES - - - -2147483392 - {{224, 0}, {16, 17}} - - - 3 - 2 - - 1 - MC44NzQ1MDk4MDM5IDAuODkwMTk2MDc4NCAwLjkxNzY0NzA1ODgAA - - - 17 - -700448768 - - - 4 - 15 - 0 - YES - 1 - 1 - - - {{1, 1}, {248, 457}} - - - - - 4 - - - - -2147483392 - {{234, 1}, {15, 442}} - - - _doScroller: - 0.48253275109170307 - - - - -2147483392 - {{1, 443}, {233, 15}} - - 1 - - _doScroller: - 0.99581589958159 - - - {{-1, 22}, {250, 459}} - - - 562 - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 258 - - - - 268 - {{-1, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - NSAddTemplate - - - - 200 - 25 - - - - - 268 - {{30, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - NSRemoveTemplate - - - - 200 - 25 - - - - - 268 - {{61, -1}, {32, 24}} - - YES - - 67239424 - 134348800 - - - - -2033958657 - 163 - - NSImage - check - - - - 200 - 25 - - - - - 268 - {{92, -1}, {32, 24}} - - YES - - -2076049856 - 134350848 - - LucidaGrande - 13 - 16 - - - -2038284033 - 163 - - - 400 - 75 - - - YES - - - 1048576 - 2147483647 - 1 - - NSImage - NSActionTemplate - - - - _popUpItemAction: - - - YES - - OtherViews - - - - - スニペットを読み込む... - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - スニペットを書き出す... - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - YES - 1 - YES - YES - 2 - - - - {244, 23} - - YES - YES - NO - 0 - - - {244, 480} - - NSView - - - - 258 - - - - 274 - - - - 272 - - - - 4370 - - - - 2304 - - - - 4352 - {395, 223} - - YES - - - 256 - {395, 17} - - - - - - -2147483392 - {{380, 0}, {16, 17}} - - - - - ImageAndTextCellColumn - 372 - 40 - 1000 - - 75628096 - 2048 - タイトル - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - - - - - 3 - YES - YES - - - - 3 - 2 - - - 17 - -1698693120 - - - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {395, 223}} - - - - - 4 - - - - -2147483392 - {{380, 17}, {15, 223}} - - - _doScroller: - 37 - 0.1947367936372757 - - - - -2147483392 - {{-100, -100}, {114, 15}} - - 1 - - _doScroller: - 0.77551020408163263 - - - - 2304 - - - - {{1, 0}, {395, 17}} - - - - - 4 - - - - {{-1, -5}, {397, 241}} - - - 530 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - {395, 235} - - NSView - - - - 272 - - - - 4370 - - - - 2304 - - - - 6418 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple PNG pasteboard type - Apple URL pasteboard type - CorePasteboardFlavorType 0x6D6F6F76 - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT Encapsulated PostScript v1.2 pasteboard type - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - NeXT font pasteboard type - NeXT ruler pasteboard type - WebURLsWithTitlesPboardType - public.url - - {{0, 2}, {380, 14}} - - - - - - content - - - - Helvetica - 13 - 16 - - - 4 - - - - - - - - - 134 - - - - 380 - 1 - - - 4003 - 0 - - - - - 6 - System - selectedTextBackgroundColor - - - - 6 - System - selectedTextColor - - - - - - - 1 - MCAwIDEAA - - - {8, -8} - 13 - - - - - - 6 - {775, 1e+07} - {223, 0} - - - - {380, 235} - - - - - - {4, -5} - 1 - - 4 - - - - 256 - {{380, 0}, {15, 220}} - - - _doScroller: - 1 - 0.85256409645080566 - - - - -2147483392 - {{-100, -100}, {87, 18}} - - 1 - - _doScroller: - 1 - 0.94565218687057495 - - - {395, 235} - - - 16 - - - - - - {{0, 245}, {395, 235}} - - NSView - - - {395, 480} - - 3 - SnippetEditorHorizontalDivider - - NO - - - - - - - - - - - 0 - NO - - - {{245, 0}, {395, 480}} - - NSView - - - {640, 480} - - YES - 2 - SnippetEditorVerticalDivider - - NO - - - - - - - - - - - 0 - NO - - - {640, 480} - - {{0, 0}, {1280, 1002}} - {1.79769e+308, 1.79769e+308} - SnippetEditorWindow - - - - - - - folderArrayController - - - - 152 - - - - managedObjectContext: snippetsController.managedObjectContext - - - - - - managedObjectContext: snippetsController.managedObjectContext - managedObjectContext - snippetsController.managedObjectContext - 2 - - - 153 - - - - managedObjectContext: snippetsController.managedObjectContext - - - - - - managedObjectContext: snippetsController.managedObjectContext - managedObjectContext - snippetsController.managedObjectContext - 2 - - - 157 - - - - snippetArrayController - - - - 160 - - - - delegate - - - - 194 - - - - predicate: filterPredicate - - - - - - predicate: filterPredicate - predicate - filterPredicate - - すべて - (index.description contains[c] $value) or (title contains[c] $value) or (content contains[c] $value) - - 2 - - - 207 - - - - predicate2: filterPredicate - - - - - - predicate2: filterPredicate - predicate2 - filterPredicate - - タイトル - title contains[c] $value - - - 2 - - - 208 - - - - predicate3: filterPredicate - - - - - - predicate3: filterPredicate - predicate3 - filterPredicate - - 内容 - content contains[c] $value - - - 2 - - - 209 - - - - dataSource - - - - 280 - - - - delegate - - - - 281 - - - - nextKeyView - - - - 282 - - - - folderTreeController - - - - 286 - - - - dataSource - - - - 299 - - - - delegate - - - - 300 - - - - folderOutlineView - - - - 301 - - - - value: arrangedObjects.nodeTitle - - - - - - value: arrangedObjects.nodeTitle - value - arrangedObjects.nodeTitle - 2 - - - 304 - - - - dataSource - - - - 305 - - - - delegate - - - - 306 - - - - nextKeyView - - - - 309 - - - - snippetTableView - - - - 310 - - - - value: arrangedObjects.title - - - - - - value: arrangedObjects.title - value - arrangedObjects.title - 2 - - - 311 - - - - contentSet: selection.snippets - - - - - - contentSet: selection.snippets - contentSet - selection.snippets - - NSDeletesObjectsOnRemove - - - 2 - - - 320 - - - - value: selection.content - - - - - - value: selection.content - value - selection.content - 2 - - - 321 - - - - addFolder: - - - - 322 - - - - window - - - - 323 - - - - removeFolder: - - - - 324 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 328 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 337 - - - - selectionIndexPaths: selectionIndexPaths - - - - - - selectionIndexPaths: selectionIndexPaths - selectionIndexPaths - selectionIndexPaths - - 2 - - - 339 - - - - remove: - - - - 395 - - - - enabled: canRemove - - - - - - enabled: canRemove - enabled - canRemove - 2 - - - 396 - - - - contentArray: sourceList - - - - - - contentArray: sourceList - contentArray - sourceList - 2 - - - 426 - - - - addSnippet: - - - - 443 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - 2 - - - 450 - - - - toggleFolderEnabled: - - - - 452 - - - - enabled: arrangedObjects.enabled - - - - - - enabled: arrangedObjects.enabled - enabled - arrangedObjects.enabled - 2 - - - 469 - - - - enabled: selectionIndexPath - - - - - - enabled: selectionIndexPath - enabled - selectionIndexPath - - NSValueTransformerName - NSIsNotNil - - 2 - - - 471 - - - - enabled: canAdd - - - - - - enabled: canAdd - enabled - canAdd - - NSValueTransformerName - NSIsNotNil - - 2 - - - 492 - - - - toggleSnippetEnabled: - - - - 504 - - - - enabled: hasFolders - - - - - - enabled: hasFolders - enabled - hasFolders - 2 - - - 506 - - - - exportSnippets: - - - - 507 - - - - importSnippets: - - - - 508 - - - - nextKeyView - - - - 509 - - - - nextKeyView - - - - 510 - - - - enabled: selection.folder - - - - - - enabled: selection.folder - enabled - selection.folder - - NSValueTransformerName - NSIsNotNil - - 2 - - - 517 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 156 - - - Snippet Array Controller - - - 192 - - - - - - - - - 193 - - - - - - - - 195 - - - - - - - - - - - - - - - 196 - - - - - - - - 197 - - - - - 198 - - - - - 199 - - - - - 201 - - - - - 204 - - - - - - - - 205 - - - - - 213 - - - - - - - - - 214 - - - - - - - - - - 215 - - - - - - - - 216 - - - - - - - - - - - 226 - - - - - - - - - 227 - - - - - - - - 228 - - - - - - - - 238 - - - - - - - - - - 239 - - - - - 240 - - - - - 241 - - - - - 268 - - - - - - - - 269 - - - - - 270 - - - - - - - - 271 - - - - - 272 - - - - - - - - 273 - - - - - 274 - - - - - - - - 275 - - - - - - - - 276 - - - - - - - - - - 277 - - - - - 278 - - - - - 279 - - - - - 217 - - - - - - - - - - 220 - - - - - - 219 - - - - - 218 - - - - - 285 - - - Folder Tree Controller - - - 290 - - - - - - - - - - 291 - - - - - 292 - - - - - 293 - - - - - - - - 295 - - - - - - - - 298 - - - - - 394 - - - - - 441 - - - - - 472 - - - - - 151 - - - Folder Array Controller - - - 229 - - - - - - - - - - - 230 - - - - - 231 - - - - - 232 - - - - - - - - 235 - - - - - - - - 236 - - - - - 233 - - - - - - - IndexedArrayController - com.apple.InterfaceBuilder.CocoaPlugin - IndexedArrayController - com.apple.InterfaceBuilder.CocoaPlugin - {{215, 339}, {640, 480}} - com.apple.InterfaceBuilder.CocoaPlugin - {{215, 339}, {640, 480}} - - {1.79769e+308, 1.79769e+308} - {0, 0} - com.apple.InterfaceBuilder.CocoaPlugin - {{227, 819}, {616, 0}} - 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.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Add Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - - ToolTip - - ToolTip - - Delete Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - - ToolTip - - ToolTip - - Enable/Disable Folder - - - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - {{296, 308}, {156, 54}} - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.brandonwalkin.BWToolkit - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - ImageAndTextCell - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - DeleteSnippet - com.apple.InterfaceBuilder.CocoaPlugin - AddSnippet - com.apple.InterfaceBuilder.CocoaPlugin - CheckSnippet - - - - - - 523 - - - - - ImageAndTextCell - NSTextFieldCell - - IBProjectSource - Source/CocoaExtensions/ImageAndTextCell.h - - - - IndexedArrayController - NSArrayController - - IBProjectSource - Source/IndexedArrayController.h - - - - SnippetEditorController - NSWindowController - - id - id - id - id - id - id - id - - - - addFolder: - id - - - addSnippet: - id - - - exportSnippets: - id - - - importSnippets: - id - - - removeFolder: - id - - - toggleFolderEnabled: - id - - - toggleSnippetEnabled: - id - - - - IndexedArrayController - NSOutlineView - NSTreeController - IndexedArrayController - NSTableView - - - - folderArrayController - IndexedArrayController - - - folderOutlineView - NSOutlineView - - - folderTreeController - NSTreeController - - - snippetArrayController - IndexedArrayController - - - snippetTableView - NSTableView - - - - IBProjectSource - Source/SnippetEditorController.h - - - - - - BWAnchoredButton - NSButton - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButton.h - - - - BWAnchoredButtonBar - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButtonBar.h - - - - BWAnchoredButtonCell - NSButtonCell - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredButtonCell.h - - - - BWAnchoredPopUpButton - NSPopUpButton - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredPopUpButton.h - - - - BWAnchoredPopUpButtonCell - NSPopUpButtonCell - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWAnchoredPopUpButtonCell.h - - - - BWSplitView - NSSplitView - - toggleCollapse: - id - - - toggleCollapse: - - toggleCollapse: - id - - - - IBFrameworkSource - BWToolkitFramework.framework/Headers/BWSplitView.h - - - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSApplication - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSApplication+BWAdditions.h - - - - NSArrayController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSArrayController.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSController - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSController.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSManagedObjectContext - NSObject - - IBFrameworkSource - CoreData.framework/Headers/NSManagedObjectContext.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMenuItemCell - NSButtonCell - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItemCell.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderCell.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRRecorderControl.h - - - - NSObject - - IBFrameworkSource - ShortcutRecorder.framework/Headers/SRValidator.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSObjectController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSObjectController.h - - - - NSOutlineView - NSTableView - - - - NSPopUpButton - NSButton - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButton.h - - - - NSPopUpButtonCell - NSMenuItemCell - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButtonCell.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSearchField - NSTextField - - IBFrameworkSource - AppKit.framework/Headers/NSSearchField.h - - - - NSSearchFieldCell - NSTextFieldCell - - IBFrameworkSource - AppKit.framework/Headers/NSSearchFieldCell.h - - - - NSSplitView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSSplitView.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableHeaderView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTableHeaderView.h - - - - NSTableView - NSControl - - - - NSText - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSText.h - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSTextView - NSText - - IBFrameworkSource - AppKit.framework/Headers/NSTextView.h - - - - NSToolbar - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbar.h - - - - NSToolbarItem - NSObject - - - - NSTreeController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSTreeController.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSView - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSView+BWAdditions.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - BWToolkitFramework.framework/Headers/NSWindow+BWAdditions.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - showWindow: - - showWindow: - id - - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - YES - ../ClipMenu.xcodeproj - 3 - - {32, 32} - {32, 32} - {32, 32} - {15, 15} - {8, 8} - {9, 8} - {7, 2} - {8, 8} - {32, 32} - {8, 8} - - - diff --git a/README.md b/README.md index 7465bd3..39dbf80 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,75 @@ -ClipMenu -======== -A clipboard manager for Mac OS X. +# ClipMenu icon ClipMenu -**New ClipMenu, completely rebuilt using Swift language, is now under development. Further information is coming soon!** +ClipMenu is a macOS clipboard manager rebuilt in Swift (SwiftUI + SwiftData). -![ClipMenu](./screenshot.jpg) +![ClipMenu Screenshot](screenshot.jpg) -## Distribution +## Installation -If you distribute derived work, especially in the Mac App Store, I ask you to follow two rules: +- Download installer: [ClipMenu.dmg](dist/ClipMenu.dmg) +- Open the DMG and install `ClipMenu.app` -1. **Don't use "ClipMenu" as your product name.** -2. **Follow the MIT license terms.** +## What Is Updated From The Original -Thank you for your cooperation. +This repository now reflects a fully modernized implementation of ClipMenu. Major updates include: -Target environments -------------------- +- Replaced legacy polling-style clipboard handling with an event-driven clipboard pipeline. +- Adopted Combine-based publishers/observation in the app flow for reactive updates. +- Migrated persistence to SwiftData models and services. +- Completed end-to-end implementation of the Actions menu, including action execution wiring in the modern app. +- Rebuilt the app architecture in Swift with SwiftUI scenes and a generated Xcode project workflow. -* Mac OS X 10.5 - 10.6 -* Xcode 3.2 -* Manual reference counting +## Huge Thanks -Dependencies ------------- -The source code is dependent on some libraries. You have to download and install them if you want to compile, run, or test the source code. +A huge thank you to Naotaka Morimoto, the original author of ClipMenu. -* [PTHotKey](http://www.rogueamoeba.com/utm/posts/Random/Homegrown_Developer_Tools-2004-07-14-12-00) by Quentin D. Carnicelli -* [Shortcut Recorder](http://code.google.com/p/shortcutrecorder/) by contributors to ShortcutRecorder -* [Sparkle](http://sparkle.andymatuschak.org/) by Andy Matuschak -* [DBPrefsWindowController](http://www.mere-mortal-software.com/blog/sourcecode.php) by Dave Batton -* [Google Toolbox for Mac](http://code.google.com/p/google-toolbox-for-mac/) by Google Inc. -* [BWToolkit](http://www.brandonwalkin.com/bwtoolkit/) by Brandon Walkin +ClipMenu has helped many users for years, and this modernization work stands on top of that original design and effort. -Author ------- +## Current Stack -Naotaka Morimoto ([@naotakaM](http://twitter.com/naotakaM)) +- Language: Swift 5.9+ +- Platform: macOS 14+ +- Build system: XcodeGen (`project.yml`) +- App type: menu bar app (`LSUIElement`) +- Dependency: `KeyboardShortcuts` -License -------- -ClipMenu is available under the MIT license. See the LICENSE file for more info. +## Build -Icons are copyrighted by their respective authors. +Prerequisites: + +```sh +xcode-select -p +brew install xcodegen +``` + +Generate project: + +```sh +xcodegen generate +``` + +Build (Debug): + +```sh +xcodebuild -project ClipMenu.xcodeproj -scheme ClipMenu -configuration Debug build \ + CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO +``` + +For detailed commands and troubleshooting, see `BUILD.md`. + +## Repository Cleanup Status + +- Legacy Objective-C source and historical release tooling were removed from the repository after migration completion. +- Historical Sparkle/appcast release scripts are no longer part of this project. +- Release and documentation flow is now maintained directly in Markdown docs in this repository. + +## Distribution Note + +If you distribute derived work: + +1. Do not use `ClipMenu` as your product name. +2. Follow the MIT license terms. + +## License + +ClipMenu is available under the MIT license. See `LICENSE` for details. diff --git a/resource/script/action/Case/Capitalize.js b/Resources/scripts/action/Case/Capitalize.js similarity index 100% rename from resource/script/action/Case/Capitalize.js rename to Resources/scripts/action/Case/Capitalize.js diff --git a/resource/script/action/Case/Title Case.js b/Resources/scripts/action/Case/Title Case.js similarity index 100% rename from resource/script/action/Case/Title Case.js rename to Resources/scripts/action/Case/Title Case.js diff --git a/resource/script/action/Case/UPPERCASE.js b/Resources/scripts/action/Case/UPPERCASE.js similarity index 100% rename from resource/script/action/Case/UPPERCASE.js rename to Resources/scripts/action/Case/UPPERCASE.js diff --git a/resource/script/action/Case/lowercase.js b/Resources/scripts/action/Case/lowercase.js similarity index 100% rename from resource/script/action/Case/lowercase.js rename to Resources/scripts/action/Case/lowercase.js diff --git a/resource/script/action/Collapse Spaces.js b/Resources/scripts/action/Collapse Spaces.js similarity index 100% rename from resource/script/action/Collapse Spaces.js rename to Resources/scripts/action/Collapse Spaces.js diff --git a/resource/script/action/Crypt/Calculate MD5 hash.js b/Resources/scripts/action/Crypt/Calculate MD5 hash.js similarity index 100% rename from resource/script/action/Crypt/Calculate MD5 hash.js rename to Resources/scripts/action/Crypt/Calculate MD5 hash.js diff --git a/resource/script/action/Crypt/Calculate SHA-1 hash.js b/Resources/scripts/action/Crypt/Calculate SHA-1 hash.js similarity index 100% rename from resource/script/action/Crypt/Calculate SHA-1 hash.js rename to Resources/scripts/action/Crypt/Calculate SHA-1 hash.js diff --git a/resource/script/action/Crypt/Decode from Base64.js b/Resources/scripts/action/Crypt/Decode from Base64.js similarity index 100% rename from resource/script/action/Crypt/Decode from Base64.js rename to Resources/scripts/action/Crypt/Decode from Base64.js diff --git a/resource/script/action/Crypt/Encode to Base64.js b/Resources/scripts/action/Crypt/Encode to Base64.js similarity index 100% rename from resource/script/action/Crypt/Encode to Base64.js rename to Resources/scripts/action/Crypt/Encode to Base64.js diff --git a/resource/script/action/HTML/Convert Character to Decimal.js b/Resources/scripts/action/HTML/Convert Character to Decimal.js similarity index 100% rename from resource/script/action/HTML/Convert Character to Decimal.js rename to Resources/scripts/action/HTML/Convert Character to Decimal.js diff --git a/resource/script/action/HTML/Convert Decimal to Character.js b/Resources/scripts/action/HTML/Convert Decimal to Character.js similarity index 100% rename from resource/script/action/HTML/Convert Decimal to Character.js rename to Resources/scripts/action/HTML/Convert Decimal to Character.js diff --git a/resource/script/action/HTML/Convert Markdown to HTML.js b/Resources/scripts/action/HTML/Convert Markdown to HTML.js similarity index 100% rename from resource/script/action/HTML/Convert Markdown to HTML.js rename to Resources/scripts/action/HTML/Convert Markdown to HTML.js diff --git a/resource/script/action/HTML/Decode URI component.js b/Resources/scripts/action/HTML/Decode URI component.js similarity index 100% rename from resource/script/action/HTML/Decode URI component.js rename to Resources/scripts/action/HTML/Decode URI component.js diff --git a/resource/script/action/HTML/Encode URI component.js b/Resources/scripts/action/HTML/Encode URI component.js similarity index 100% rename from resource/script/action/HTML/Encode URI component.js rename to Resources/scripts/action/HTML/Encode URI component.js diff --git a/resource/script/action/HTML/Escape HTML characters.js b/Resources/scripts/action/HTML/Escape HTML characters.js similarity index 100% rename from resource/script/action/HTML/Escape HTML characters.js rename to Resources/scripts/action/HTML/Escape HTML characters.js diff --git a/resource/script/action/HTML/Strip Tags.js b/Resources/scripts/action/HTML/Strip Tags.js similarity index 100% rename from resource/script/action/HTML/Strip Tags.js rename to Resources/scripts/action/HTML/Strip Tags.js diff --git a/resource/script/action/HTML/Surround with Tags....js b/Resources/scripts/action/HTML/Surround with Tags....js similarity index 100% rename from resource/script/action/HTML/Surround with Tags....js rename to Resources/scripts/action/HTML/Surround with Tags....js diff --git a/resource/script/action/HTML/Unescape HTML characters.js b/Resources/scripts/action/HTML/Unescape HTML characters.js similarity index 100% rename from resource/script/action/HTML/Unescape HTML characters.js rename to Resources/scripts/action/HTML/Unescape HTML characters.js diff --git a/resource/script/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js b/Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js similarity index 100% rename from resource/script/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js rename to Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js diff --git a/resource/script/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js b/Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js similarity index 100% rename from resource/script/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js rename to Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js diff --git a/resource/script/action/Japanese/Convert Hiragana to Katakana.js b/Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js similarity index 100% rename from resource/script/action/Japanese/Convert Hiragana to Katakana.js rename to Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js diff --git a/resource/script/action/Japanese/Convert Katakana to Hiragana.js b/Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js similarity index 100% rename from resource/script/action/Japanese/Convert Katakana to Hiragana.js rename to Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js diff --git a/resource/script/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js b/Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js similarity index 100% rename from resource/script/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js rename to Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js diff --git a/resource/script/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js b/Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js similarity index 100% rename from resource/script/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js rename to Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js diff --git a/resource/script/action/Reverse.js b/Resources/scripts/action/Reverse.js similarity index 100% rename from resource/script/action/Reverse.js rename to Resources/scripts/action/Reverse.js diff --git "a/resource/script/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" "b/Resources/scripts/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" rename to "Resources/scripts/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" diff --git "a/resource/script/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" "b/Resources/scripts/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" rename to "Resources/scripts/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" diff --git "a/resource/script/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" "b/Resources/scripts/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" rename to "Resources/scripts/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" diff --git "a/resource/script/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" "b/Resources/scripts/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" rename to "Resources/scripts/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" diff --git "a/resource/script/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" "b/Resources/scripts/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" rename to "Resources/scripts/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" diff --git "a/resource/script/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" "b/Resources/scripts/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" rename to "Resources/scripts/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" diff --git "a/resource/script/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" "b/Resources/scripts/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" similarity index 100% rename from "resource/script/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" rename to "Resources/scripts/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" diff --git "a/resource/script/action/Surround with/\" \".js" "b/Resources/scripts/action/Surround with/\" \".js" similarity index 100% rename from "resource/script/action/Surround with/\" \".js" rename to "Resources/scripts/action/Surround with/\" \".js" diff --git a/resource/script/action/Surround with/' '.js b/Resources/scripts/action/Surround with/' '.js similarity index 100% rename from resource/script/action/Surround with/' '.js rename to Resources/scripts/action/Surround with/' '.js diff --git a/resource/script/action/Surround with/( ).js b/Resources/scripts/action/Surround with/( ).js similarity index 100% rename from resource/script/action/Surround with/( ).js rename to Resources/scripts/action/Surround with/( ).js diff --git a/resource/script/action/Surround with/< >.js b/Resources/scripts/action/Surround with/< >.js similarity index 100% rename from resource/script/action/Surround with/< >.js rename to Resources/scripts/action/Surround with/< >.js diff --git a/resource/script/action/Surround with/[ ].js b/Resources/scripts/action/Surround with/[ ].js similarity index 100% rename from resource/script/action/Surround with/[ ].js rename to Resources/scripts/action/Surround with/[ ].js diff --git a/resource/script/action/Surround with/` `.js b/Resources/scripts/action/Surround with/` `.js similarity index 100% rename from resource/script/action/Surround with/` `.js rename to Resources/scripts/action/Surround with/` `.js diff --git a/resource/script/action/Surround with/{ }.js b/Resources/scripts/action/Surround with/{ }.js similarity index 100% rename from resource/script/action/Surround with/{ }.js rename to Resources/scripts/action/Surround with/{ }.js diff --git a/resource/script/action/Trim/LTrim.js b/Resources/scripts/action/Trim/LTrim.js similarity index 100% rename from resource/script/action/Trim/LTrim.js rename to Resources/scripts/action/Trim/LTrim.js diff --git a/resource/script/action/Trim/RTrim.js b/Resources/scripts/action/Trim/RTrim.js similarity index 100% rename from resource/script/action/Trim/RTrim.js rename to Resources/scripts/action/Trim/RTrim.js diff --git a/resource/script/action/Trim/Trim.js b/Resources/scripts/action/Trim/Trim.js similarity index 100% rename from resource/script/action/Trim/Trim.js rename to Resources/scripts/action/Trim/Trim.js diff --git a/resource/script/lib/JS-methods/char.js b/Resources/scripts/lib/JS-methods/char.js similarity index 100% rename from resource/script/lib/JS-methods/char.js rename to Resources/scripts/lib/JS-methods/char.js diff --git a/resource/script/lib/JS-methods/string.js b/Resources/scripts/lib/JS-methods/string.js similarity index 100% rename from resource/script/lib/JS-methods/string.js rename to Resources/scripts/lib/JS-methods/string.js diff --git a/resource/script/lib/fhconvert.js b/Resources/scripts/lib/fhconvert.js similarity index 100% rename from resource/script/lib/fhconvert.js rename to Resources/scripts/lib/fhconvert.js diff --git a/resource/script/lib/inflection.js b/Resources/scripts/lib/inflection.js similarity index 100% rename from resource/script/lib/inflection.js rename to Resources/scripts/lib/inflection.js diff --git a/resource/script/lib/showdown.js b/Resources/scripts/lib/showdown.js similarity index 100% rename from resource/script/lib/showdown.js rename to Resources/scripts/lib/showdown.js diff --git a/resource/script/lib/v8cgi/html.js b/Resources/scripts/lib/v8cgi/html.js similarity index 100% rename from resource/script/lib/v8cgi/html.js rename to Resources/scripts/lib/v8cgi/html.js diff --git a/resource/script/lib/v8cgi/util.js b/Resources/scripts/lib/v8cgi/util.js similarity index 100% rename from resource/script/lib/v8cgi/util.js rename to Resources/scripts/lib/v8cgi/util.js diff --git a/Snippets.xcdatamodel/elements b/Snippets.xcdatamodel/elements deleted file mode 100644 index a9ed1da..0000000 Binary files a/Snippets.xcdatamodel/elements and /dev/null differ diff --git a/Snippets.xcdatamodel/layout b/Snippets.xcdatamodel/layout deleted file mode 100644 index 108accd..0000000 Binary files a/Snippets.xcdatamodel/layout and /dev/null differ diff --git a/Source/ActionController.h b/Source/ActionController.h deleted file mode 100644 index 0f78976..0000000 --- a/Source/ActionController.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// ActionController.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/01/20. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import -#import - -extern NSString *const CMBuiltinActionTypeKey; -extern NSString *const CMJavaScriptActionTypeKey; - -//extern NSString *const nodeTitleKey; -//extern NSString *const isLeafKey; -//extern NSString *const childrenKey; - -@class ActionNodeFactory, BuiltInActionController, Clip; - -@interface ActionController : NSObject -{ - WebView *webView; - - ActionNodeFactory *actionNodeFactory; - BuiltInActionController *builtInActionController; - - NSMutableArray *actionNodes; - NSArray *builtinActionNodes; - NSArray *bundledActionNodes; - NSArray *usersActionNodes; - - NSInteger selectedClipTag; - NSManagedObject *selectedSnippet; - - ProcessSerialNumber frontPSN; -} -@property (nonatomic, retain) WebView *webView; -@property (nonatomic, retain) ActionNodeFactory *actionNodeFactory; -@property (nonatomic, retain) BuiltInActionController *builtInActionController; -@property (nonatomic, copy) NSMutableArray *actionNodes; -@property (nonatomic, retain) NSArray *builtinActionNodes; -@property (nonatomic, retain) NSArray *bundledActionNodes; -@property (nonatomic, retain) NSArray *usersActionNodes; -@property (nonatomic, assign) NSInteger selectedClipTag; -@property (nonatomic, assign) NSManagedObject *selectedSnippet; - -+ (ActionController *)sharedInstance; -+ (NSMutableArray *)defaultActions; - -- (void)prepareActions; -- (BOOL)saveActions; -- (void)loadActions; - -- (void)invokeCommandForKey:(NSString *)key toTarget:(id)target; -//- (NSString *)invokeScript:(NSString *)scriptPath toText:(NSString *)clipText; -- (Clip *)invokeScript:(NSString *)scriptPath toClip:(Clip *)clip; -- (void)clearSelection; - - -//- (BOOL)moveCurrentProcessToForeground; -- (void)keepCurrentFrontProcessAndActivate; -- (BOOL)restorePreviousFrontProcess; - -@end diff --git a/Source/ActionController.m b/Source/ActionController.m deleted file mode 100644 index 0291b00..0000000 --- a/Source/ActionController.m +++ /dev/null @@ -1,743 +0,0 @@ -// -// ActionController.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/01/20. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionController.h" -#import "ActionNodeFactory.h" -#import "ActionNode.h" -#import "ActionFactory.h" -#import "BuiltInActionController.h" -#import "JavaScriptSupport.h" -#import "ClipsController.h" -#import "Clip.h" -#import "ScriptableClip.h" -#import "constants.h" -#import "CMUtilities.h" - - -#pragma mark - - -static ActionController *sharedInstance = nil; - -NSString *const scriptExceptionKey = @"__scriptException"; -NSString *const namespaceKey = @"ClipMenu"; -NSString *const clipKey = @"clip"; -NSString *const clipTextKey = @"clipText"; - -/* - fileInfo - */ -NSString *const filenameKey = @"filename"; -NSString *const filePathKey = @"filePath"; -NSString *const resourcePathSeparator = @"ClipMenu.app/Contents/Resources/"; -NSString *const saveFileName = @"actions.plist"; - - -@interface ActionController () -- (void)_prepareDefaultActionNodes; -- (void)_prepareBuiltinActionNodes; -- (void)_prepareBundledScriptActionNodes; -- (void)_prepareUsersScriptActionNodes; -- (NSArray *)_makeScriptNodesWithWalkingDirectory:(NSString *)directoryPath; -- (ActionNode *)_javaScriptNodeWithName:(NSString *)name; -- (NSDictionary *)_javaScriptFileInfoWithName:(NSString *)name; -- (NSString *)_saveFilePath; - -//- (void)_prepareCommands; -- (NSString *)_loadScript:(NSString *)filePath; - -- (void)_alertPanelWithTitle:(NSString *)title messageText:(NSString *)messageText; -- (id)_init; -@end - -#pragma mark - - -@implementation ActionController - -@synthesize webView; -@synthesize actionNodeFactory; -@synthesize builtInActionController; -@synthesize actionNodes; -@synthesize builtinActionNodes; -@synthesize bundledActionNodes; -@synthesize usersActionNodes; -@synthesize selectedClipTag; -@synthesize selectedSnippet; - -#pragma mark Initialize - -+ (void)initialize -{ - if (sharedInstance == nil) { - sharedInstance = [[self alloc] _init]; - } -} - -+ (ActionController *)sharedInstance -{ - return [[sharedInstance retain] autorelease]; -} - -- (id)init -{ - NSAssert(self != sharedInstance, @"Should never send init to the singleton instance"); - - [self release]; - [sharedInstance retain]; - return sharedInstance; -} - -- (id)_init -{ - self = [super init]; - if (self) { - WebView *wv = [[WebView alloc] init]; - // [wv setFrameLoadDelegate:self]; - [wv setPolicyDelegate:self]; - [[wv mainFrame] loadHTMLString:kEmptyString baseURL:nil]; - [self setValue:wv forKey:@"webView"]; - [wv release], wv = nil; - - actionNodeFactory = [[ActionNodeFactory alloc] init]; - builtInActionController = [[BuiltInActionController alloc] init]; - - // [self _prepareCommands]; - } - return self; -} - -- (void)dealloc -{ - [webView release], webView = nil; - [actionNodeFactory release], actionNodeFactory = nil; - [actionNodes release], actionNodes = nil; - [builtinActionNodes release], builtinActionNodes = nil; - [bundledActionNodes release], bundledActionNodes = nil; - [usersActionNodes release], usersActionNodes = nil; - [builtInActionController release], builtInActionController = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark Class Methods - -+ (NSMutableArray *)defaultActions -{ - NSMutableArray *newActions = [NSMutableArray array]; - - NSMutableDictionary *removeAction = [NSMutableDictionary dictionaryWithObjectsAndKeys: - @"removeAction", @"name", - kEmptyString, @"path", - nil]; - [newActions addObject:removeAction]; - - return newActions; -} - -#pragma mark - -#pragma mark Accessors - -#pragma mark - Write - - -- (void)setActionNodes:(NSMutableArray *)newNodes -{ - if (actionNodes != newNodes) { - [actionNodes autorelease]; -// actionNodes = [[NSMutableArray alloc] initWithArray:newNodes]; - actionNodes = [newNodes mutableCopy]; - } -} - -#pragma mark - -#pragma mark Delegate -//#pragma mark - WebFrameLoadDelegate Protocol - -// -//- (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject -//{ -// NSLog(@"WebFrameLoadDelegate"); -//} - -#pragma mark - WebPolicyDelegate Protocol - - -/* Prevent accessing external resources */ -- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener -{ - [listener ignore]; -} - -#pragma mark - -#pragma mark Public - -- (void)prepareActions -{ - [self _prepareBuiltinActionNodes]; - [self _prepareBundledScriptActionNodes]; - [self _prepareUsersScriptActionNodes]; -} - -- (BOOL)saveActions -{ - NSString *path = [CMUtilities applicationSupportFolder]; - if (![CMUtilities prepareSaveToPath:path]) { - return NO; - } - -// return [NSKeyedArchiver archiveRootObject:actionNodes toFile:[self _saveFilePath]]; // old format - - NSMutableArray *plistArray = [NSMutableArray array]; - - for (ActionNode *node in actionNodes) { -// NSLog(@"node: %@", [node dictionaryRepresentation]); - - [plistArray addObject:[node dictionaryRepresentation]]; - } - - NSString *plistPath = [path stringByAppendingPathComponent:saveFileName]; - NSString *errorDescription; - - NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:plistArray - format:NSPropertyListXMLFormat_v1_0 - errorDescription:&errorDescription]; - - if (xmlData) { - [xmlData writeToFile:plistPath atomically:YES]; - return YES; - } - else { - NSLog(@"%@", errorDescription); - [errorDescription release], errorDescription = nil; - return NO; - } -} - -- (void)loadActions -{ - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *path = [CMUtilities applicationSupportFolder]; - NSString *plistPath = [path stringByAppendingPathComponent:saveFileName]; - - /* Property List format */ - if ([fileManager fileExistsAtPath:plistPath]) { - NSData *plistData = [NSData dataWithContentsOfFile:plistPath]; - if (!plistData) { -// NSLog(@"loadData is nil"); - [self _prepareDefaultActionNodes]; - return; - } - - NSString *errorDescription; - - NSArray *plist = [NSPropertyListSerialization propertyListFromData:plistData - mutabilityOption:NSPropertyListImmutable - format:NULL - errorDescription:&errorDescription]; - if (plist) { - NSMutableArray *unarhivedNodes = [NSMutableArray array]; - - for (NSDictionary *dict in plist) { - ActionNode *node = [[ActionNode alloc] initWithDictionary:dict]; - [unarhivedNodes addObject:node]; - [node release], node = nil; - } - - [self setActionNodes:unarhivedNodes]; - } - else { - NSLog(@"%@", errorDescription); - [errorDescription release], errorDescription = nil; - } - } - /* old format */ - else if ([fileManager fileExistsAtPath:[self _saveFilePath]]) { - NSMutableArray *loadedData = [NSKeyedUnarchiver unarchiveObjectWithFile:[self _saveFilePath]]; - if (loadedData == nil) { - // NSLog(@"loadData is nil"); - [self _prepareDefaultActionNodes]; - - return; - } - - [self setValue:loadedData forKey:@"actionNodes"]; - } - /* first startup */ - else { -// NSLog(@"loadData is nil"); - [self _prepareDefaultActionNodes]; - return; - } -} - -- (void)invokeCommandForKey:(NSString *)key toTarget:(id)target -{ - NSDictionary *actions = [builtInActionController actions]; - NSDictionary *action = [actions objectForKey:key]; - SEL sel = NSSelectorFromString([action objectForKey:@"actionName"]); - if (!sel) { - return; - } - - [builtInActionController performSelector:sel withObject:target]; -} - -//- (NSString *)invokeScript:(NSString *)scriptPath toText:(NSString *)clipText -//{ -// if (!clipText || [clipText length] == 0) { -// return nil; -// } -// -// NSString *scriptContent = [self _loadScript:scriptPath]; -// if (scriptContent == nil) { -// [self _alertPanelWithTitle:NSLocalizedString(@"Unable to load script", nil) -// messageText:NSLocalizedString(@"Your script file does not exist.", nil)]; -// return nil; -// } -// -//// NSString *script = [NSString stringWithFormat: -//// @"try { %@ } catch (e) { %@ = e.toString() }", -//// scriptContent, -//// scriptExceptionKey]; -// -//// NSString *script = [NSString stringWithFormat: -//// @"function __wrapper() { try { %@ } catch (e) { %@ = e.toString(); return; } } __wrapper();", -//// scriptContent, -//// scriptExceptionKey]; -// -// NSString *script = [NSString stringWithFormat: -// @"function __wrapper(clipText) { try { %@ } catch (e) { %@ = e.toString(); return; } }", -// scriptContent, -// scriptExceptionKey]; -// -// /* setup WebScriptObject */ -// WebScriptObject *scriptObject = [webView windowScriptObject]; -// -//// [scriptObject setValue:clipText forKey:clipTextKey]; -// [scriptObject setValue:kEmptyString forKey:scriptExceptionKey]; -// -// JavaScriptSupport *jss = [[[JavaScriptSupport alloc] initWithScriptObject:scriptObject] autorelease]; -// [scriptObject setValue:jss forKey:namespaceKey]; -// -// /* evaluate JavaScript */ -//// id scriptResult = [scriptObject evaluateWebScript:script]; -// -// [scriptObject evaluateWebScript:script]; -// -// NSArray *args = [NSArray arrayWithObjects:clipText, nil]; -// id scriptResult = [scriptObject callWebScriptMethod:@"__wrapper" withArguments:args]; -// -// if (!scriptResult) { -// [self _alertPanelWithTitle:NSLocalizedString(@"Script Error", nil) -// messageText:NSLocalizedString(@"Failed to evaluate script", nil)]; -// return nil; -// } -// -//// NSLog(@"scriptResult: %@", [scriptResult className]); -// -// /* Error check */ -// if (![[scriptObject valueForKey:scriptExceptionKey] isEqualToString:kEmptyString]) { -// [self _alertPanelWithTitle:NSLocalizedString(@"Script Exception Raised", nil) -// messageText:[scriptObject valueForKey:scriptExceptionKey]]; -// return nil; -// } -// else if ([scriptResult isMemberOfClass:[WebUndefined class]]) { -//// [self _alertPanelWithTitle:NSLocalizedString(@"Script Error", nil) -////// messageText:@"The returned value is the JavaScript \"undefined\"."]; -//// messageText:NSLocalizedString(@"Script error has occurred", nil)]; -// return nil; -// } -// -// /* Restore process if needed */ -// [self restorePreviousFrontProcess]; -// -// NSString *result = ([scriptResult respondsToSelector:@selector( stringValue )]) -// ? [scriptResult stringValue] -// : scriptResult; -// -// return result; -//} - -- (Clip *)invokeScript:(NSString *)scriptPath toClip:(Clip *)clip -{ - if (clip == nil) { - return nil; - } - - NSString *clipText = [clip stringValue]; - if (!clipText || [clipText length] == 0) { - return nil; - } - - ScriptableClip *scriptableClip = [[[ScriptableClip alloc] initWithClip:clip] autorelease]; - - NSString *scriptContent = [self _loadScript:scriptPath]; - if (scriptContent == nil) { - [self _alertPanelWithTitle:NSLocalizedString(@"Unable to load script", nil) - messageText:NSLocalizedString(@"Your script file does not exist.", nil)]; - return nil; - } - -// NSString *script = [NSString stringWithFormat: -// @"function __wrapper(clipText) { try { %@ } catch (e) { %@ = e.toString(); return; } }", -// scriptContent, -// scriptExceptionKey]; - - NSString *script = [NSString stringWithFormat: - @"function __wrapper() { try { %@ } catch (e) { %@ = e.toString(); return; } }", - scriptContent, - scriptExceptionKey]; - - /* Setup WebScriptObject */ - WebScriptObject *scriptObject = [webView windowScriptObject]; - - [scriptObject setValue:kEmptyString forKey:scriptExceptionKey]; - [scriptObject setValue:clipText forKey:clipTextKey]; - [scriptObject setValue:scriptableClip forKey:clipKey]; - - JavaScriptSupport *jss = [[[JavaScriptSupport alloc] initWithScriptObject:scriptObject] autorelease]; - [scriptObject setValue:jss forKey:namespaceKey]; - - /* Evaluate JavaScript */ - id scriptResult; - scriptResult = [scriptObject evaluateWebScript:script]; - - if (!scriptResult) { - [self _alertPanelWithTitle:NSLocalizedString(@"Script Error", nil) - messageText:NSLocalizedString(@"Failed to evaluate script", nil)]; - return nil; - } - -// NSArray *args = [NSArray arrayWithObjects:clipText, nil]; -// scriptResult = [scriptObject callWebScriptMethod:@"__wrapper" withArguments:args]; - - scriptResult = [scriptObject callWebScriptMethod:@"__wrapper" withArguments:nil]; - - if (!scriptResult) { - [self _alertPanelWithTitle:NSLocalizedString(@"Script Error", nil) - messageText:NSLocalizedString(@"Failed to evaluate script", nil)]; - return nil; - } - -// NSLog(@"scriptResult: %@", [scriptResult className]); - - -// id lengthObject = [scriptResult valueForKey:@"length"]; -// NSUInteger length = ([lengthObject isKindOfClass:[NSNumber class]]) -// ? [lengthObject unsignedIntegerValue] : 0; -// NSMutableArray *arrayFromScript = [[NSMutableArray alloc] initWithCapacity:length]; -// for (NSInteger i = 0; i < length; i++) { -// id element = [scriptResult webScriptValueAtIndex:i]; -// if (element) { -// [arrayFromScript addObject:element]; -// } -// } -// NSLog(@"scriptResult: %@", arrayFromScript); -// [arrayFromScript release], arrayFromScript = nil; - -// NSLog(@"scriptResult: %@", [scriptResult valueForKey:@"0"]); -// NSLog(@"scriptResult: %@", [scriptResult valueForKey:@"color"]); - - - /* Error check */ - if (![[scriptObject valueForKey:scriptExceptionKey] isEqualToString:kEmptyString]) { - [self _alertPanelWithTitle:NSLocalizedString(@"Script Exception Raised", nil) - messageText:[scriptObject valueForKey:scriptExceptionKey]]; - return nil; - } - else if ([scriptResult isMemberOfClass:[WebUndefined class]]) { - // [self _alertPanelWithTitle:NSLocalizedString(@"Script Error", nil) - //// messageText:@"The returned value is the JavaScript \"undefined\"."]; - // messageText:NSLocalizedString(@"Script error has occurred", nil)]; - return nil; - } - - /* Restore process if needed */ - [self restorePreviousFrontProcess]; - - /* Return Clip */ - if ([scriptResult isKindOfClass:[ScriptableClip class]]) { - return [(ScriptableClip *)scriptResult clip]; - } - - NSString *result = ([scriptResult respondsToSelector:@selector( stringValue )]) - ? [scriptResult stringValue] - : scriptResult; - - Clip *newClip = [Clip clipWithString:result]; - - return newClip; -} - -- (void)clearSelection -{ - [self setSelectedClipTag:0]; - [self setSelectedSnippet:nil]; -} - - -#pragma mark - Process - - -//- (BOOL)moveCurrentProcessToForeground -//{ -// ProcessSerialNumber psn; -// -// GetCurrentProcess(&psn); -// TransformProcessType(&psn, kProcessTransformToForegroundApplication); -// OSErr osError = SetFrontProcess(&psn); -// if (osError != noErr) { -// return NO; -// } -// return YES; -//} - -- (void)keepCurrentFrontProcessAndActivate -{ - GetFrontProcess(&frontPSN); // Keep the most front of process - [NSApp activateIgnoringOtherApps:YES]; -} - -- (BOOL)restorePreviousFrontProcess -{ - if (frontPSN.lowLongOfPSN == kNoProcess) { - return YES; - } - -// TransformProcessType(&frontPSN, kProcessTransformToForegroundApplication); // This doesn't work on Leopard - OSErr osError = SetFrontProcess(&frontPSN); - - frontPSN.highLongOfPSN = 0; - frontPSN.lowLongOfPSN = kNoProcess; - - if (osError == noErr) { - return YES; - } - return NO; -} - -#pragma mark - -#pragma mark Private - -#pragma mark - Action Node - - -- (void)_prepareDefaultActionNodes -{ - NSMutableArray *newNodes = [NSMutableArray array]; - NSArray *jsNodes; - - /* Paste as Plain Text */ - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Paste as Plain Text", nil) - actionName:CMBuiltInActionPasteAsPlainText]]; - - /* Case */ - jsNodes = [NSArray arrayWithObjects: - [self _javaScriptNodeWithName:@"Case/Capitalize.js"], - [self _javaScriptNodeWithName:@"Case/lowercase.js"], - [self _javaScriptNodeWithName:@"Case/Title Case.js"], - [self _javaScriptNodeWithName:@"Case/UPPERCASE.js"], - nil]; - [newNodes addObject:[actionNodeFactory createFolderNodeWithTitle:NSLocalizedString(@"Case", nil) - children:jsNodes]]; - /* Trim */ - jsNodes = [NSArray arrayWithObjects: - [self _javaScriptNodeWithName:@"Trim/LTrim.js"], - [self _javaScriptNodeWithName:@"Trim/RTrim.js"], - [self _javaScriptNodeWithName:@"Trim/Trim.js"], - nil]; - [newNodes addObject:[actionNodeFactory createFolderNodeWithTitle:NSLocalizedString(@"Trim", nil) - children:jsNodes]]; - - /* Remove Action */ - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Remove", nil) - actionName:CMBuiltInActionRemove]]; - - [self setActionNodes:newNodes]; -} - -- (void)_prepareBuiltinActionNodes -{ - NSMutableArray *newNodes = [NSMutableArray array]; - - /* Paste as */ - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Paste as Plain Text", nil) - actionName:CMBuiltInActionPasteAsPlainText]]; - - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Paste as File Path", nil) - actionName:CMBuiltInActionPasteAsFilePath]]; - - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Paste as HFS File Path", nil) - actionName:CMBuiltInActionPasteAsHFSFilePath]]; - - /* Remove Action */ - [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Remove", nil) - actionName:CMBuiltInActionRemove]]; - -// [newNodes addObject:[actionNodeFactory createBuiltinActionWithTitle:NSLocalizedString(@"Speak", nil) -// actionName:CMBuiltInActionSpeak]]; - - [self setValue:newNodes forKey:@"builtinActionNodes"]; -} - -- (void)_prepareBundledScriptActionNodes -{ - NSString *bundledActionsFolder = [CMUtilities bundledActionsFolder]; - if (!bundledActionsFolder) { - return; - } - - NSArray *newNodes = [self _makeScriptNodesWithWalkingDirectory:bundledActionsFolder]; - - [self setValue:newNodes forKey:@"bundledActionNodes"]; -} - -- (void)_prepareUsersScriptActionNodes -{ - NSString *userActionsFolder = [CMUtilities userActionsFolder]; - if (!userActionsFolder) { - return; - } - - NSArray *newNodes = [self _makeScriptNodesWithWalkingDirectory:userActionsFolder]; - // NSLog(@"newNode: %@", newNodes); - - [self setValue:newNodes forKey:@"usersActionNodes"]; -} - -- (NSArray *)_makeScriptNodesWithWalkingDirectory:(NSString *)directoryPath -{ - NSMutableArray *nodes = [NSMutableArray array]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - BOOL isDir = NO; - - NSArray *directoryContents = [fileManager contentsOfDirectoryAtPath:directoryPath - error:&error]; - - if (error) { - NSLog(@"Failed to make scripts nodes"); - return nil; - } - - for (NSString *path in directoryContents) { - NSString *fullPath = [directoryPath stringByAppendingPathComponent:path]; - NSString *filename = [path lastPathComponent]; - - if ([filename length] == 0 || - [filename characterAtIndex:0] == '.') { - continue; - } - - NSString *rootname = [filename stringByDeletingPathExtension]; - NSString *localizedName = [CMUtilities localizedFileName:rootname]; - NSString *pathExtension = [filename pathExtension]; - - // NSLog(@"path: %@\nfilename: %@\nrootname: %@\npathExtension: %@", - // path, filename, rootname, pathExtension); - - ActionNode *node = nil; - - if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDir] && isDir) { - NSArray *children = [self _makeScriptNodesWithWalkingDirectory:fullPath]; - node = [actionNodeFactory createFolderNodeWithTitle:localizedName - children:children]; - } - else { - if (![pathExtension isEqualToString:kJavaScriptExtension]) { - continue; - } - - node = [actionNodeFactory createJavaScriptActionWithTitle:localizedName - path:fullPath]; - } - - [nodes addObject:node]; - } - - return nodes; -} - -- (ActionNode *)_javaScriptNodeWithName:(NSString *)name -{ - NSDictionary *fileInfo = [self _javaScriptFileInfoWithName:name]; - ActionNode *node = [actionNodeFactory createJavaScriptActionWithTitle:[fileInfo objectForKey: - filenameKey] - path:[fileInfo objectForKey:filePathKey]]; - - return node; -} - -- (NSDictionary *)_javaScriptFileInfoWithName:(NSString *)name -{ - NSString *bundledActionsFolder = [CMUtilities bundledActionsFolder]; - if (!bundledActionsFolder) { - return nil; - } - - NSMutableArray *components = [NSMutableArray arrayWithArray:[name componentsSeparatedByString:@"/"]]; - [components insertObject:bundledActionsFolder atIndex:0]; - - NSString *filename = [components lastObject]; - [components replaceObjectAtIndex:([components count] - 1) withObject:filename]; - - NSString *filePath = [NSString pathWithComponents:components]; - - NSDictionary *fileInfo = [NSDictionary dictionaryWithObjectsAndKeys: - filename, filenameKey, - filePath, filePathKey, - nil]; - - return fileInfo; -} - -- (NSString *)_saveFilePath -{ - return [[CMUtilities applicationSupportFolder] stringByAppendingPathComponent:kActionSaveDataName]; -} - -#pragma mark - Action - - -- (NSString *)_loadScript:(NSString *)path -{ - NSString *filePath; - NSArray *components; - - components = [path componentsSeparatedByString:resourcePathSeparator]; - - if (1 < [components count]) { - filePath = [[[NSBundle mainBundle] resourcePath] - stringByAppendingPathComponent:[components lastObject]]; - } - else { - filePath = path; - } - - // NSLog(@"filePath: %@", filePath); - - if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { - return nil; - } - - NSData *data = [NSData dataWithContentsOfFile:filePath]; - if (!data) { - return nil; - } - - return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; -} - -#pragma mark - User Interface - - -- (void)_alertPanelWithTitle:(NSString *)title messageText:(NSString *)messageText -{ - [self keepCurrentFrontProcessAndActivate]; // Keep the most front of process - - NSRunAlertPanel(title, - messageText, - NSLocalizedString(@"OK", nil), - nil,nil); - - [self restorePreviousFrontProcess]; // Restore other app to front -} - -@end diff --git a/Source/ActionFactory.h b/Source/ActionFactory.h deleted file mode 100644 index 385ec37..0000000 --- a/Source/ActionFactory.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// ActionFactory.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface ActionFactory : NSObject -{ -} - -- (NSDictionary *)createActionForType:(NSString *)type name:(NSString *)name path:(NSString *)path; -- (NSDictionary *)createActionForType:(NSString *)type name:(NSString *)name; - -@end diff --git a/Source/ActionFactory.m b/Source/ActionFactory.m deleted file mode 100644 index 62184cb..0000000 --- a/Source/ActionFactory.m +++ /dev/null @@ -1,57 +0,0 @@ -// -// ActionFactory.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionFactory.h" - - -NSString *const CMBuiltinActionTypeKey = @"builtin"; -NSString *const CMJavaScriptActionTypeKey = @"js"; - -@implementation ActionFactory - -- (NSDictionary *)_actionTypes -{ - NSArray *typeKeys = [NSArray arrayWithObjects: - CMBuiltinActionTypeKey, - CMJavaScriptActionTypeKey, - nil]; - NSArray *typeStrings = [NSArray arrayWithObjects:@"Built-in", @"JavaScript", nil]; - - return [NSDictionary dictionaryWithObjects:typeStrings forKeys:typeKeys]; -} - -#pragma mark Public - -- (NSDictionary *)createActionForType:(NSString *)type name:(NSString *)name path:(NSString *)path -{ - // NSString *typeString = [[self _actionTypes] objectForKey:type]; - NSMutableDictionary *action = [NSMutableDictionary dictionaryWithObjectsAndKeys: - type, @"type", - nil]; - - if (name) { - [action setObject:name forKey:@"name"]; - } - - if (path) { - [action setObject:path forKey:@"path"]; - } - - // if ([type isEqualToString:CMBuiltinActionTypeKey]) { - // [action setObject:name forKey:@"name"]; - // } - - return action; -} - -- (NSDictionary *)createActionForType:(NSString *)type name:(NSString *)name -{ - return [self createActionForType:type name:name path:nil]; -} - -@end diff --git a/Source/ActionNode.h b/Source/ActionNode.h deleted file mode 100644 index 328bcfa..0000000 --- a/Source/ActionNode.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// ActionNode.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/13. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import -#import "BaseNode.h" - -extern NSString *const nodeTitleKey; -extern NSString *const isLeafKey; -extern NSString *const childrenKey; -extern NSString *const actionKey; - - -@interface ActionNode : BaseNode -{ - NSDictionary *action; -} -@property (nonatomic, retain, setter=setActionCommand:) NSDictionary *action; - -- (id)initWithAction:(NSDictionary *)anAction; -- (id)initWithDictionary:(NSDictionary *)aDictonary; -//- (NSDictionary *)dictionaryRepresentation; - -@end diff --git a/Source/ActionNode.m b/Source/ActionNode.m deleted file mode 100644 index 98b106c..0000000 --- a/Source/ActionNode.m +++ /dev/null @@ -1,107 +0,0 @@ -// -// ActionNode.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/13. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionNode.h" - -/* extern */ -NSString *const nodeTitleKey = @"nodeTitle"; -NSString *const isLeafKey = @"isLeaf"; -NSString *const childrenKey = @"children"; -NSString *const actionKey = @"action"; - - -@implementation ActionNode - -@synthesize action; - -/* designated initializer */ -- (id)initWithAction:(NSDictionary *)anAction -{ - self = [super initLeaf]; - if (self) { - [self setActionCommand:anAction]; - } - return self; -} - -- (id)initWithDictionary:(NSDictionary *)aDictonary -{ - BOOL isDictLeaf = [[aDictonary objectForKey:isLeafKey] boolValue]; - - if (isDictLeaf) { - self = [self initWithAction:[aDictonary objectForKey:actionKey]]; - if (!self) { - return nil; - } - } - else { - self = [self init]; - if (!self) { - return nil; - } - - NSMutableArray *childNodes = [NSMutableArray array]; - - for (NSDictionary *child in [aDictonary objectForKey:childrenKey]) { - ActionNode *childNode = [[ActionNode alloc] initWithDictionary:child]; - [childNodes addObject:childNode]; - [childNode release], childNode = nil; - } - - [self setChildren:childNodes]; - } - - [self setNodeTitle:[aDictonary objectForKey:nodeTitleKey]]; - - return self; -} - -- (void)dealloc -{ - [action release], action = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark Override - -//- (NSDictionary *)dictionaryRepresentation -//{ -// NSMutableArray *childNodes; -// -// if (0 < [children count]) { -// childNodes = [NSMutableArray array]; -// for (ActionNode *node in children) { -// [childNodes addObject:[node dictionaryRepresentation]]; -// } -// } -// else { -// childNodes = [self children]; -// } -// -// return [NSDictionary dictionaryWithObjectsAndKeys: -// [self nodeTitle], nodeTitleKey, -// childNodes, childrenKey, -// [NSNumber numberWithBool:[self isLeaf]], isLeafKey, -// [self action], actionKey, -// nil]; -//} - -// ------------------------------------------------------------------------------- -// mutableKeys: -// -// Maintain support for archiving and copying. -// ------------------------------------------------------------------------------- -- (NSArray *)mutableKeys -{ - return [[super mutableKeys] arrayByAddingObjectsFromArray: - [NSArray arrayWithObjects:@"action", nil]]; -} - -@end diff --git a/Source/ActionNodeController.h b/Source/ActionNodeController.h deleted file mode 100644 index 75c1112..0000000 --- a/Source/ActionNodeController.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ActionNodeController */ - -#import - -typedef enum { - CMSelectedSegmentForBuiltinAction = 0, - CMSelectedSegmentForScriptAction, - CMSelectedSegmentForUserScriptAction -} CMSelectedSegment; - -@interface ActionNodeController : NSObject -{ - IBOutlet NSOutlineView *actionsOutlineView; - IBOutlet NSOutlineView *reservedActionsOutlineView; - - IBOutlet NSTreeController *actionTreeController; - IBOutlet NSTreeController *reserveTreeController; - - IBOutlet NSTextField *nameField; - IBOutlet NSTextField *typeField; - IBOutlet NSTextField *pathField; - - NSInteger indexOfActionTypeSegment; - - NSArray *draggedNodes; - - /* Model */ - NSMutableArray *actionNodes; - NSArray *builtinNodes; - NSArray *bundledNodes; - NSArray *usersNodes; - - /* cached images for generic folder and url document */ - NSImage *folderImage; - NSImage *itemImage; - NSImage *jsImage; -} -@property (nonatomic, assign) NSInteger indexOfActionTypeSegment; -@property (nonatomic, assign) NSArray *draggedNodes; -@property (nonatomic, copy) NSMutableArray *actionNodes; -@property (nonatomic, retain) NSArray *builtinNodes; -@property (nonatomic, retain) NSArray *bundledNodes; -@property (nonatomic, retain) NSArray *usersNodes; -@property (nonatomic, retain) NSImage *folderImage; -@property (nonatomic, retain) NSImage *itemImage; -@property (nonatomic, retain) NSImage *jsImage; - -- (void)handleAwakeFromNib; - -- (IBAction)add:(id)sender; -- (IBAction)remove:(id)sender; - -@end diff --git a/Source/ActionNodeController.m b/Source/ActionNodeController.m deleted file mode 100644 index 255d1e6..0000000 --- a/Source/ActionNodeController.m +++ /dev/null @@ -1,571 +0,0 @@ -#import "ActionNodeController.h" -//#import "NSTreeController+NaoAdditions.h" -#import "NSIndexPath+NaoAdditions.h" -#import "ActionNode.h" -#import "ImageAndTextCell.h" -#import "ActionTypeTransformer.h" -#import "ActionController.h" -#import "CMUtilities.h" -#import "constants.h" - - -#define SMALL_ICON_SIZE 16 -#define DragDropItemPboardType @"DRAG_DROP_ITEM_PBOARD_TYPE" -#define COLUMNID_NAME @"NameColumn" // the single column name in our outline view - - -@interface ActionNodeController (Private) -- (void)_bindDetailsWithTreeController:(NSTreeController *)aController; -- (void)_changeReservedTreeContentToIndex:(NSInteger)selectedIndex; -- (void)_cacheIconImages; - -//- (void)_applyImageAndTextCellForOutlineView:(NSOutlineView *)outlineView; -- (NSIndexPath *)_destinationIndexPathFromNode:(NSTreeNode *)destinationNode childIndex:(NSInteger)index; -@end - -@implementation ActionNodeController (Private) - -- (void)_bindDetailsWithTreeController:(NSTreeController *)aController -{ - NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: - kEmptyString, NSNoSelectionPlaceholderBindingOption, - nil]; - - [nameField bind:@"value" - toObject:aController - withKeyPath:@"selection.nodeTitle" - options:options]; - - NSDictionary *optionsForActionType = [NSDictionary dictionaryWithObjectsAndKeys: - @"ActionTypeTransformer", NSValueTransformerNameBindingOption, - kEmptyString, NSNoSelectionPlaceholderBindingOption, - nil]; - [typeField bind:@"value" - toObject:aController - withKeyPath:@"selection.action.type" - options:optionsForActionType]; - - [pathField bind:@"value" - toObject:aController - withKeyPath:@"selection.action.path" - options:options]; -} - -- (void)_changeReservedTreeContentToIndex:(NSInteger)selectedIndex -{ - NSString *contentKeyPath = nil; - - switch (selectedIndex) { - case CMSelectedSegmentForBuiltinAction: - contentKeyPath = @"builtinNodes"; - break; - case CMSelectedSegmentForScriptAction: - contentKeyPath = @"bundledNodes"; - break; - case CMSelectedSegmentForUserScriptAction: - contentKeyPath = @"usersNodes"; - break; - default: - NSAssert(NO, @"Should not reach here"); - break; - } - - // NSLog(@"reserveTreeController: %@", [reserveTreeController infoForBinding:@"contentArray"]); - - /* unset */ - [reserveTreeController unbind:@"contentArray"]; - [reserveTreeController setContent:nil]; - - /* set */ - [reserveTreeController bind:@"contentArray" - toObject:self - withKeyPath:contentKeyPath - options:nil]; -} - -- (void)_cacheIconImages -{ - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSImage *image; - - if (image = [ws iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)]) { - folderImage = [image retain]; - [folderImage setSize:NSMakeSize(SMALL_ICON_SIZE,SMALL_ICON_SIZE)]; - } - -// itemImage = [[ws iconForFileType:NSFileTypeForHFSTypeCode(kGenericDocumentIcon)] retain]; -// [itemImage setSize:NSMakeSize(SMALL_ICON_SIZE,SMALL_ICON_SIZE)]; - - NSString *fileNameForAction = [[NSBundle mainBundle] pathForImageResource:@"ActionIcon"]; - if (fileNameForAction) { - itemImage = [[NSImage alloc] initWithContentsOfFile:fileNameForAction]; - } - - if (image = [ws iconForFileType:@"js"]) { - jsImage = [image retain]; - [jsImage setSize:NSMakeSize(SMALL_ICON_SIZE,SMALL_ICON_SIZE)]; - } -} - -//- (void)_applyImageAndTextCellForOutlineView:(NSOutlineView *)outlineView -//{ -// NSTableColumn *tableColumn = [outlineView tableColumnWithIdentifier:COLUMNID_NAME]; -// ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease]; -// [imageAndTextCell setEditable:YES]; -// [imageAndTextCell setLineBreakMode:NSLineBreakByTruncatingTail]; -// [tableColumn setDataCell:imageAndTextCell]; -//} - -- (NSIndexPath *)_destinationIndexPathFromNode:(NSTreeNode *)destinationNode childIndex:(NSInteger)index -{ - NSIndexPath *destinationIndexPath = nil; - - BOOL destinationIsRoot = (destinationNode == nil); - BOOL destinationIsInsideAFolder = (index >= 0); - - if (destinationIsRoot) { - NSUInteger insertionIndex = (index >= 0) ? index : [actionNodes count]; - destinationIndexPath = [NSIndexPath indexPathWithIndex:insertionIndex]; - } - else { // has parent - destinationIndexPath = [destinationNode indexPath]; - // NSLog(@"destinationIndexPath: %@", destinationIndexPath); - - if (destinationIsInsideAFolder) { - // NSLog(@"index >= 0"); - destinationIndexPath = [destinationIndexPath indexPathByAddingIndex:index]; - } - else { // above an item - if ([destinationNode isLeaf]) { - // NSLog(@"above an item and not a folder"); - // NSLog(@"destinationIndexPath: %@", destinationIndexPath); - destinationIndexPath = [destinationIndexPath incrementLastNodeIndex]; - } - else { - NSArray *children = [[destinationNode representedObject] valueForKey:childrenKey]; - destinationIndexPath = [destinationIndexPath indexPathByAddingIndex:[children count]]; - } - } - } - - return destinationIndexPath; -} - -@end - -#pragma mark - - -@implementation ActionNodeController - -@synthesize indexOfActionTypeSegment; -@synthesize draggedNodes; -@synthesize actionNodes; -@synthesize builtinNodes; -@synthesize bundledNodes; -@synthesize usersNodes; -@synthesize folderImage; -@synthesize itemImage; -@synthesize jsImage; - -#pragma mark Initialize - -+ (void)initialize -{ - ActionTypeTransformer *actionTypeTransformer = [[[ActionTypeTransformer alloc] init] autorelease]; - [NSValueTransformer setValueTransformer:actionTypeTransformer forName:@"ActionTypeTransformer"]; -} - -- (id)init -{ - self = [super init]; - if (self) { - ActionController *actionController = [ActionController sharedInstance]; - [actionController prepareActions]; - - [self setValue:[actionController actionNodes] forKey:@"actionNodes"]; - [self setValue:[actionController builtinActionNodes] forKey:@"builtinNodes"]; - [self setValue:[actionController bundledActionNodes] forKey:@"bundledNodes"]; - [self setValue:[actionController usersActionNodes] forKey:@"usersNodes"]; - - [self _cacheIconImages]; - } - return self; -} - -- (void)dealloc -{ - /* KVO */ - [self removeObserver:self - forKeyPath:@"indexOfActionTypeSegment"]; - - [actionNodes release], actionNodes = nil; - [builtinNodes release], builtinNodes = nil; - [bundledNodes release], bundledNodes = nil; - [usersNodes release], usersNodes = nil; - - [folderImage release], folderImage = nil; - [itemImage release], itemImage = nil; - [jsImage release], jsImage = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark Accessors -#pragma mark - Setter - - -- (void)setActionNodes:(NSMutableArray *)newNodes -{ - if (actionNodes != newNodes) { - [actionNodes autorelease]; -// actionNodes = [[NSMutableArray alloc] initWithArray:newNodes]; - actionNodes = [newNodes mutableCopy]; - } -} - -#pragma mark - -#pragma mark KVO - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ -// NSLog(@"observeValueForKeyPath: %@", keyPath); - - if ([keyPath isEqualToString:@"indexOfActionTypeSegment"]) { - if ([change objectForKey:NSKeyValueChangeNewKey]) { - NSInteger selectedIndex = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; - [self _changeReservedTreeContentToIndex:selectedIndex]; - } - } -} - -#pragma mark - -#pragma mark Delegate - -#pragma mark - NSControl - - -- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor -{ - if ([[fieldEditor string] length] == 0) { - // don't allow empty node names - return NO; - } - - return YES; -} - -#pragma mark - NSOutlineView - - -- (void)outlineViewSelectionDidChange:(NSNotification *)notification -{ - NSOutlineView *outlineView = [notification object]; - -// NSLog(@"outlineViewSelectionDidChange: %@", outlineView); - - if (outlineView == actionsOutlineView) { - [self _bindDetailsWithTreeController:actionTreeController]; - } - else { - [self _bindDetailsWithTreeController:reserveTreeController]; - } -} - -- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - if ([[tableColumn identifier] isEqualToString:COLUMNID_NAME]) { - // we are displaying the single and only column - if ([cell isKindOfClass:[ImageAndTextCell class]]) { - NSImage *nodeIcon = nil; - - ActionNode *node = [item representedObject]; - if (node) { - if ([node isLeaf]) { - NSDictionary *action = [node action]; - NSString *actionType = nil; - if (action && - (actionType = [action objectForKey:@"type"])) { - if ([actionType isEqualToString:CMBuiltinActionTypeKey]) { - nodeIcon = itemImage; - } - else if ([actionType isEqualToString:CMJavaScriptActionTypeKey]) { - nodeIcon = jsImage; - } - } - else { - // it's a separator, don't bother with the icon - } - } - else { - // it's a folder, use the folderImage as its icon - nodeIcon = folderImage; - } - } - // set the cell's image - [(ImageAndTextCell *)cell setImage:nodeIcon]; - } - } -} - -#pragma mark NSOutlineView data source - -- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard -{ - NSArray *pboardTypes = [NSArray arrayWithObjects:DragDropItemPboardType, nil]; - [pboard declareTypes:pboardTypes owner:self]; - - draggedNodes = items; -// NSLog(@"draggedNodes: %@", draggedNodes); - - return YES; -} - -- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(NSInteger)index -{ -// NSLog(@"validateDrop: %@", item); - - NSPasteboard *pboard = [info draggingPasteboard]; - NSArray *pboardTypes = [NSArray arrayWithObjects:DragDropItemPboardType, nil]; - - if ([pboard availableTypeFromArray:pboardTypes]) { - if ([info draggingSource] == outlineView) { - return NSDragOperationMove; - } - else { - return NSDragOperationCopy; - } - } - - return NSDragOperationNone; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(NSInteger)index -{ -// NSLog(@"childIndex: %d", index); - - NSIndexPath *destinationIndexPath = [self _destinationIndexPathFromNode:item childIndex:index]; -// NSLog(@"destinationIndexPath: %@", destinationIndexPath); - - /* if draggingSource is self, it's a move */ - if ([info draggingSource] == outlineView) { -// NSInteger nodeCount = 0; - for (id node in draggedNodes) { -// nodeCount++; - - id item = [[node representedObject] copy]; - NSIndexPath *sourceIndexPath = [node indexPath]; - NSIndexPath *parentIndexPath = ([node parentNode]) ? [[node parentNode] indexPath] : nil; -// NSLog(@"parentIndexPath: %@", parentIndexPath); -// NSLog(@"sourceIndexPath: %@", sourceIndexPath); -// NSLog(@"destinationPath: %@", destinationIndexPath); - - NSComparisonResult comparisonResult = [sourceIndexPath compare:destinationIndexPath]; - BOOL isSibling = [sourceIndexPath isSiblingOfIndexPath:destinationIndexPath]; - BOOL sourceAndDestinationHaveSameParent = NO; - if ([[sourceIndexPath indexPathByRemovingLastIndex] compare:[destinationIndexPath indexPathByRemovingLastIndex]] == NSOrderedSame) { - sourceAndDestinationHaveSameParent = YES; - } - BOOL destinationIsParent = NO; - if (parentIndexPath && - [[parentIndexPath parentPathIndex] compare:[destinationIndexPath parentPathIndex]] == NSOrderedSame) { - destinationIsParent = YES; - } - BOOL destinationIsRoot = ([destinationIndexPath length] == 1); - NSIndexPath *firstCommonAncestorIndexPath = [sourceIndexPath firstCommonAncestorWithIndexPath:destinationIndexPath]; -// NSLog(@"source compare dest: %d", comparisonResult); -// NSLog(@"source parent path: %@, dest path: %@", [sourceIndexPath indexPathByRemovingLastIndex], [destinationIndexPath indexPathByRemovingLastIndex]); -// NSLog(@"sourceAndDestinationHaveSameParent: %d", sourceAndDestinationHaveSameParent); -// NSLog(@"destinationIsRoot: %d", destinationIsRoot); -// NSLog(@"destinationIsParent: %d", destinationIsParent); -// NSLog(@"isSibling: %d", isSibling); -// NSLog(@"firstCommonAncestorIndexPath: %@", firstCommonAncestorIndexPath); - - NSIndexPath *removeObjectPathIndex = nil; - NSIndexPath *decrementedDestinationPathIndex = nil; - if (comparisonResult == NSOrderedDescending) { - if (isSibling) { - removeObjectPathIndex = [sourceIndexPath incrementLastNodeIndex]; - } - else if (destinationIsRoot || destinationIsParent) { -// NSLog(@"destinationIsRoot || destinationIsParent"); - - NSUInteger sourceLength = [sourceIndexPath length]; - NSUInteger indexes[sourceLength]; - [sourceIndexPath getIndexes:indexes]; - - for (NSInteger i = 0; i < sourceLength; i++) { -// NSLog(@"indexes[%d] = %d", i, indexes[i]); - if ([firstCommonAncestorIndexPath length] == i) { -// NSLog(@"firstCommonAncestorIndexPath is equal to 'i'"); - indexes[i] = indexes[i] + 1; - } - } - - removeObjectPathIndex = [NSIndexPath indexPathWithIndexes:indexes - length:sourceLength]; - } - else { -// NSLog(@"OrderedDescending, not sibling"); - removeObjectPathIndex = sourceIndexPath; - } - } - else { -// NSLog(@"OrderedAscending"); - removeObjectPathIndex = sourceIndexPath; - - NSUInteger sourceLength = [sourceIndexPath length]; - NSUInteger destLength = [destinationIndexPath length]; - NSUInteger min = (sourceLength < destLength) ? sourceLength-1 : destLength-1; - NSUInteger destIndexes[destLength]; - [destinationIndexPath getIndexes:destIndexes]; - -// NSLog(@"sourceLength: %d, destLength: %d", sourceLength, destLength); -// NSLog(@"min: %d", min); - - if (sourceAndDestinationHaveSameParent) { - destIndexes[min] = destIndexes[min] - 1; -// NSLog(@"path: %d", destIndexes[min]); - } - - decrementedDestinationPathIndex = [NSIndexPath indexPathWithIndexes:destIndexes - length:destLength]; - } -// NSLog(@"removeObjectPathIndex: %@", removeObjectPathIndex); - - @try { - [actionTreeController insertObject:item atArrangedObjectIndexPath:destinationIndexPath]; - [actionTreeController removeObjectAtArrangedObjectIndexPath:removeObjectPathIndex]; - } - @catch (NSException *ex) { - NSLog(@"Exception: %@", ex); - } - @finally { - [item release], item = nil; - } - - if (decrementedDestinationPathIndex) { -// NSLog(@"decrementedDestinationPathIndex: %@", decrementedDestinationPathIndex); - destinationIndexPath = decrementedDestinationPathIndex; - } - - destinationIndexPath = [destinationIndexPath incrementLastNodeIndex]; -// NSLog(@"incremented destinationIndexPath: %@", destinationIndexPath); - } - - return YES; - } - else { - /* draggingSource is not self, it's a copy */ -// NSLog(@"copy"); - - for (id node in draggedNodes) { - id item = [[node representedObject] copy]; - @try { - [actionTreeController insertObject:item atArrangedObjectIndexPath:destinationIndexPath]; - } - @catch (NSException *ex) { - NSLog(@"Exception: %@", ex); - } - @finally { - [item release], item = nil; - } - - destinationIndexPath = [destinationIndexPath incrementLastNodeIndex]; - } - - return YES; - } - - return NO; -} - -#pragma mark -- Hacks for Drag and Drop -- - -- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item -{ - return nil; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item -{ - return NO; -} - -- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item -{ - return 0; -} - -- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item -{ - return nil; -} - -#pragma mark - -#pragma mark Public - -- (void)handleAwakeFromNib -{ -// /* apply our custom ImageAndTextCell for rendering the first column's cells */ -// [self _applyImageAndTextCellForOutlineView:actionsOutlineView]; -// [self _applyImageAndTextCellForOutlineView:reservedActionsOutlineView]; - - /* Drag and Drop */ - NSArray *draggedTypes = [NSArray arrayWithObjects:DragDropItemPboardType, nil]; - [actionsOutlineView registerForDraggedTypes:draggedTypes]; - [actionsOutlineView setDraggingSourceOperationMask:(NSDragOperationCopy | NSDragOperationMove) - forLocal:YES]; - - [reservedActionsOutlineView setDraggingSourceOperationMask:(NSDragOperationCopy) - forLocal:YES]; - - /* OutlineView sort setting */ - NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:nodeTitleKey ascending:YES]; - [reservedActionsOutlineView setSortDescriptors:[NSArray arrayWithObject:descriptor]]; - [descriptor release], descriptor = nil; - -// [reservedActionsOutlineView selectColumnIndexes:[NSIndexSet indexSetWithIndex:0] -// byExtendingSelection:NO]; - - /* Binding */ - [reserveTreeController bind:@"contentArray" - toObject:self - withKeyPath:@"builtinNodes" - options:nil]; - - [self _bindDetailsWithTreeController:actionTreeController]; - - [self addObserver:self - forKeyPath:@"indexOfActionTypeSegment" - options:NSKeyValueObservingOptionNew - context:nil]; -} - -#pragma mark Actions - -/* Buttons */ - -- (IBAction)add:(id)sender -{ - NSArray *selectedObjects = [reserveTreeController selectedObjects]; - if (!(0 < [selectedObjects count])) { - return; - } - - for (id item in selectedObjects) { - NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:[actionNodes count]]; - [actionTreeController insertObject:item atArrangedObjectIndexPath:indexPath]; - } -} - -- (IBAction)remove:(id)sender -{ - NSArray *selectedIndexPaths = [actionTreeController selectionIndexPaths]; - if (!([selectedIndexPaths count] > 0)) { - return; - } - - for (NSIndexPath *indexPath in [selectedIndexPaths reverseObjectEnumerator]) { - [actionTreeController removeObjectAtArrangedObjectIndexPath:indexPath]; - } -} - -@end diff --git a/Source/ActionNodeFactory.h b/Source/ActionNodeFactory.h deleted file mode 100644 index 3c02efe..0000000 --- a/Source/ActionNodeFactory.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// ActionNodeFactory.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - -@class ActionNode, ActionFactory; - -@interface ActionNodeFactory : NSObject -{ - ActionFactory *actionFactory; -} -@property (nonatomic, retain) ActionFactory *actionFactory; - -- (ActionNode *)createFolderNodeWithTitle:(NSString *)title children:(NSArray *)children; -- (ActionNode *)createActionNodeForType:(NSString *)type title:(NSString *)title actionName:(NSString *)actionName path:(NSString *)path; - -- (ActionNode *)createBuiltinActionWithTitle:(NSString *)title actionName:(NSString *)actionName; -- (ActionNode *)createJavaScriptActionWithTitle:(NSString *)title path:(NSString *)path; - -@end diff --git a/Source/ActionNodeFactory.m b/Source/ActionNodeFactory.m deleted file mode 100644 index 0004cf7..0000000 --- a/Source/ActionNodeFactory.m +++ /dev/null @@ -1,74 +0,0 @@ -// -// ActionNodeFactory.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionNodeFactory.h" -#import "ActionNode.h" -#import "ActionFactory.h" -#import "ActionController.h" -#import "constants.h" - - -@implementation ActionNodeFactory - -@synthesize actionFactory; - -- (id)init -{ - self = [super init]; - if (self) { - ActionFactory *factory = [[ActionFactory alloc] init]; - [self setActionFactory:factory]; - [factory release], factory = nil; - } - return self; -} - -- (void)dealloc -{ - [actionFactory release], actionFactory = nil; - - [super dealloc]; -} - -#pragma mark Public - -- (ActionNode *)createFolderNodeWithTitle:(NSString *)title children:(NSArray *)children -{ - ActionNode *newNode = [[[ActionNode alloc] init] autorelease]; - [newNode setValue:title forKey:nodeTitleKey]; - [newNode setValue:children forKey:childrenKey]; - - return newNode; -} - -- (ActionNode *)createActionNodeForType:(NSString *)type title:(NSString *)title actionName:(NSString *)actionName path:(NSString *)path -{ - NSDictionary *action = [actionFactory createActionForType:type name:actionName path:path]; - - ActionNode *newNode = [[[ActionNode alloc] initWithAction:action] autorelease]; - [newNode setValue:title forKey:nodeTitleKey]; - - return newNode; -} - -- (ActionNode *)createBuiltinActionWithTitle:(NSString *)title actionName:(NSString *)actionName -{ - return [self createActionNodeForType:CMBuiltinActionTypeKey title:title - actionName:actionName - path:nil]; -} - -- (ActionNode *)createJavaScriptActionWithTitle:(NSString *)title path:(NSString *)path -{ - return [self createActionNodeForType:CMJavaScriptActionTypeKey - title:title - actionName:nil - path:path]; -} - -@end diff --git a/Source/ActionPopUpButton.h b/Source/ActionPopUpButton.h deleted file mode 100644 index 54e894c..0000000 --- a/Source/ActionPopUpButton.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// ActionPopUpButton.h -// SnippetsPractice -// -// Created by naotaka on 08/11/15. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface ActionPopUpButton : NSButton -{ -} - -@end diff --git a/Source/ActionPopUpButton.m b/Source/ActionPopUpButton.m deleted file mode 100644 index 6d24462..0000000 --- a/Source/ActionPopUpButton.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// ActionPopUpButton.m -// SnippetsPractice -// -// Created by naotaka on 08/11/15. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionPopUpButton.h" - - -@implementation ActionPopUpButton - -- (void)mouseDown:(NSEvent *)theEvent -{ - NSPoint locationInWindow = [theEvent locationInWindow]; -// NSLog(@"locationInWindow: %@", NSStringFromPoint(locationInWindow)); - - NSEvent *newEvent = [NSEvent mouseEventWithType:[theEvent type] - location:locationInWindow - modifierFlags:[theEvent modifierFlags] - timestamp:[theEvent timestamp] - windowNumber:[theEvent windowNumber] - context:[theEvent context] - eventNumber:[theEvent eventNumber] - clickCount:[theEvent clickCount] - pressure:[theEvent pressure]]; - - [self highlight:YES]; - - [NSMenu popUpContextMenu:[self menu] withEvent:newEvent forView:self]; - - [self highlight:NO]; -} - -@end diff --git a/Source/ActionTypeTransformer.h b/Source/ActionTypeTransformer.h deleted file mode 100644 index 8843574..0000000 --- a/Source/ActionTypeTransformer.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// ActionTypeTransformer.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/27. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface ActionTypeTransformer : NSValueTransformer -{ -} - -@end diff --git a/Source/ActionTypeTransformer.m b/Source/ActionTypeTransformer.m deleted file mode 100644 index c57205a..0000000 --- a/Source/ActionTypeTransformer.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// ActionTypeTransformer.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/27. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "ActionTypeTransformer.h" -#import "ActionController.h" - - -@implementation ActionTypeTransformer - -+ (Class)transformedValueClass -{ - return [NSString class]; -} - -+ (BOOL)allowsReverseTransformation -{ - return NO; -} - -- (id)transformedValue:(id)value -{ - if (value == nil) { - return nil; - } - - NSString *result = nil; - - if ([value isEqualToString:CMBuiltinActionTypeKey]) { - result = NSLocalizedString(@"Built-in", nil); - } - else if ([value isEqualToString:CMJavaScriptActionTypeKey]) { - result = NSLocalizedString(@"JavaScript", nil); - } - - return result; -} - -@end diff --git a/Source/AppController.h b/Source/AppController.h deleted file mode 100644 index 9400cb8..0000000 --- a/Source/AppController.h +++ /dev/null @@ -1,31 +0,0 @@ -/* AppController */ - -#import - -@class SnippetEditorController; - -@interface AppController : NSObject -{ - SnippetEditorController *snippetEditorController; - -// NSOperationQueue *queue; - ProcessSerialNumber frontPSN; -} -//@property (nonatomic, retain) NSOperationQueue *queue; - -- (IBAction)showPreferencePanel:(id)sender; -- (IBAction)showSnippetEditor:(id)sender; -- (IBAction)clearHistory:(id)sender; - -- (void)popUpClipMenu:(id)sender; -- (void)popUpActionMenu:(id)sender; -- (void)popUpHistoryMenu:(id)sender; -- (void)popUpSnippetsMenu:(id)sender; -- (void)selectMenuItem:(id)sender; -- (void)selectSnippetMenuItem:(id)sender; -- (void)selectActionMenuItem:(id)sender; - -- (void)keepCurrentFrontProcessAndActivate; -- (BOOL)restorePreviousFrontProcess; - -@end diff --git a/Source/AppController.m b/Source/AppController.m deleted file mode 100644 index 12b2015..0000000 --- a/Source/AppController.m +++ /dev/null @@ -1,851 +0,0 @@ -#import "AppController.h" -#import "constants.h" -#import "CMUtilities.h" -#import "PrefsWindowController.h" -#import "MenuController.h" -#import "ActionController.h" -#import "ActionNode.h" -#import "ClipsController.h" -#import "Clip.h" -#import "SnippetEditorController.h" -#import "NMLoginItems.h" - -#import "PTHotKey.h" -#import "PTHotKeyCenter.h" -#import - - -@interface AppController () -//- (BOOL)_moveCurrentProcessToForeground; -//- (BOOL)_movePreviousFrontProcessToForeground; - -- (void)_toggleCheckPreReleaseUpdates:(BOOL)flag; - -- (void)_promptToAddLoginItems; -- (void)_toggleAddingToLoginItems:(BOOL)flag; -- (void)_toggleLoginItemState; - -- (void)_registerHotKeys; -- (void)_unregisterHotKeys; - -- (BOOL)_invokeModifiedClickWithBehavior:(id)behavior andSender:(id)sender; - -- (BOOL)_applyActionToTarget:(id)sender; -- (void)_invokeAction:(NSDictionary *)action toIndex:(NSInteger)index; -- (void)_invokeAction:(NSDictionary *)action; -- (void)_invokeBuiltinAction:(NSDictionary *)action toTarget:(id)target; -- (void)_invokeJavaScriptAction:(NSDictionary *)action atIndex:(NSInteger)index; - -- (void)_handlePreferencePanelWillClose:(NSNotification *)aNotification; -@end - - -#pragma mark - -@implementation AppController - -//@synthesize queue; - -NSDictionary *_storeTypesDictionary() -{ - NSMutableArray *storeTypeValues = [NSMutableArray array]; - NSArray *availableTypeNames = [Clip availableTypeNames]; - - for (NSString *name in availableTypeNames) { - [storeTypeValues addObject:[NSNumber numberWithBool:YES]]; - } - - return [NSDictionary dictionaryWithObjects:storeTypeValues forKeys:availableTypeNames]; -} - -#pragma mark - - -+ (NSDictionary *)_defaultHotKeyCombos -{ - NSMutableDictionary *hotKeyCombos = [NSMutableDictionary dictionary]; - NSMutableArray *newCombos = [NSMutableArray array]; - - /* - [code] - 9 = 'v', - 11 = 'b', - - [modifiers] - 768 = 'command' + 'shift' - 2304 = 'command' + 'option' - 4352 = 'command' + 'control' - */ - - PTKeyCombo *keyCombo; - - /* Main Menu key combo */ - keyCombo = [PTKeyCombo keyComboWithKeyCode:9 modifiers:768]; - [newCombos addObject:keyCombo]; - - /* History Menu key combo */ - keyCombo = [PTKeyCombo keyComboWithKeyCode:9 modifiers:4352]; - [newCombos addObject:keyCombo]; - - /* Snippets Menu key combo */ - keyCombo = [PTKeyCombo keyComboWithKeyCode:11 modifiers:768]; - [newCombos addObject:keyCombo]; - - NSDictionary *hotKeyMap = [CMUtilities hotKeyMap]; - for (NSString *identifier in hotKeyMap) { - NSUInteger index = [[[hotKeyMap objectForKey:identifier] objectForKey:kIndex] - unsignedIntegerValue]; - PTKeyCombo *keyCombo = [newCombos objectAtIndex:index]; - [hotKeyCombos setObject:[keyCombo plistRepresentation] forKey:identifier]; - } - - return hotKeyCombos; -} - -+ (NSMutableArray *)_defaultExcludeList -{ - NSMutableDictionary *anAppInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: - @"org.openoffice.script", kCMBundleIdentifierKey, - @"OpenOffice.org", kCMNameKey, - nil]; - -// NSMutableDictionary *anAppInfo2 = [NSMutableDictionary dictionaryWithObjectsAndKeys: -// @"zzz.com.apple.Safari", kCMBundleIdentifierKey, -// @"zzzSafari", kCMNameKey, -// nil]; -// NSMutableArray *excludeList = [NSMutableArray arrayWithObjects:anAppInfo, anAppInfo2, nil]; - - NSMutableArray *excludeList = [NSMutableArray arrayWithObjects:anAppInfo, nil]; - return excludeList; -} - -#pragma mark Initialize - -+ (void)initialize -{ - /* Default Values */ - NSMutableDictionary *defaultValues = [NSMutableDictionary dictionary]; - - /* Hot Keys */ - [defaultValues setObject:[self _defaultHotKeyCombos] forKey:CMPrefHotKeysKey]; - - /* General */ - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefLoginItemKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefSuppressAlertForLoginItemKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefInputPasteCommandKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefReorderClipsAfterPasting]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:20] forKey:CMPrefMaxHistorySizeKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:1800] forKey:CMPrefAutosaveDelayKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefSaveHistoryOnQuitKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefExportHistoryAsSingleFileKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:1] forKey:CMPrefTagOfSeparatorForExportHistoryToFileKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:1] forKey:CMPrefShowStatusItemKey]; - [defaultValues setObject:[NSNumber numberWithFloat:0.75] forKey:CMPrefTimeIntervalKey]; - [defaultValues setObject:_storeTypesDictionary() forKey:CMPrefStoreTypesKey]; - [defaultValues setObject:[self _defaultExcludeList] forKey:CMPrefExcludeAppsKey]; - /* Menu */ - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:20] forKey:CMPrefMaxMenuItemTitleLengthKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:0] forKey:CMPrefNumberOfItemsPlaceInlineKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:10] forKey:CMPrefNumberOfItemsPlaceInsideFolderKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefMenuItemsAreMarkedWithNumbersKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefMenuItemsTitleStartWithZeroKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefAddNumericKeyEquivalentsKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefShowLabelsInMenuKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefAddClearHistoryMenuItemKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefShowAlertBeforeClearHistoryKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefShowToolTipOnMenuItemKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:200] forKey:CMPrefMaxLengthOfToolTipKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefChangeFontSizeKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefHowToChangeFontSizeKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:14] forKey:CMPrefSelectedFontSizeKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefShowImageInTheMenuKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:100] forKey:CMPrefThumbnailWidthKey]; - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:32] forKey:CMPrefThumbnailHeightKey]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefShowIconInTheMenuKey]; - /* - Menu Icon - */ - [defaultValues setObject:[NSNumber numberWithUnsignedInteger:16] forKey:CMPrefMenuIconSizeKey]; - [defaultValues setObject:[NSNumber numberWithInteger:1] forKey:CMPrefMenuIconOfFileTypeTagForStringKey]; - [defaultValues setObject:@"TEXT" forKey:CMPrefMenuIconOfFileTypeForStringKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefMenuIconOfFileTypeTagForRTFKey]; - [defaultValues setObject:@"rtf" forKey:CMPrefMenuIconOfFileTypeForRTFKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefMenuIconOfFileTypeTagForRTFDKey]; - [defaultValues setObject:@"rtfd" forKey:CMPrefMenuIconOfFileTypeForRTFDKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefMenuIconOfFileTypeTagForPDFKey]; - [defaultValues setObject:@"pdf" forKey:CMPrefMenuIconOfFileTypeForPDFKey]; - [defaultValues setObject:[NSNumber numberWithInteger:1] forKey:CMPrefMenuIconOfFileTypeTagForFilenamesKey]; - [defaultValues setObject:@"clpu" forKey:CMPrefMenuIconOfFileTypeForFilenamesKey]; // need to change? - [defaultValues setObject:[NSNumber numberWithInteger:1] forKey:CMPrefMenuIconOfFileTypeTagForURLKey]; - [defaultValues setObject:@"gurl" forKey:CMPrefMenuIconOfFileTypeForURLKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefMenuIconOfFileTypeTagForTIFFKey]; - [defaultValues setObject:@"tiff" forKey:CMPrefMenuIconOfFileTypeForTIFFKey]; - [defaultValues setObject:[NSNumber numberWithInteger:0] forKey:CMPrefMenuIconOfFileTypeTagForPICTKey]; - [defaultValues setObject:@"pict" forKey:CMPrefMenuIconOfFileTypeForPICTKey]; - /* Actions */ - NSMutableArray *defaultActions = [ActionController defaultActions]; - [defaultValues setObject:defaultActions forKey:@"actions"]; - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMPrefEnableActionKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMPrefInvokeActionImmediatelyKey]; - [defaultValues setObject:kPopUpActionMenu forKey:CMPrefContorlClickBehaviorKey]; - /* Snippet */ - [defaultValues setObject:[NSNumber numberWithInteger:CMPositionOfSnippetsBelowClips] forKey:CMPrefPositionOfSnippetsKey]; - /* Updates */ - [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:CMEnableAutomaticCheckKey]; - [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:CMEnableAutomaticCheckPreReleaseKey]; - [defaultValues setObject:[NSNumber numberWithInteger:86400] forKey:CMUpdateCheckIntervalKey]; // daily - - [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues]; -} - -//- (id)init -//{ -// self = [super init]; -// if (self) { -// queue = [[NSOperationQueue alloc] init]; -// } -// return self; -//} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - /* KVO */ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults removeObserver:self - forKeyPath:CMPrefHotKeysKey]; -// [defaults removeObserver:self -// forKeyPath:CMPrefLoginItemKey]; - [defaults removeObserver:self - forKeyPath:CMEnableAutomaticCheckPreReleaseKey]; - - [[ClipsController sharedInstance] removeObserver:self - forKeyPath:@"clips"]; - -// [queue release], queue = nil; - - [super dealloc]; -} - -- (void)awakeFromNib -{ -// NSLog(@"awakeFromNib"); - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - if ([defaults boolForKey:CMPrefShowStatusItemKey]) { - [[MenuController sharedInstance] createStatusItem]; - } - - /* KVO */ - [defaults addObserver:self - forKeyPath:CMPrefHotKeysKey - options:NSKeyValueObservingOptionNew - context:nil]; -// [defaults addObserver:self -// forKeyPath:CMPrefLoginItemKey -// options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) -// context:nil]; - - [[ClipsController sharedInstance] addObserver:self - forKeyPath:@"clips" - options:NSKeyValueObservingOptionNew - context:nil]; - - /* Notification */ - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector( _handlePreferencePanelWillClose: ) - name:CMPreferencePanelWillCloseNotification - object:nil]; -} - - -#pragma mark - -#pragma mark KVO - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ -// NSLog(@"observeValueForKeyPath: %@, change: %@", keyPath, change); - - if ([keyPath isEqualToString:@"clips"]) { - [[MenuController sharedInstance] updateStatusMenu]; - } - else if ([keyPath isEqualToString:CMPrefHotKeysKey]) { - [self _registerHotKeys]; - } -// else if ([keyPath isEqualToString:CMPrefLoginItemKey]) { -// BOOL old = [[change objectForKey:kOldKey] boolValue]; -// BOOL new = [[change objectForKey:kNewKey] boolValue]; -// if (old == new) { -// return; -// } -// [self _toggleAddingToLoginItems:new]; -// } - else if ([keyPath isEqualToString:CMEnableAutomaticCheckPreReleaseKey]) { - BOOL checkPreReleases = [[object objectForKey:kNewKey] boolValue]; - [self _toggleCheckPreReleaseUpdates:checkPreReleases]; - } -} - -#pragma mark - -#pragma mark Delegate -#pragma mark - NSApplication - - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - -// NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; - - NSOperationQueue *queue = [[NSOperationQueue alloc] init]; - NSOperation *operation; - - /* load clips */ - operation = [[NSInvocationOperation alloc] initWithTarget:[ClipsController sharedInstance] - selector:@selector( loadClips ) - object:nil]; - [queue addOperation:operation]; - [operation release], operation = nil; - - /* load actions */ - operation = [[NSInvocationOperation alloc] initWithTarget:[ActionController sharedInstance] - selector:@selector( loadActions ) - object:nil]; - [queue addOperation:operation]; - [operation release], operation = nil; - - /* register hot-keys */ - operation = [[NSInvocationOperation alloc] initWithTarget:self - selector:@selector( _registerHotKeys ) - object:nil]; - [queue addOperation:operation]; - [operation release], operation = nil; - - /* ask to register as login item */ - if (([defaults boolForKey:CMPrefLoginItemKey] == NO) && - ([defaults boolForKey:CMPrefSuppressAlertForLoginItemKey] == NO)) { - [self _promptToAddLoginItems]; - } - - /* Sparkle updater */ - SUUpdater *updater = [SUUpdater sharedUpdater]; - - [self _toggleCheckPreReleaseUpdates:[defaults boolForKey:CMEnableAutomaticCheckPreReleaseKey]]; - - [updater setAutomaticallyChecksForUpdates:[defaults boolForKey:CMEnableAutomaticCheckKey]]; - [updater setUpdateCheckInterval:[defaults integerForKey:CMUpdateCheckIntervalKey]]; - - [defaults addObserver:self - forKeyPath:CMEnableAutomaticCheckPreReleaseKey - options:NSKeyValueObservingOptionNew - context:nil]; - - /* Finish all operations */ - [queue waitUntilAllOperationsAreFinished]; - [queue release], queue = nil; - -// NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate]; -// NSLog(@"result: %f", (end - start)); - -// [self showSnippetEditor:self]; // temp!!! -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - /* Save clips to file */ - BOOL saveHistoryOnQuit = [[NSUserDefaults standardUserDefaults] boolForKey:CMPrefSaveHistoryOnQuitKey]; - if (saveHistoryOnQuit) { - BOOL result = [[ClipsController sharedInstance] saveClips]; - if (result == NO) { - [NSApp activateIgnoringOtherApps:YES]; - NSRunAlertPanel(NSLocalizedString(@"Error", nil), - NSLocalizedString(@"Could not save your clipboard history to file.", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - } - } - else { - [[ClipsController sharedInstance] removeClips]; - } - - [[ActionController sharedInstance] saveActions]; - - [self _unregisterHotKeys]; -} - -#pragma mark - -#pragma mark Protocols -#pragma mark - NSMenuValidation - - -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem -{ -// NSLog(@"validateMenuItem"); - - SEL action = [menuItem action]; - if (action == @selector( clearHistory: )) { - NSUInteger numberOfClips = [[[ClipsController sharedInstance] clips] count]; - if (numberOfClips == 0) { - return NO; - } - } - - return YES; -} - -#pragma mark - -#pragma mark Public - -- (IBAction)showPreferencePanel:(id)sender -{ - [[PrefsWindowController sharedPrefWindowController] showWindow:nil]; -} - -- (IBAction)showSnippetEditor:(id)sender -{ - if (!snippetEditorController) { - snippetEditorController = [[SnippetEditorController alloc] init]; - } - - [snippetEditorController showWindow:self]; -} - -- (IBAction)clearHistory:(id)sender -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL showAlert = [defaults boolForKey:CMPrefShowAlertBeforeClearHistoryKey]; - - if (showAlert) { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"Clear History", nil)]; - [alert setInformativeText:NSLocalizedString(@"Are you sure you want to clear your clipboard history?", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Clear History", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Cancel", nil)]; - [alert setShowsSuppressionButton:YES]; - - [NSApp activateIgnoringOtherApps:YES]; - - NSInteger result = [alert runModal]; - - if ([[alert suppressionButton] state] == NSOnState) { - [defaults setBool:NO forKey:CMPrefShowAlertBeforeClearHistoryKey]; - } - - [alert release], alert = nil; - - if (result != NSAlertFirstButtonReturn) { - return; - } - } - - [[ClipsController sharedInstance] clearAll]; -} - -- (void)popUpClipMenu:(id)sender -{ - [[MenuController sharedInstance] popUpMenuForType:CMPopUpMenuTypeMain]; -} - -- (void)popUpActionMenu:(id)sender -{ -// NSLog(@"selectAlternateMenuItem: %@", sender); - - NSArray *actionNodes = [[ActionController sharedInstance] actionNodes]; - if (!actionNodes || [actionNodes count] < 1) { - return; - } - - NSInteger tag = [sender tag]; - - NSManagedObject *snippet = ([sender representedObject]) ? [sender representedObject] : nil; - if (snippet) { - tag = -1; -// [[ActionController sharedInstance] setSelectedString:[snippet valueForKey:kContent]]; - [[ActionController sharedInstance] setSelectedSnippet:snippet]; - } - - [[ActionController sharedInstance] setSelectedClipTag:tag]; - - BOOL isInvokeFirstActionImmediately = [[NSUserDefaults standardUserDefaults] boolForKey:CMPrefInvokeActionImmediatelyKey]; - - if (isInvokeFirstActionImmediately && [actionNodes count] == 1) { - ActionNode *actionNode = [actionNodes objectAtIndex:0]; - NSDictionary *action = [actionNode action]; - if (action) { - [self _invokeAction:action]; - } - } - else { - [[MenuController sharedInstance] popUpMenuForType:CMPopUpMenuTypeActions]; - } - - [[ActionController sharedInstance] clearSelection]; -} - -- (void)popUpHistoryMenu:(id)sender -{ - [[MenuController sharedInstance] popUpMenuForType:CMPopUpMenuTypeHistory]; -} - -- (void)popUpSnippetsMenu:(id)sender -{ - [[MenuController sharedInstance] popUpMenuForType:CMPopUpMenuTypeSnippets]; -} - -- (void)selectMenuItem:(id)sender -{ -// NSLog(@"selectMenuItem: %@", sender); - - BOOL actionApplied = [self _applyActionToTarget:sender]; - if (actionApplied) { - return; // no problem - } - - NSInteger tag = [sender tag]; - [[ClipsController sharedInstance] copyClipToPasteboardAtIndex:tag]; - - [CMUtilities paste]; -} - -- (void)selectSnippetMenuItem:(id)sender -{ -// NSLog(@"selectSnippetMenuItem: %@", sender); - - NSManagedObject *snippet = [sender representedObject]; - if (!snippet) { - NSBeep(); - return; - } - -// NSLog(@"snippet: %@", snippet); - - BOOL actionApplied = [self _applyActionToTarget:sender]; - if (actionApplied) { - return; // no problem - } - - NSString *content = [snippet valueForKey:kContent]; - [[ClipsController sharedInstance] copyStringToPasteboard:content]; - [CMUtilities paste]; -} - -- (void)selectActionMenuItem:(id)sender -{ - NSDictionary *action = [sender representedObject]; - if (!action) { - return; - } - - [self _invokeAction:(NSDictionary *)action]; -} - -#pragma mark - -#pragma mark Private - -- (void)_toggleCheckPreReleaseUpdates:(BOOL)flag -{ - NSString *feed = (flag) - ? [CMUtilities infoValueForKey:@"SUPreReleaseFeedURL"] - : [CMUtilities infoValueForKey:@"SUFeedURL"]; - - NSURL *feedURL = [[NSURL alloc] initWithString:feed]; - [[SUUpdater sharedUpdater] setFeedURL:feedURL]; - [feedURL release], feedURL = nil; -} - -#pragma mark - Login Item - - -- (void)_promptToAddLoginItems -{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"Launch ClipMenu on system startup?", nil)]; - [alert setInformativeText:NSLocalizedString(@"You can change this setting in the Preferences if you want.", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Launch on system startup", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Don't Launch", nil)]; - [alert setShowsSuppressionButton:YES]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - [NSApp activateIgnoringOtherApps:YES]; - - if ([alert runModal] == NSAlertFirstButtonReturn) { - [defaults setBool:YES forKey:CMPrefLoginItemKey]; - [self _toggleLoginItemState]; - } - - if ([[alert suppressionButton] state] == NSOnState) { - [defaults setBool:YES forKey:CMPrefSuppressAlertForLoginItemKey]; - } - - [alert release], alert = nil; -} - -- (void)_toggleAddingToLoginItems:(BOOL)flag -{ - NSString *appPath = [[NSBundle mainBundle] bundlePath]; - - if (flag) { - [NMLoginItems addPathToLoginItems:appPath hide:NO]; - } - else { - [NMLoginItems removePathFromLoginItems:appPath]; - } -} - -- (void)_toggleLoginItemState -{ - BOOL isInLoginItems = [[NSUserDefaults standardUserDefaults] boolForKey:CMPrefLoginItemKey]; - [self _toggleAddingToLoginItems:isInLoginItems]; -} - -#pragma mark - HotKey - - -- (void)_registerHotKeys -{ - PTHotKeyCenter *hotKeyCenter = [PTHotKeyCenter sharedCenter]; - - //Read keyCombos from preferences - NSDictionary *hotKeyCombos = [[NSUserDefaults standardUserDefaults] objectForKey:CMPrefHotKeysKey]; - - NSDictionary *defaultHotKeyCombos = [AppController _defaultHotKeyCombos]; -// NSLog(@"hotKeyCombos: %@, defaultHotKeyCombos: %@", hotKeyCombos, defaultHotKeyCombos); - - for (NSString *identifier in defaultHotKeyCombos) { - id keyComboPlist = [hotKeyCombos objectForKey:identifier]; - if (keyComboPlist == nil) { - keyComboPlist = [defaultHotKeyCombos objectForKey:identifier]; - } - - PTKeyCombo *keyCombo = [[[PTKeyCombo alloc] initWithPlistRepresentation:keyComboPlist] - autorelease]; - - //Create our hot key - PTHotKey *hotKey = [[PTHotKey alloc] initWithIdentifier:identifier - keyCombo:keyCombo]; - - NSString *selectorName = [[[CMUtilities hotKeyMap] objectForKey:identifier] - objectForKey:kSelector]; - [hotKey setTarget:self]; - [hotKey setAction:NSSelectorFromString( selectorName )]; - - //Register it - [hotKeyCenter registerHotKey:hotKey]; - [hotKey release], hotKey = nil; - } -} - -- (void)_unregisterHotKeys -{ - //Unregister our hot key (not required?) - PTHotKeyCenter *hotKeyCenter = [PTHotKeyCenter sharedCenter]; - for (PTHotKey *hotKey in [hotKeyCenter allHotKeys]) { - [hotKeyCenter unregisterHotKey:hotKey]; - } -} - -- (BOOL)_invokeModifiedClickWithBehavior:(id)behavior andSender:(id)sender -{ - if (!behavior) { - return NO; - } - - if ([behavior respondsToSelector:@selector( isEqualToString: )]) { - if ([behavior isEqualToString:kEmptyString]) { - return NO; - } - else if ([behavior isEqualToString:kPopUpActionMenu]) { - [self popUpActionMenu:sender]; - } - } - else { - /* behavior must be an NSDictionary */ -// NSLog(@"behavior: %@", behavior); - [self _invokeAction:behavior toIndex:[sender tag]]; - } - - return YES; -} - -#pragma mark - Action - - -- (BOOL)_applyActionToTarget:(id)sender -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL enableAction = [defaults boolForKey:CMPrefEnableActionKey]; - - if (!enableAction) { - return NO; - } - - NSEvent *currentEvent = [NSApp currentEvent]; - id behavior; // NSString or NSDictionary - BOOL success = NO; - -// NSLog(@"currentEvent: %@", currentEvent); - - if ([currentEvent type] == NSRightMouseUp - || ([currentEvent modifierFlags] & NSControlKeyMask)) { - behavior = [defaults objectForKey:CMPrefContorlClickBehaviorKey]; - success = [self _invokeModifiedClickWithBehavior:behavior andSender:sender]; - } - else if ([currentEvent modifierFlags] & NSShiftKeyMask) { - behavior = [defaults objectForKey:CMPrefShiftClickBehaviorKey]; - success = [self _invokeModifiedClickWithBehavior:behavior andSender:sender]; - } - else if ([currentEvent modifierFlags] & NSAlternateKeyMask) { - behavior = [defaults objectForKey:CMPrefOptionClickBehaviorKey]; - success = [self _invokeModifiedClickWithBehavior:behavior andSender:sender]; - } - else if ([currentEvent modifierFlags] & NSCommandKeyMask) { - behavior = [defaults objectForKey:CMPrefCommandClickBehaviorKey]; - success = [self _invokeModifiedClickWithBehavior:behavior andSender:sender]; - } - - return success; -} - -- (void)_invokeAction:(NSDictionary *)action toIndex:(NSInteger)index -{ - NSString *type = [action objectForKey:@"type"]; - if (!type) { - return; - } - - id target; - - if (index < 0) { - /* it's a snippet */ - target = [[ActionController sharedInstance] selectedSnippet]; - } - else { - /* it's a clip */ - target = [[ClipsController sharedInstance] clipAtIndex:index]; - } - - if ([type isEqualToString:CMBuiltinActionTypeKey]) { -// Clip *clip = [[ClipsController sharedInstance] clipAtIndex:index]; -// [self _invokeBuiltinAction:action toClip:clip]; - - [self _invokeBuiltinAction:action toTarget:target]; - } - else if ([type isEqualToString:CMJavaScriptActionTypeKey]) { - [self _invokeJavaScriptAction:action atIndex:index]; - } -} - -- (void)_invokeAction:(NSDictionary *)action -{ -// NSLog(@"_invokeAction: %@", action); - - NSInteger tag = [[ActionController sharedInstance] selectedClipTag]; - [self _invokeAction:action toIndex:tag]; -} - -- (void)_invokeBuiltinAction:(NSDictionary *)action toTarget:(id)target -{ - NSString *actionName = [action objectForKey:@"name"]; - if (!actionName) { - return; - } - - [[ActionController sharedInstance] invokeCommandForKey:actionName toTarget:target]; -} - -- (void)_invokeJavaScriptAction:(NSDictionary *)action atIndex:(NSInteger)index -{ -// GetFrontProcess(&frontPSN); // Keep the most front of process -//// NSLog(@"frontPSN: %d, %d", frontPSN.highLongOfPSN, frontPSN.lowLongOfPSN); -// -//// [self _moveCurrentProcessToForeground]; -// -// [NSApp activateIgnoringOtherApps:YES]; // for prompt called by JavaScript - - NSString *scriptPath = [action objectForKey:@"path"]; - if (!scriptPath || ![[NSFileManager defaultManager] fileExistsAtPath:scriptPath]) { - CMRunAlertPanel(nil, - NSLocalizedString(@"The script you selected does not exist", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - return; - } - -// NSString *clipText; -// -// if (index < 0) { -// /* it's a snippet */ -// clipText = [[[ActionController sharedInstance] selectedSnippet] valueForKey:kContent]; -// } -// else { -// /* it's a clip */ -// Clip *selectedClip = [[ClipsController sharedInstance] clipAtIndex:index]; -// clipText = [selectedClip stringValue]; -// } -// -// NSString *scriptResult = [[ActionController sharedInstance] invokeScript:scriptPath toText:clipText]; -// if (!scriptResult) { -// return; -// } -// -// Clip *newClip = [Clip clipWithString:scriptResult]; -// if (!newClip) { -// return; -// } -// -// [[ClipsController sharedInstance] copyClipToPasteboard:newClip]; - - ActionController *actionController = [ActionController sharedInstance]; - Clip *selectedClip; - - if (index < 0) { - /* it's a snippet */ - NSString *snippetString = [[actionController selectedSnippet] valueForKey:kContent]; - selectedClip = [Clip clipWithString:snippetString]; - } - else { - /* it's a clip */ - selectedClip = [[ClipsController sharedInstance] clipAtIndex:index]; - } - - Clip *resultClip = [actionController invokeScript:scriptPath toClip:selectedClip]; - if (!resultClip) { - return; - } - - [[ClipsController sharedInstance] copyClipToPasteboard:resultClip]; - - [CMUtilities paste]; -} - -#pragma mark - Process - - -- (void)keepCurrentFrontProcessAndActivate -{ - GetFrontProcess(&frontPSN); // Keep the most front of process - [NSApp activateIgnoringOtherApps:YES]; -} - -- (BOOL)restorePreviousFrontProcess -{ - if (frontPSN.lowLongOfPSN == kNoProcess) { - return YES; - } - - // TransformProcessType(&frontPSN, kProcessTransformToForegroundApplication); // This doesn't work on Leopard - OSErr osError = SetFrontProcess(&frontPSN); - - frontPSN.highLongOfPSN = 0; - frontPSN.lowLongOfPSN = kNoProcess; - - if (osError == noErr) { - return YES; - } - return NO; -} - -#pragma mark - Notification - - -- (void)_handlePreferencePanelWillClose:(NSNotification *)aNotification -{ - [self _toggleLoginItemState]; -} - -@end diff --git a/Source/BuiltInActionController.h b/Source/BuiltInActionController.h deleted file mode 100644 index bffda59..0000000 --- a/Source/BuiltInActionController.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// BuiltInActionController.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -extern NSString *const CMBuiltInActionRemove; -extern NSString *const CMBuiltInActionPasteAsPlainText; -extern NSString *const CMBuiltInActionPasteAsFilePath; -extern NSString *const CMBuiltInActionPasteAsHFSFilePath; -//extern NSString *const CMBuiltInActionSpeak; - - -@class Clip; - -@interface BuiltInActionController : NSObject -{ - NSDictionary *actions; - NSDictionary *toolTips; - - NSArray *availableTypes; -} -@property (nonatomic, retain) NSDictionary *actions; -@property (nonatomic, retain) NSDictionary *toolTips; -@property (nonatomic, retain) NSArray *availableTypes; - -//- (void)remove:(Clip *)clip; -//- (void)pasteAsPlainText:(Clip *)clip; - -@end diff --git a/Source/BuiltInActionController.m b/Source/BuiltInActionController.m deleted file mode 100644 index 23fe2ea..0000000 --- a/Source/BuiltInActionController.m +++ /dev/null @@ -1,252 +0,0 @@ -// -// BuiltInActionController.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/06. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "BuiltInActionController.h" -#import "constants.h" -#import "CMUtilities.h" -#import "ClipsController.h" -#import "SnippetsController.h" -#import "Clip.h" - - -NSString *const CMBuiltInActionRemove = @"remove:"; -NSString *const CMBuiltInActionPasteAsPlainText = @"pasteAsPlainText:"; -NSString *const CMBuiltInActionPasteAsFilePath = @"pasteAsFilePath:"; -NSString *const CMBuiltInActionPasteAsHFSFilePath = @"pasteAsHFSFilePath:"; -//NSString *const CMBuiltInActionSpeak = @"speak:"; - - -@interface BuiltInActionController (Private) -- (void)_prepareActions; -- (void)_prepareToolTips; - -//- (NSDictionary *)_createAction:(NSString *)actionName forTypes:(NSArray *)types toolTip:(NSString *)toolTip; -- (NSDictionary *)_createAction:(NSString *)actionName forTypes:(NSArray *)types; - -- (NSDictionary *)_actionToRemove; -- (NSDictionary *)_actionToPasteAsPlainText; -- (NSDictionary *)_actionToPasteAsFilePath; -- (NSDictionary *)_actionToPasteAsHFSFilePath; -//- (NSDictionary *)_actionToSpeak; -@end - -@implementation BuiltInActionController (Private) - -- (void)_prepareActions -{ - NSMutableDictionary *newActions = [NSMutableDictionary dictionary]; - - NSArray *commandNames = [NSArray arrayWithObjects: - @"Remove", @"PasteAsPlainText", - @"PasteAsFilePath", @"PasteAsHFSFilePath", nil]; -// NSArray *commandNames = [NSArray arrayWithObjects: -// @"Remove", @"PasteAsPlainText", -// @"PasteAsFilePath", @"PasteAsHFSFilePath", -// @"Speak", nil]; - NSString *prefix = @"_actionTo"; - - for (NSString *commandName in commandNames) { - SEL aSelector = NSSelectorFromString([prefix stringByAppendingString:commandName]); - NSDictionary *command = [self performSelector:aSelector]; - [newActions setObject:command forKey:[command objectForKey:@"actionName"]]; - } - - [self setValue:newActions forKey:@"actions"]; -} - -- (void)_prepareToolTips -{ - NSDictionary *newToolTips = [NSDictionary dictionaryWithObjectsAndKeys: - NSLocalizedString(@"Remove the clip from the clipboard history", nil), CMBuiltInActionRemove, - NSLocalizedString(@"Paste the clip as Plain Text", nil), CMBuiltInActionPasteAsPlainText, - NSLocalizedString(@"Paste the clip as POSIX File Path", nil), CMBuiltInActionPasteAsFilePath, - NSLocalizedString(@"Paste the clip as HFS File Path", nil), CMBuiltInActionPasteAsHFSFilePath, -// NSLocalizedString(@"Speak", nil), CMBuiltInActionSpeak, - nil]; - - [self setValue:newToolTips forKey:@"toolTips"]; -} - -//- (NSDictionary *)_createAction:(NSString *)actionName forTypes:(NSArray *)types toolTip:(NSString *)toolTip -//{ -// NSMutableDictionary *action = [NSMutableDictionary dictionaryWithObjectsAndKeys: -// actionName, @"actionName", -// types, @"types", -// nil]; -// -// if (toolTip) { -// [action setObject:toolTip forKey:@"toolTip"]; -// } -// -// return action; -//} - -- (NSDictionary *)_createAction:(NSString *)actionName forTypes:(NSArray *)types -{ - NSDictionary *action = [NSDictionary dictionaryWithObjectsAndKeys: - actionName, @"actionName", - types, @"types", - nil]; - - return action; -} - -#pragma mark - Create Built-in Actions - - -- (NSDictionary *)_actionToRemove -{ - NSDictionary *action = [self _createAction:CMBuiltInActionRemove - forTypes:availableTypes]; - return action; -} - -- (NSDictionary *)_actionToPasteAsPlainText -{ - NSArray *types = [NSArray arrayWithObject:NSStringPboardType]; - NSDictionary *action = [self _createAction:CMBuiltInActionPasteAsPlainText - forTypes:types]; - return action; -} - -- (NSDictionary *)_actionToPasteAsFilePath -{ - NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType]; - NSDictionary *action = [self _createAction:CMBuiltInActionPasteAsFilePath - forTypes:types]; - return action; -} - -- (NSDictionary *)_actionToPasteAsHFSFilePath -{ - NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType]; - NSDictionary *action = [self _createAction:CMBuiltInActionPasteAsHFSFilePath - forTypes:types]; - return action; -} - -//- (NSDictionary *)_actionToSpeak -//{ -// NSArray *types = [NSArray arrayWithObject:NSStringPboardType]; -// NSDictionary *action = [self _createAction:CMBuiltInActionSpeak -// forTypes:types]; -// return action; -//} - -@end - - -@implementation BuiltInActionController - -@synthesize actions; -@synthesize toolTips; -@synthesize availableTypes; - -#pragma mark Initialize - -- (id)init -{ - self = [super init]; - if (self) { - [self setAvailableTypes:[Clip availableTypes]]; - - [self _prepareActions]; - [self _prepareToolTips]; - } - return self; -} - -- (void)dealloc -{ - [actions release], actions = nil; - [toolTips release], toolTips = nil; - [availableTypes release], availableTypes = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark Actions - -- (void)remove:(id)target -{ - if ([target isKindOfClass:[Clip class]]) { - [[ClipsController sharedInstance] removeClip:(Clip *)target]; - } - else { - [[SnippetsController sharedInstance] removeSnippet:(NSManagedObject *)target]; - } -} - -- (void)pasteAsPlainText:(id)target -{ - NSString *plainText; - - if ([target isKindOfClass:[Clip class]]) { - plainText = [target stringValue]; - } - else { - plainText = [target valueForKey:kContent]; - } - -// NSString *plainText = ([target isKindOfClass:[Clip class]]) ? [target stringValue] : target; - Clip *newClip = [Clip clipWithString:plainText]; - - [[ClipsController sharedInstance] copyClipToPasteboard:newClip]; - [CMUtilities paste]; -} - -- (void)pasteAsFilePath:(Clip *)clip -{ - NSArray *filenames = [clip filenames]; - NSString *results = [filenames componentsJoinedByString:kNewLine]; - Clip *newClip = [Clip clipWithString:results]; - - [[ClipsController sharedInstance] copyClipToPasteboard:newClip]; - [CMUtilities paste]; -} - -- (void)pasteAsHFSFilePath:(Clip *)clip -{ - NSArray *filenames = [clip filenames]; - - NSMutableArray *paths = [NSMutableArray array]; - - for (NSString *filename in filenames) { - NSURL *url = [NSURL fileURLWithPath:filename]; - if (!url) { - continue; - } - CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLHFSPathStyle); - [paths addObject:(NSString *)hfsPath]; - CFRelease(hfsPath); - } - - NSString *results = [paths componentsJoinedByString:kNewLine]; - Clip *newClip = [Clip clipWithString:results]; - - [[ClipsController sharedInstance] copyClipToPasteboard:newClip]; - [CMUtilities paste]; -} - -//- (void)speak:(id)target -//{ -// NSString *plainText; -// -// if ([target isKindOfClass:[Clip class]]) { -// plainText = [target stringValue]; -// } -// else { -// plainText = [target valueForKey:kContent]; -// } -// -// NSSpeechSynthesizer *synthesizer = [[NSSpeechSynthesizer alloc] init]; -// [synthesizer startSpeakingString:plainText]; -// [synthesizer release], synthesizer = nil; -//} - -@end diff --git a/Source/CMUtilities.h b/Source/CMUtilities.h deleted file mode 100644 index 8791bd6..0000000 --- a/Source/CMUtilities.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// CMUtilities.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/10. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface CMUtilities : NSObject -{ -} - -NSInteger CMRunAlertPanel(NSString *title, NSString *msg, NSString *defaultButton, NSString *alternateButton, NSString *otherButton); - -+ (BOOL)paste; -+ (NSDictionary *)hotKeyMap; - -+ (NSString *)localizedFileName:(NSString *)filename; -+ (id)infoValueForKey:(NSString*)key; - -+ (NSString *)applicationSupportFolder; -+ (NSString *)scriptLibFolder; -+ (NSString *)userLibFolder; -+ (NSString *)bundledActionsFolder; -+ (NSString *)userActionsFolder; -+ (BOOL)prepareSaveToPath:(NSString *)path; - -@end diff --git a/Source/CMUtilities.m b/Source/CMUtilities.m deleted file mode 100644 index 5b42bb5..0000000 --- a/Source/CMUtilities.m +++ /dev/null @@ -1,355 +0,0 @@ -// -// CMUtilities.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/10. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "CMUtilities.h" -#import "constants.h" -#import "PrefsWindowController.h" -#import - - -static NSInteger vKeyCode = 0; - - -@implementation CMUtilities - -#pragma mark Functions - -//BOOL postCommandV(BOOL isANSILayout) -//{ -// /*" fakeCommandV synthesizes keyboard events for Cmd-v Paste shortcut. "*/ -//// CGPostKeyboardEvent( (CGCharCode)0, (CGKeyCode)55, true ); // command key down -//// CGPostKeyboardEvent( (CGCharCode)'v', (CGKeyCode)9, true ); // 'v' key down -//// CGPostKeyboardEvent( (CGCharCode)'v', (CGKeyCode)9, false ); // 'v' key up -//// CGPostKeyboardEvent( (CGCharCode)0, (CGKeyCode)55, false ); // command key up -// -// -// CGEventSourceRef sourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); -// if (!sourceRef) { -// NSLog(@"No event source"); -// return NO; -// } -// -// NSUInteger vKeyCode = (isANSILayout) ? kVK_ANSI_V : kVK_ANSI_Period; -// CGEventRef eventDown, eventUp; -// -// NSLog(@"key: %d", vKeyCode); -// -// eventDown = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)vKeyCode, true); // v key down -// CGEventSetFlags(eventDown, kCGEventFlagMaskCommand); // command key press -// eventUp = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)vKeyCode, false); // v key up -// -// CGEventPost(kCGSessionEventTap, eventDown); -// CGEventPost(kCGSessionEventTap, eventUp); -// -// CFRelease(eventDown); -// CFRelease(eventUp); -// CFRelease(sourceRef); -// -// return YES; -//} - -NSString *transformKeyCode(NSInteger keyCode) -{ - // Can be -1 when empty - if ( keyCode < 0 ) return nil; - - OSStatus err; - TISInputSourceRef tisSource = TISCopyCurrentKeyboardLayoutInputSource(); - - if(!tisSource) return nil; - - CFDataRef layoutData; - UInt32 keysDown = 0; - layoutData = (CFDataRef)TISGetInputSourceProperty(tisSource, kTISPropertyUnicodeKeyLayoutData); - CFRelease(tisSource); - - if(!layoutData) return nil; - const UCKeyboardLayout *keyLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); - - UniCharCount length = 4, realLength; - UniChar chars[4]; - - err = UCKeyTranslate(keyLayout, - keyCode, - kUCKeyActionDisplay, - 0, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &keysDown, - length, - &realLength, - chars); - - if ( err != noErr ) return nil; - - NSString *keyString = [[NSString stringWithCharacters:chars length:1] uppercaseString]; - - return keyString; -} - -BOOL postCommandV() -{ - CGEventSourceRef sourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); - if (!sourceRef) { - NSLog(@"No event source"); - return NO; - } - - if (vKeyCode == 0) { -// NSString *transformedKey = transformKeyCode(vKeyCode); -// NSLog(@"transformedKey: %@", transformedKey); - - // loop over every keycode (0 - 127) finding its current string mapping... - NSMutableDictionary *stringToKeyCodeDict = [[NSMutableDictionary alloc] init]; - NSUInteger i; - for ( i = 0U; i < 128U; i++ ) - { - NSString *string = transformKeyCode(i); - if ( ( string ) && ( [string length] ) ) - { - NSNumber *keyCode = [NSNumber numberWithUnsignedInteger:i]; - [stringToKeyCodeDict setObject:keyCode forKey:string]; - } - } - -// NSLog(@"dict: %@", stringToKeyCodeDict); - - NSNumber *keyCodeNum = [stringToKeyCodeDict objectForKey:@"V"]; - [stringToKeyCodeDict release], stringToKeyCodeDict = nil; - - if (!keyCodeNum) { - return NO; - } - - vKeyCode = [keyCodeNum unsignedIntegerValue]; - } - -// NSLog(@"key: %d", vKeyCode); - - CGEventRef eventDown, eventUp; - - eventDown = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)vKeyCode, true); // v key down - CGEventSetFlags(eventDown, kCGEventFlagMaskCommand); // command key press - eventUp = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)vKeyCode, false); // v key up - CGEventSetFlags(eventUp, kCGEventFlagMaskCommand); // command key up - - CGEventPost(kCGSessionEventTap, eventDown); - CGEventPost(kCGSessionEventTap, eventUp); - - CFRelease(eventDown); - CFRelease(eventUp); - CFRelease(sourceRef); - - return YES; -} - -NSInteger CMRunAlertPanel(NSString *title, NSString *msg, NSString *defaultButton, NSString *alternateButton, NSString *otherButton) -{ - [NSApp activateIgnoringOtherApps:YES]; - - NSInteger result = NSRunAlertPanel(title, - msg, - defaultButton, - alternateButton, - otherButton); - return result; -} - -#pragma mark - - -+ (BOOL)paste -{ - if (![[NSUserDefaults standardUserDefaults] boolForKey:CMPrefInputPasteCommandKey]) { - return NO; - } - - return postCommandV(); -} - -+ (NSDictionary *)hotKeyMap -{ - NSMutableDictionary *map = [NSMutableDictionary dictionary]; - NSDictionary *dict; - NSUInteger index = 0; - - dict = [[NSDictionary alloc] initWithObjectsAndKeys: - [NSNumber numberWithUnsignedInteger:index], kIndex, - @"popUpClipMenu:", kSelector, - nil]; - [map setObject:dict forKey:kClipMenuIdentifier]; - [dict release], dict = nil; - index++; - - dict = [[NSDictionary alloc] initWithObjectsAndKeys: - [NSNumber numberWithUnsignedInteger:index], kIndex, - @"popUpHistoryMenu:", kSelector, - nil]; - [map setObject:dict forKey:kHistoryMenuIdentifier]; - [dict release], dict = nil; - index++; - - dict = [[NSDictionary alloc] initWithObjectsAndKeys: - [NSNumber numberWithUnsignedInteger:index], kIndex, - @"popUpSnippetsMenu:", kSelector, - nil]; - [map setObject:dict forKey:kSnippetsMenuIdentifier]; - [dict release], dict = nil; -// index++; - - return map; -} - -/* Ignore warnings for this method */ -+ (NSString *)localizedFileName:(NSString *)filename -{ - return NSLocalizedString(filename, nil); -} - -+ (id)infoValueForKey:(NSString*)key -{ - NSBundle *bundle = [NSBundle mainBundle]; - NSString *value; - - // InfoPlist.strings entries have priority over Info.plist ones. - value = [[bundle localizedInfoDictionary] objectForKey:key]; - if (value) { - return value; - } - - return [[bundle infoDictionary] objectForKey:key]; -} - - -#pragma mark Archiver - -+ (NSString *)applicationSupportFolder -{ - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); - NSString *basePath = (0 < [paths count]) ? [paths objectAtIndex:0] : NSTemporaryDirectory(); - - return [basePath stringByAppendingPathComponent:kApplicationName]; -} - -+ (NSString *)scriptLibFolder -{ - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - if (!resourcePath) { - return nil; - } - - NSArray *pathArray = [NSArray arrayWithObjects: - resourcePath, - kScriptDirectory, - kLibraryScriptDirectory, - nil]; - if (!pathArray) { - return nil; - } - - NSString *path = [NSString pathWithComponents:pathArray]; - - BOOL isDir; - if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] - || !isDir) { - return nil; - } - - return path; -} - -+ (NSString *)userLibFolder -{ - NSString *applicationSupportFolder = [self applicationSupportFolder]; - - NSArray *pathArray = [NSArray arrayWithObjects: - applicationSupportFolder, - kScriptDirectory, - kLibraryScriptDirectory, - nil]; - if (!pathArray) { - return nil; - } - - NSString *path = [NSString pathWithComponents:pathArray]; - - BOOL isDir; - if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] - || !isDir) { - return nil; - } - - return path; -} - -+ (NSString *)bundledActionsFolder -{ - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - if (!resourcePath) { - return nil; - } - - NSArray *pathArray = [NSArray arrayWithObjects: - resourcePath, - kScriptDirectory, - kActionDirectory, - nil]; - if (!pathArray) { - return nil; - } - - NSString *path = [NSString pathWithComponents:pathArray]; - - BOOL isDir; - if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] - || !isDir) { - return nil; - } - - return path; -} - -+ (NSString *)userActionsFolder -{ - NSArray *pathArray = [NSArray arrayWithObjects: - [self applicationSupportFolder], - kScriptDirectory, - kActionDirectory, - nil]; - if (!pathArray) { - return nil; - } - - NSString *path = [NSString pathWithComponents:pathArray]; - - BOOL isDir; - if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] - || !isDir) { - return nil; - } - - return path; -} - -+ (BOOL)prepareSaveToPath:(NSString *)path -{ - NSFileManager *fileManager = [NSFileManager defaultManager]; - BOOL isDir; - - if (([fileManager fileExistsAtPath:path isDirectory:&isDir] && isDir) == NO) { - if (![fileManager createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:NULL]) { - return NO; - } - } - - return YES; -} - -@end diff --git a/Source/Clip.h b/Source/Clip.h deleted file mode 100644 index 2574952..0000000 --- a/Source/Clip.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Clip.h -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/02. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import - -@interface Clip : NSObject -{ - NSArray *types; - NSDate *createdDate; - NSDate *lastUsedDate; - - NSString *stringValue; - NSData *RTFData; -// NSData *RTF; -// NSData *RTFD; - NSData *PDF; - NSArray *filenames; - NSArray *URL; - NSImage *image; - - NSUInteger cachedHash; - NSImage *thumbnail; - NSSize thumbnailSize; -} -@property (nonatomic, retain) NSArray *types; -@property (nonatomic, retain) NSDate *createdDate; -@property (nonatomic, retain) NSDate *lastUsedDate; -@property (nonatomic, retain) NSString *stringValue; -@property (nonatomic, retain) NSData *RTFData; -//@property (nonatomic, readonly) NSData *RTF; -//@property (nonatomic, readonly) NSData *RTFD; -@property (nonatomic, retain) NSData *PDF; -@property (nonatomic, retain) NSArray *filenames; -@property (nonatomic, retain) NSArray *URL; -@property (nonatomic, retain) NSImage *image; - -+ (id)clipWithString:(NSString *)aString; -- (id)initWithString:(NSString *)aString; -- (id)initWithClip:(Clip *)aClip; - -+ (NSArray *)availableTypes; -+ (NSArray *)availableTypeNames; -+ (NSDictionary *)availableTypeDictionary; -+ (NSImage *)fileTypeIconForPboardType:(NSString *)aType; - -- (NSString *)description; -- (NSString *)primaryPboardType; -- (NSImage *)thumbnailOfSize:(NSSize)size; -//- (BOOL)isEqualToClip:(Clip *)otherClip; - -@end diff --git a/Source/Clip.m b/Source/Clip.m deleted file mode 100644 index 79c685b..0000000 --- a/Source/Clip.m +++ /dev/null @@ -1,584 +0,0 @@ -// -// Clip.m -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/02. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import "Clip.h" - - -#define TYPES_KEY @"types" -#define CREATED_DATE_KEY @"createdDate" -#define LAST_USED_DATE_KEY @"lastUsedDate" -#define STRING_VALUE_KEY @"stringValue" -#define RTFDATA_KEY @"RTFData" -#define RTF_KEY @"RTF" -#define RTFD_KEY @"RTFD" -#define PDF_KEY @"PDF" -#define FILENAMES_KEY @"filenames" -#define URL_KEY @"URL" -#define IMAGE_KEY @"image" - - -//@interface Clip (Private) -//- (BOOL)_isEqualToTIFF:(NSImage *)otherImage; -//@end -// -//@implementation Clip (Private) -// -//- (BOOL)_isEqualToTIFF:(NSImage *)otherImage -//{ -//// NSLog(@"Enter image equality check."); -// -// NSData *TIFFImage = [image TIFFRepresentation]; -// NSData *otherData = [otherImage TIFFRepresentation]; -// -// NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:TIFFImage]; -// NSBitmapImageRep *otherRep = [NSBitmapImageRep imageRepWithData:otherData]; -// -//// NSLog(@"length: %d, other: %d", [TIFFImage length], [otherData length]); -//// NSLog(@"imageRep: %@", imageRep); -//// NSLog(@"otherRep: %@", otherRep); -// -// /* NSImageRep */ -// if (!NSEqualSizes([imageRep size],[otherRep size])) { -// return NO; -// } -// if (![[imageRep colorSpaceName] isEqualToString:[otherRep colorSpaceName]]) { -// return NO; -// } -// if ([imageRep bitsPerSample] != [otherRep bitsPerSample]) { -// return NO; -// } -// if ([imageRep hasAlpha] != [otherRep hasAlpha]) { -// return NO; -// } -// if ([imageRep isOpaque] != [otherRep isOpaque]) { -// return NO; -// } -// -// /* NSBitmapImageRep */ -//// NSLog(@"me: %d, other: %d", [imageRep bitmapFormat], [otherRep bitmapFormat]); -// if ([imageRep bitmapFormat] != [otherRep bitmapFormat]) { // this doesn't work correctly -//// NSLog(@"Not equal!"); -// return NO; -// } -// -// if ([imageRep isPlanar] != [otherRep isPlanar]) { -// return NO; -// } -// if ([imageRep samplesPerPixel] != [otherRep samplesPerPixel]) { -// return NO; -// } -// -// /* NSData */ -// if (![TIFFImage isEqualToData:otherData]) { -//// NSLog(@"Not equal!"); -// return NO; -// } -// -//// NSLog(@"Same image."); -// return YES; -//} -// -//@end - -@interface Clip () -- (NSBitmapImageRep *)_representationOfBitmapImageRep:(NSBitmapImageRep *)bitmapRep withSize:(NSSize)size; -@end - -#pragma mark - - -@implementation Clip - -@synthesize types; -@synthesize createdDate; -@synthesize lastUsedDate; -@synthesize stringValue; -@synthesize RTFData; -//@synthesize RTF; -//@synthesize RTFD; -@synthesize PDF; -@synthesize filenames; -@synthesize URL; -@synthesize image; - -#pragma mark Class methods - -+ (NSArray *)availableTypes -{ - return [NSArray arrayWithObjects: - NSStringPboardType, - NSRTFPboardType, - NSRTFDPboardType, - NSPDFPboardType, - NSFilenamesPboardType, - NSURLPboardType, - NSTIFFPboardType, - NSPICTPboardType, - nil]; -} - -+ (NSArray *)availableTypeNames -{ - return [NSArray arrayWithObjects: - @"String", - @"RTF", - @"RTFD", - @"PDF", - @"Filenames", - @"URL", - @"TIFF", - @"PICT", - nil]; -} - -+ (NSDictionary *)availableTypeDictionary -{ - return [NSDictionary dictionaryWithObjects:[self availableTypeNames] - forKeys:[self availableTypes]]; -} - -+ (NSImage *)fileTypeIconForPboardType:(NSString *)aType -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - NSString *pbType = nil; - if ([aType isEqualToString:NSStringPboardType]) { - pbType = @"String"; - } - else if ([aType isEqualToString:NSRTFPboardType]) { - pbType = @"RTF"; - } - else if ([aType isEqualToString:NSRTFDPboardType]) { - pbType = @"RTFD"; - } - else if ([aType isEqualToString:NSPDFPboardType]) { - pbType = @"PDF"; - } - else if ([aType isEqualToString:NSFilenamesPboardType]) { - pbType = @"Filenames"; - } - else if ([aType isEqualToString:NSURLPboardType]) { - pbType = @"URL"; - } - else if ([aType isEqualToString:NSTIFFPboardType]) { - pbType = @"TIFF"; - } - else if ([aType isEqualToString:NSPICTPboardType]) { - pbType = @"PICT"; - } - - NSString *fileTypeSelectionTagKey = [NSString stringWithFormat: - @"menuIconOfFileTypeTagFor%@", pbType]; - NSString *fileTypeKey = [NSString stringWithFormat: - @"menuIconOfFileTypeFor%@", pbType]; - NSString *fileType = [defaults stringForKey:fileTypeKey]; - - switch ([defaults integerForKey:fileTypeSelectionTagKey]) { - case 1: { - OSType hfsTypeCode = NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", fileType]); - fileType = NSFileTypeForHFSTypeCode(hfsTypeCode); - break; - } - } - - return [[NSWorkspace sharedWorkspace] iconForFileType:fileType]; -} - -#pragma mark Initialize - -+ (id)clipWithString:(NSString *)aString -{ -// Clip *clip = [[[[self class] alloc] init] autorelease]; -// [clip setStringValue:aString]; -// [clip setTypes:[NSArray arrayWithObject:NSStringPboardType]]; -// return clip; - - return [[[[self class] alloc] initWithString:aString] autorelease]; -} - -/* Designated Initializer */ -- (id)init -{ - self = [super init]; - if (self == nil) { - return nil; - } - - NSDate *currentDate = [NSDate date]; - [self setCreatedDate:currentDate]; - [self setLastUsedDate:currentDate]; - - return self; -} - -- (id)initWithString:(NSString *)aString -{ - Clip *clip = [self init]; - if (clip == nil) { - return nil; - } - - [clip setStringValue:aString]; - [clip setTypes:[NSArray arrayWithObject:NSStringPboardType]]; - return clip; -} - -- (id)initWithClip:(Clip *)aClip -{ - Clip *clip = [self init]; - if (clip == nil) { - return nil; - } - - [clip setTypes:[aClip types]]; - [clip setCreatedDate:[aClip createdDate]]; - [clip setLastUsedDate:[aClip lastUsedDate]]; - [clip setStringValue:[aClip stringValue]]; - [clip setRTFData:[aClip RTFData]]; -// [clip setRTF:[aClip RTF]]; -// [clip setRTFD:[aClip RTFD]]; - [clip setPDF:[aClip PDF]]; - [clip setFilenames:[aClip filenames]]; - [clip setURL:[aClip URL]]; - [clip setImage:[aClip image]]; - - return clip; -} - -- (void)dealloc -{ - [types release], types = nil; - [createdDate release], createdDate = nil; - [lastUsedDate release], lastUsedDate = nil; - [stringValue release], stringValue = nil; - [RTFData release], RTFData = nil; -// [RTF release], RTF = nil; -// [RTFD release], RTFD = nil; - [PDF release], PDF = nil; - [filenames release], filenames = nil; - [URL release], URL = nil; - [image release], image = nil; - [thumbnail release], thumbnail = nil; - - [super dealloc]; -} - -#pragma mark - Copying - - -- (id)copyWithZone:(NSZone *)zone -{ - return [[[self class] allocWithZone:zone] initWithClip:self]; -} - -#pragma mark - Archiving - - -- (void)encodeWithCoder:(NSCoder *)encoder -{ - [encoder encodeObject:self.types forKey:TYPES_KEY]; - [encoder encodeObject:self.createdDate forKey:CREATED_DATE_KEY]; - [encoder encodeObject:self.lastUsedDate forKey:LAST_USED_DATE_KEY]; - [encoder encodeObject:self.stringValue forKey:STRING_VALUE_KEY]; - [encoder encodeObject:self.RTFData forKey:RTFDATA_KEY]; -// [encoder encodeObject:self.RTF forKey:RTF_KEY]; -// [encoder encodeObject:self.RTFD forKey:RTFD_KEY]; - [encoder encodeObject:self.PDF forKey:PDF_KEY]; - [encoder encodeObject:self.filenames forKey:FILENAMES_KEY]; - [encoder encodeObject:self.URL forKey:URL_KEY]; - [encoder encodeObject:self.image forKey:IMAGE_KEY]; -} - -- (id)initWithCoder:(NSCoder *)decoder -{ - self = [super init]; - if (self) { - NSDate *createdAt = [decoder decodeObjectForKey:CREATED_DATE_KEY]; - if (createdAt == nil) { - createdAt = [NSDate date]; - } - - NSDate *usedAt = [decoder decodeObjectForKey:LAST_USED_DATE_KEY]; - if (usedAt == nil) { - usedAt = [decoder decodeObjectForKey:@"lastAccessedDate"]; // ivar name of v0.4.2a2 to v0.4.2a4 - if (usedAt == nil) { - usedAt = createdAt; - } - } - - NSData *rtfData = [decoder decodeObjectForKey:RTFDATA_KEY]; - if (rtfData == nil) { - rtfData = [decoder decodeObjectForKey:RTFD_KEY]; - if (rtfData == nil) { - rtfData = [decoder decodeObjectForKey:RTF_KEY]; - } - } - - [self setTypes:[decoder decodeObjectForKey:TYPES_KEY]]; - [self setCreatedDate:createdAt]; - [self setLastUsedDate:usedAt]; - [self setStringValue:[decoder decodeObjectForKey:STRING_VALUE_KEY]]; - [self setRTFData:rtfData]; -// [self setRTF:[decoder decodeObjectForKey:RTF_KEY]]; -// [self setRTFD:[decoder decodeObjectForKey:RTFD_KEY]]; - [self setPDF:[decoder decodeObjectForKey:PDF_KEY]]; - [self setFilenames:[decoder decodeObjectForKey:FILENAMES_KEY]]; - [self setURL:[decoder decodeObjectForKey:URL_KEY]]; - [self setImage:[decoder decodeObjectForKey:IMAGE_KEY]]; - } - return self; -} - -#pragma mark - - -- (NSString *)description -{ - return [NSString stringWithFormat:@"types: %@\nstring: %@", self.types, self.stringValue]; -} - -- (NSString *)primaryPboardType -{ - if (!self.types || [self.types count] < 0) { - return nil; - } - - return [self.types objectAtIndex:0]; -} - -- (NSImage *)thumbnailOfSize:(NSSize)size -{ - if (thumbnail && - NSEqualSizes(thumbnailSize, size)) { -// NSLog(@"cachedSize: %@", NSStringFromSize(thumbnailSize)); - return thumbnail; - } - - NSArray *representations = [self.image representations]; - NSBitmapImageRep *bitmapRep = nil; - - for (NSImageRep *rep in representations) { - if ([rep isKindOfClass:[NSBitmapImageRep class]]) { - bitmapRep = (NSBitmapImageRep *)rep; - break; - } - } - - if (bitmapRep == nil) { - return nil; - } - - NSInteger origWidth = [bitmapRep pixelsWide]; - NSInteger origHeight = [bitmapRep pixelsHigh]; - - CGFloat aspect = (CGFloat)origWidth / (CGFloat)origHeight; - -// NSLog(@"width: %d, height: %d, aspect: %f", origWidth, origHeight, aspect); - - CGFloat targetWidth = size.width; - CGFloat targetHeight = size.height; - CGFloat newWidth; - CGFloat newHeight; - - /* Resize */ - /* from Zachary Wily's NSBitmapImageRep+sizing.m of iPhotoToGallery */ - /* http://github.com/zwily/iphototogallery */ - if (1 <= aspect) { - newWidth = targetWidth; - newHeight = newWidth / aspect; - - if (targetHeight < newHeight) { - newHeight = targetHeight; - newWidth = targetHeight * aspect; - } - } - else { - newHeight = targetHeight; - newWidth = targetHeight * aspect; - - if (targetWidth < newWidth) { - newWidth = targetWidth; - newHeight = targetWidth / aspect; - } - } - - // Don't go any bigger! - if (origWidth < newWidth) { - newWidth = origWidth; - } - - if (origHeight < newHeight) { - newHeight = origHeight; - } - - /* Make new image representation */ - NSImageRep *newImageRep; - - if ([self.image respondsToSelector:@selector( bestRepresentationForRect:context:hints: )]) { - /* Mac OS X 10.6 and later */ - newImageRep = [self.image bestRepresentationForRect:NSMakeRect(0, 0, newWidth, newHeight) - context:nil - hints:nil]; - } - else { - newImageRep = [self _representationOfBitmapImageRep:bitmapRep - withSize:NSMakeSize(newWidth, newHeight)]; - } - - if (newImageRep == nil) { -// NSLog(@"No newImageRep"); - return nil; - } - - thumbnail = [[NSImage alloc] initWithSize:NSMakeSize(newWidth, newHeight)]; - [thumbnail addRepresentation:newImageRep]; - - thumbnailSize = size; -// [self.image setCacheMode:NSImageCacheNever]; - - return thumbnail; -} - -#pragma mark - Override - - -NSUInteger -integerFromBytes(uint8_t * bytes, NSUInteger length) -{ - NSUInteger i, value = 0; - for (i = 0; i < length; i++) - value = (value << 8) | bytes[i]; - return value; -} - -- (NSUInteger)hash -{ -// if (cachedHash) { -//// NSLog(@"cached hash: %u\n", cachedHash); -// return cachedHash; -// } - - cachedHash = 0; - - cachedHash = [[self.types componentsJoinedByString:@""] hash]; - - - if (self.image) { -// NSLog(@"image: %u", [[self.image TIFFRepresentation] length]); - cachedHash ^= [[self.image TIFFRepresentation] length]; - } - - if (self.filenames) { -// NSLog(@"filenames: %@", self.filenames); - for (NSString *filename in filenames) { -// NSLog(@"f: %d", [filename hash]); - cachedHash ^= [filename hash]; - } - } - else if (self.URL) { -// NSLog(@"URL: %@", self.URL); - for (NSString *aURL in URL) { -// NSLog(@"aURL: %d", [aURL hash]); - cachedHash ^= [aURL hash]; - } - } - else if (self.PDF) { - cachedHash ^= [self.PDF length]; - } - else if (self.stringValue) { -// NSLog(@"String: %u", [self.stringValue hash]); - cachedHash ^= [self.stringValue hash]; - } - - if (self.RTFData) { - /* Despite attributes modified, length doesn't change. Why? */ - -// NSLog(@"RTFData: %qu", [self.RTFData length]); - -// NSData *rtfData = self.RTFData; -// NSUInteger rtfLength = [rtfData length]; -// unsigned char *buffer = NSZoneMalloc([self zone], rtfLength); -// [rtfData getBytes:buffer length:rtfLength]; -// NSLog(@"bytes: %qi", buffer); -// -// -// NSUInteger v = 0; -// for (NSUInteger i = 0; i < rtfLength; i++) { -//// v += buffer[i]; -// char c = buffer[i]; -//// NSLog(@"c: %d", (int)c); -// v += (int)(c); -// } -// -// NSLog(@"casted buffer: %d", v); -// -//// cachedHash ^= (NSUInteger)*buffer; -// NSZoneFree([self zone], buffer); - - cachedHash ^= [self.RTFData length]; - } - -// if (self.RTFD) { -//// NSLog(@"RTFD"); -// cachedHash ^= [self.RTFD length]; -// } -// else if (self.RTF) { -//// NSLog(@"RTF: %u", [self.RTF length]); -// cachedHash ^= [self.RTF length]; -// } - -// NSLog(@"hash: %u\n", cachedHash); - - return cachedHash; -} - -- (BOOL)isEqual:(id)anObject -{ - if (anObject == self) { - return YES; - } - - if (!anObject || ![anObject isKindOfClass:[Clip class]]) { - return NO; - } - - if ([self hash] == [anObject hash]) { - return YES; - } - - return NO; -} - -//- (id)valueForKey:(NSString *)key -//{ -// id value; -// -// if ([key isEqualToString:@"stringValue"]) { -// value = @"stringValue"; -// } -// else { -// value = [super valueForKey:key]; -// } -// -// return value; -//} - -#pragma mark Private - -/* from Zachary Wily's NSBitmapImageRep+sizing.m of iPhotoToGallery */ -/* http://github.com/zwily/iphototogallery */ -- (NSBitmapImageRep *)_representationOfBitmapImageRep:(NSBitmapImageRep *)bitmapRep withSize:(NSSize)size -{ - NSRect rect = NSMakeRect(0, 0, size.width, size.height); - NSImage *anImage = [[[NSImage alloc] initWithSize:size] autorelease]; - NSBitmapImageRep *outRep; - [anImage lockFocus]; - [[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationHigh]; - [[NSGraphicsContext currentContext] setShouldAntialias:YES]; - [bitmapRep drawInRect:rect]; - outRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:rect] autorelease]; - [anImage unlockFocus]; - return outRep; -} - -@end diff --git a/Source/ClipsController.h b/Source/ClipsController.h deleted file mode 100644 index f88ba7d..0000000 --- a/Source/ClipsController.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// ClipsController.h -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/02. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import - -@class Clip; - -@interface ClipsController : NSObject -{ - NSMutableSet *clips; // use "mutableArrayValueForKey" to access - NSDictionary *storeTypes; - NSSet *excludeIdentifiers; - NSUInteger maxClipsSize; - NSUInteger cachedChangeCount; - - NSDate *lastClipsUpdated; - NSDate *lastSaved; - - NSTimer *pboardObservingTimer; - NSTimer *autosaveTimer; - -// BOOL isHalted; -} -@property (nonatomic, copy) NSMutableSet *clips; -@property (nonatomic, retain) NSDictionary *storeTypes; -@property (nonatomic, retain) NSSet *excludeIdentifiers; -@property (nonatomic, assign) NSUInteger maxClipsSize; -@property (nonatomic, assign) NSUInteger cachedChangeCount; -@property (nonatomic, retain) NSDate *lastClipsUpdated; -@property (nonatomic, retain) NSDate *lastSaved; -//@property (nonatomic, assign) BOOL isHalted; -@property (readonly) NSArray *sortedClips; - -+ (ClipsController *)sharedInstance; - -- (void)startAutosaveTimer; -- (void)stopAutosaveTimer; - -- (BOOL)saveClips; -- (void)loadClips; -- (void)removeClips; - -- (BOOL)exportHistoryStringsAsSingleFile:(NSString *)path; -- (BOOL)exportHistoryStringsAsMultipleFiles:(NSString *)path; - -- (void)clearAll; -- (Clip *)clipAtIndex:(NSUInteger)index; -- (BOOL)removeClipAtIndex:(NSUInteger)index; -- (BOOL)removeClip:(Clip *)clip; -- (void)copyStringToPasteboard:(NSString *)aString; -- (void)copyClipToPasteboard:(Clip *)clip; -- (void)copyClipToPasteboardAtIndex:(NSUInteger)index; - -//- (void)startUpdate; -//- (void)restartUpdate; -//- (void)haltUpdate; - -@end diff --git a/Source/ClipsController.m b/Source/ClipsController.m deleted file mode 100644 index b6781ae..0000000 --- a/Source/ClipsController.m +++ /dev/null @@ -1,886 +0,0 @@ -// -// ClipsController.m -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/02. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import "ClipsController.h" -#import "Clip.h" -#import "constants.h" -#import "CMUtilities.h" -#import "PrefsWindowController.h" -#import "MenuController.h" - - -#define MAX_TIME_INTERVAL 1.0 -#define MIN_AUTOSAVE_INTERVAL 15 - -static ClipsController *sharedInstance = nil; - - -@interface ClipsController () -- (void)_updateClips:(id)sender; -- (Clip *)_makeClipFromPasteboard:(NSPasteboard *)pboard; -- (NSArray *)_makeTypesFromPasteboard:(NSPasteboard *)pboard; -- (BOOL)_storeType:(NSString *)type; -- (BOOL)_frontProcessIsInExcludeList; - -- (void)_trimHistorySize; -- (void)_startPasteboardObservingTimer; -- (void)_autosave; -- (void)_fireSaveClips; - -- (NSString *)_saveFilePath; - -- (id)_init; -@end - - -#pragma mark - - -@implementation ClipsController - -@synthesize clips; -@synthesize storeTypes; -@synthesize excludeIdentifiers; -@synthesize maxClipsSize; -@synthesize cachedChangeCount; -@synthesize lastClipsUpdated; -@synthesize lastSaved; -//@synthesize isHalted; -@dynamic sortedClips; - -#pragma mark Initialize - -+ (void)initialize -{ - if (sharedInstance == nil) { - sharedInstance = [[self alloc] _init]; - } -} - -+ (ClipsController *)sharedInstance -{ - return [[sharedInstance retain] autorelease]; -} - -- (id)init -{ - NSAssert(self != sharedInstance, @"Should never send init to the singleton instance"); - - [self release]; - [sharedInstance retain]; - return sharedInstance; -} - -- (NSSet *)_getExcludeBundleIdentifiersFromList:(NSArray *)excludeList -{ - if ([excludeList count] == 0) { - return nil; - } - - NSArray *values = [excludeList valueForKey:kCMBundleIdentifierKey]; - return [NSSet setWithArray:values]; -} - -- (id)_init -{ - self = [super init]; - if (self) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - [self setClips:[NSMutableSet set]]; - [self setStoreTypes:[defaults objectForKey:CMPrefStoreTypesKey]]; - [self setMaxClipsSize:[defaults integerForKey:CMPrefMaxHistorySizeKey]]; - - /* Exclude Identifiers */ - NSArray *excludeList = [defaults objectForKey:CMPrefExcludeAppsKey]; -// NSSet *set = nil; -// -// if (excludeList && 0 < [excludeList count]) { -// NSArray *values = [excludeList valueForKey:kCMBundleIdentifierKey]; -// set = [NSSet setWithArray:values]; -// } - - NSSet *set = [self _getExcludeBundleIdentifiersFromList:excludeList]; - - if (set) { - [self setExcludeIdentifiers:set]; - } - else { - [self setExcludeIdentifiers:[NSSet set]]; - } - - /* Date */ - NSDate *now; - - now = [[NSDate alloc] init]; - [self setLastClipsUpdated:now]; - [now release], now = nil; - - now = [[NSDate alloc] initWithTimeIntervalSinceNow:1]; - [self setLastSaved:now]; - [now release], now = nil; - - /* Timer */ - [self _startPasteboardObservingTimer]; - [self startAutosaveTimer]; - - /* KVO */ - [defaults addObserver:self - forKeyPath:CMPrefMaxHistorySizeKey - options:NSKeyValueObservingOptionNew - context:nil]; - [defaults addObserver:self - forKeyPath:CMPrefAutosaveDelayKey - options:NSKeyValueObservingOptionNew - context:nil]; - [defaults addObserver:self - forKeyPath:CMPrefTimeIntervalKey - options:NSKeyValueObservingOptionNew - context:nil]; - [defaults addObserver:self - forKeyPath:CMPrefStoreTypesKey - options:NSKeyValueObservingOptionNew - context:nil]; - [defaults addObserver:self - forKeyPath:CMPrefExcludeAppsKey - options:NSKeyValueObservingOptionNew - context:nil]; - } - return self; -} - -- (void)dealloc -{ - /* KVO */ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults removeObserver:self forKeyPath:CMPrefMaxHistorySizeKey]; - [defaults removeObserver:self forKeyPath:CMPrefAutosaveDelayKey]; - [defaults removeObserver:self forKeyPath:CMPrefTimeIntervalKey]; - [defaults removeObserver:self forKeyPath:CMPrefStoreTypesKey]; - [defaults removeObserver:self forKeyPath:CMPrefExcludeAppsKey]; - - [clips release], clips = nil; - [storeTypes release], storeTypes = nil; - [excludeIdentifiers release], excludeIdentifiers = nil; - [lastClipsUpdated release], lastClipsUpdated = nil; - [lastSaved release], lastSaved = nil; - - if (pboardObservingTimer) { - [pboardObservingTimer invalidate]; - pboardObservingTimer = nil; - } - - if (autosaveTimer) { - [autosaveTimer invalidate]; - autosaveTimer = nil; - } - - [super dealloc]; -} - -#pragma mark - -#pragma mark Accessors - -#pragma mark - ReadOnly- - -- (NSArray *)sortedClips -{ - BOOL reorder = [[NSUserDefaults standardUserDefaults] boolForKey:CMPrefReorderClipsAfterPasting]; - NSString *key = (reorder) ? @"lastUsedDate" : @"createdDate"; - - NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:NO]; - NSArray *descriptors = [[NSArray alloc] initWithObjects:descriptor, nil]; - [descriptor release], descriptor = nil; - - NSArray *results; - - if ([clips respondsToSelector:@selector( sortedArrayUsingDescriptors: )]) { - /* Mac OS X 10.6 and lator */ - results = [self.clips sortedArrayUsingDescriptors:descriptors]; - } - else { - results = [[self.clips allObjects] sortedArrayUsingDescriptors:descriptors]; - } - - [descriptors release], descriptors = nil; - - return results; -} - -#pragma mark - Write - - -- (void)setClips:(NSMutableSet *)newClips -{ - if (clips != newClips) { - [clips release]; - clips = [newClips mutableCopy]; - } -} - -#pragma mark - -#pragma mark KVO - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ -// NSLog(@"observeValueForKeyPath: %@", keyPath); - - if ([keyPath isEqualToString:CMPrefMaxHistorySizeKey]) { - [self _trimHistorySize]; - } - else if ([keyPath isEqualToString:CMPrefAutosaveDelayKey]) { - [self startAutosaveTimer]; - } - else if ([keyPath isEqualToString:CMPrefTimeIntervalKey]) { - [self _startPasteboardObservingTimer]; - } - else if ([keyPath isEqualToString:CMPrefStoreTypesKey]) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [self setValue:[defaults objectForKey:CMPrefStoreTypesKey] forKey:@"storeTypes"]; - } - else if ([keyPath isEqualToString:CMPrefExcludeAppsKey]) { - NSArray *excludeList = [change objectForKey:@"new"]; - - NSSet *set = [self _getExcludeBundleIdentifiersFromList:excludeList]; - - if (set) { - [self setExcludeIdentifiers:set]; - } - else { - [self setExcludeIdentifiers:[NSSet set]]; - } - } -} - -#pragma mark - -#pragma mark Public - -- (void)startAutosaveTimer -{ - [self stopAutosaveTimer]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSUInteger timeInterval = [defaults integerForKey:CMPrefAutosaveDelayKey]; - - if (timeInterval == 0) { - return; - } - else if (timeInterval < MIN_AUTOSAVE_INTERVAL) { - timeInterval = MIN_AUTOSAVE_INTERVAL; - } - - autosaveTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval - target:self - selector:@selector( _autosave ) - userInfo:nil - repeats:YES]; -} - -- (void)stopAutosaveTimer -{ - if (autosaveTimer) { - [autosaveTimer invalidate]; - autosaveTimer = nil; - } -} - -- (BOOL)saveClips -{ - BOOL result = NO; - - NSString *path = [CMUtilities applicationSupportFolder]; - if ([CMUtilities prepareSaveToPath:path]) { - result = [NSKeyedArchiver archiveRootObject:self.sortedClips toFile:[self _saveFilePath]]; - } - - return result; -} - -- (void)loadClips -{ - NSMutableArray *loadedData = [NSKeyedUnarchiver unarchiveObjectWithFile:[self _saveFilePath]]; - if (loadedData == nil) { - return; - } - - [self setClips:[NSMutableSet setWithArray:loadedData]]; - [self _trimHistorySize]; -} - -- (void)removeClips -{ - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *path = [self _saveFilePath]; - if ([fileManager fileExistsAtPath:path]) { - NSError *error = nil; - [fileManager removeItemAtPath:path error:&error]; - } -} - -- (BOOL)exportHistoryStringsAsSingleFile:(NSString *)path -{ - if ([self.clips count] == 0) { - return YES; - } - - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - BOOL success; - - if ([fileManager fileExistsAtPath:path]) { - success = [fileManager removeItemAtPath:path error:&error]; - if (!success) { - NSLog(@"Error removing file at %@\n%@", path, [error localizedDescription]); - return NO; - } - } - - NSString *separator; - NSUInteger tag = [[NSUserDefaults standardUserDefaults] - integerForKey:CMPrefTagOfSeparatorForExportHistoryToFileKey]; - switch (tag) { - case 1: - separator = kNewLine; - break; - case 2: - separator = kCarriageReturnAndNewLine; - break; - case 3: - separator = kCarriageReturn; - break; - case 4: - separator = kTab; - break; - case 5: - separator = kSingleSpace; - break; - case 0: - default: - separator = kEmptyString; - break; - } - - NSEnumerator *enumerator = [self.sortedClips objectEnumerator]; - Clip *clip; - NSString *stringWithSeparator; - NSFileHandle *outFile; - NSData *data; - const char *utf8String; - - while ((clip = [enumerator nextObject])) { - // NSLog(@"item: %@", clip); - - if (![clip.types containsObject:NSStringPboardType]) { - continue; - } - - stringWithSeparator = [NSString stringWithFormat:@"%@%@", clip.stringValue, separator]; - - if ([fileManager fileExistsAtPath:path]) { - outFile = [NSFileHandle fileHandleForWritingAtPath:path]; - [outFile seekToEndOfFile]; - - utf8String = [stringWithSeparator UTF8String]; - data = [[NSData alloc] initWithBytes:utf8String length:strlen(utf8String)]; - [outFile writeData:data]; - [data release], data = nil; - - [outFile closeFile]; - } - else { - error = nil; - success = [stringWithSeparator writeToFile:path - atomically:YES - encoding:NSUTF8StringEncoding - error:&error]; - if (!success) { - NSLog(@"Error writing file at %@\n%@", path, [error localizedDescription]); - return NO; - } - } -} - -// NSLog(@"Finished export history"); - return YES; -} - -- (BOOL)exportHistoryStringsAsMultipleFiles:(NSString *)path -{ - if ([self.clips count] == 0) { - return YES; - } - - NSURL *destURL = [NSURL fileURLWithPath:path]; - BOOL isSnowLeopardAndLator = [destURL respondsToSelector:@selector( URLByAppendingPathComponent: )]; - - NSURL *outputFileURL; - NSString *filename; - NSString *extension = @"txt"; - NSError *error = nil; - BOOL success; - NSUInteger i = 0; - - for (Clip *clip in self.sortedClips) { - i++; - - if (![clip.types containsObject:NSStringPboardType]) { - continue; - } - - filename = [NSString stringWithFormat:@"%u.%@", i, extension]; // 32-bit unsighed integer -// NSLog(@"filename: %@", filename); - - if (isSnowLeopardAndLator) { - /* Mac OS X 10.6 and lator */ - outputFileURL = [destURL URLByAppendingPathComponent:filename]; - } - else { - /* Mac OS X 10.5 and earlier */ - outputFileURL = [NSURL fileURLWithPath:[NSString stringWithFormat: - @"%@/%@", path, filename]]; - } - - success = [clip.stringValue writeToURL:outputFileURL - atomically:YES - encoding:NSUTF8StringEncoding - error:&error]; - if (!success) { - NSLog(@"Error writing file at %@\n%@", outputFileURL, [error localizedDescription]); - return NO; - } - } - - return YES; -} - -- (void)clearAll -{ - [self willChangeValueForKey:@"clips"]; - [self.clips removeAllObjects]; - [self didChangeValueForKey:@"clips"]; -} - -- (Clip *)clipAtIndex:(NSUInteger)index -{ - return [self.sortedClips objectAtIndex:index]; -} - -- (BOOL)removeClipAtIndex:(NSUInteger)index -{ - Clip *clip = [self.sortedClips objectAtIndex:index]; - -// @try { -// [self willChangeValueForKey:@"clips"]; -// [self.clips removeObject:clip]; -// [self didChangeValueForKey:@"clips"]; -// } -// @catch (NSException *ex) { -// return NO; -// } -// -// return YES; - - return [self removeClip:clip]; -} - -- (BOOL)removeClip:(Clip *)clip -{ - @try { - [self willChangeValueForKey:@"clips"]; - [self.clips removeObject:clip]; - [self didChangeValueForKey:@"clips"]; - } - @catch (NSException *ex) { - return NO; - } - - return YES; -} - -- (void)copyStringToPasteboard:(NSString *)aString -{ - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self]; - [pboard setString:aString forType:NSStringPboardType]; -} - -- (void)copyClipToPasteboard:(Clip *)clip -{ - NSArray *types = [clip types]; - - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - [pboard declareTypes:types owner:self]; - - for (NSString *pbType in types) { - /* stringValue */ - if ([pbType isEqualToString:NSStringPboardType]) { - NSString *pbString = ([clip stringValue]) ? [clip stringValue] : kEmptyString; - [pboard setString:pbString forType:NSStringPboardType]; - } - /* RTFD */ - else if ([pbType isEqualToString:NSRTFDPboardType]) { -// NSData *rtfData = [clip RTFD]; - NSData *rtfData = [clip RTFData]; - [pboard setData:rtfData forType:NSRTFDPboardType]; - } - /* RTF */ - else if ([pbType isEqualToString:NSRTFPboardType]) { -// NSData *rtfData = [clip RTF]; - NSData *rtfData = [clip RTFData]; - [pboard setData:rtfData forType:NSRTFPboardType]; - } - /* PDF */ - else if ([pbType isEqualToString:NSPDFPboardType]) { - NSData *pdfData = [clip PDF]; - NSPDFImageRep *pdfRep = [NSPDFImageRep imageRepWithData:pdfData]; - [pboard setData:[pdfRep PDFRepresentation] forType:NSPDFPboardType]; - } - /* filenames */ - else if ([pbType isEqualToString:NSFilenamesPboardType]) { - NSArray *filenames = [clip filenames]; - [pboard setPropertyList:filenames forType:NSFilenamesPboardType]; - } - /* URL */ - else if ([pbType isEqualToString:NSURLPboardType]) { - NSArray *url = [clip URL]; - [pboard setPropertyList:url forType:NSURLPboardType]; - } - /* image */ - else if ([pbType isEqualToString:NSTIFFPboardType] || - [pbType isEqualToString:NSPICTPboardType]) { - NSImage *image = [clip image]; - if (image) { - [pboard setData:[image TIFFRepresentation] forType:NSTIFFPboardType]; - } - } - } -} - -- (void)copyClipToPasteboardAtIndex:(NSUInteger)index -{ - Clip *clip = [self.sortedClips objectAtIndex:index]; - [self copyClipToPasteboard:clip]; -} - -//- (void)startUpdate -//{ -// [self setIsHalted:NO]; -//} -// -//- (void)restartUpdate -//{ -// [self copyClipToPasteboardAtIndex:0]; -// [self startUpdate]; -//} -// -//- (void)haltUpdate -//{ -// [self setIsHalted:YES]; -//} - -#pragma mark - -#pragma mark Private - -- (void)_updateClips:(id)sender -{ -// /* Check recording mode */ -// if (isHalted) { -// return; -// } - - /* Check changeCount */ - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - -// NSLog(@"changeCount: %d", [pboard changeCount]); - - if ([pboard changeCount] == cachedChangeCount) { - return; - } - - self.cachedChangeCount = [pboard changeCount]; - - /* Exclude apps */ - if ([self _frontProcessIsInExcludeList]) { - return; - } - - /* Make new clip */ - Clip *clip = [self _makeClipFromPasteboard:pboard]; - if (clip == nil) { - return; - } - - /* Make proxy */ - NSMutableSet *clipsProxy = [self mutableSetValueForKey:@"clips"]; - - /* Check dupulication and re-order */ - if (0 < [clipsProxy count]) { - if ([clipsProxy containsObject:clip]) { -// NSLog(@"The new clip is already a member: %u", [clip hash]); - - NSNumber *hashNumber = [NSNumber numberWithUnsignedInteger:[clip hash]]; - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hash == %@", hashNumber]; -// NSLog(@"filterd: %@", [clipsProxy filteredSetUsingPredicate:predicate]); - - Clip *existedClip = [[clipsProxy filteredSetUsingPredicate:predicate] anyObject]; - if (existedClip) { - [self willChangeValueForKey:@"clips"]; - [existedClip setLastUsedDate:[NSDate date]]; - [self didChangeValueForKey:@"clips"]; - } - - return; - } - } - - /* Add clip to clips */ - [clipsProxy addObject:clip]; - - /* Check clips size */ - [self _trimHistorySize]; - - /* Updated time */ - NSDate *now = [[NSDate alloc] init]; - [self setLastClipsUpdated:now]; - [now release], now = nil; -} - -- (Clip *)_makeClipFromPasteboard:(NSPasteboard *)pboard -{ -// NSPasteboard *pboard = [NSPasteboard generalPasteboard]; -// -//// NSLog(@"changeCount: %d", [pboard changeCount]); -// -// /* Check changeCount */ -// if ([pboard changeCount] == cachedChangeCount) { -// return nil; -// } -// [self setValue:[NSNumber numberWithInt:[pboard changeCount]] forKey:@"cachedChangeCount"]; - - /* make new clip */ - Clip *clip = [[[Clip alloc] init] autorelease]; - - /* types */ - NSArray *types = [self _makeTypesFromPasteboard:pboard]; -// NSLog(@"types:\r%@", types); - - if ([types count] == 0) { -// NSLog(@"types count is %d. return nil.", [types count]); - return nil; - } - - if (![[storeTypes allValues] containsObject:[NSNumber numberWithBool:YES]]) { -// NSLog(@"storeTypes does not contain YES. return nil."); - return nil; - } - - [clip setValue:types forKey:@"types"]; - - for (NSString *pbType in types) { -// NSLog(@"available types: %d", [self _storeType:pbType]); - - /* stringValue */ - if ([pbType isEqualToString:NSStringPboardType]) { - NSString *pbString = [pboard stringForType:NSStringPboardType]; - [clip setValue:pbString forKey:@"stringValue"]; - } - /*RTFD */ - else if ([pbType isEqualToString:NSRTFDPboardType]) { - NSData *rtfData = [pboard dataForType:NSRTFDPboardType]; -// [clip setValue:rtfData forKey:@"RTFD"]; - [clip setValue:rtfData forKey:@"RTFData"]; - } - /* RTF */ - else if ([pbType isEqualToString:NSRTFPboardType] && (clip.RTFData == nil)) { - NSData *rtfData = [pboard dataForType:NSRTFPboardType]; -// [clip setValue:rtfData forKey:@"RTF"]; - [clip setValue:rtfData forKey:@"RTFData"]; - } - /* PDF */ - else if ([pbType isEqualToString:NSPDFPboardType]) { - NSData *pdfData = [pboard dataForType:NSPDFPboardType]; - [clip setValue:pdfData forKey:@"PDF"]; - } - /* filenames */ - else if ([pbType isEqualToString:NSFilenamesPboardType]) { - // NSLog(@"filenames: %@", [pboard propertyListForType:NSFilenamesPboardType]); - NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; - [clip setValue:filenames forKey:@"filenames"]; - } - /* URL */ - else if ([pbType isEqualToString:NSURLPboardType]) { - NSArray *url = [pboard propertyListForType:NSURLPboardType]; - [clip setValue:url forKey:@"URL"]; - } - /* image */ - else if ([pbType isEqualToString:NSTIFFPboardType] || [pbType isEqualToString:NSPICTPboardType]) { - if ([NSImage canInitWithPasteboard:pboard]) { - NSImage *image = [[NSImage alloc] initWithPasteboard:pboard]; - [clip setValue:image forKey:@"image"]; - [image release], image = nil; - } - } - } - - return clip; -} - -- (NSArray *)_makeTypesFromPasteboard:(NSPasteboard *)pboard -{ - NSMutableArray *types = [NSMutableArray array]; - - NSArray *pbTypes = [pboard types]; -// NSLog(@"pbTypes: %@", pbTypes); - - for (NSString *dataType in pbTypes) { - if ([self _storeType:dataType] != YES) { - continue; - } - -// NSLog(@"type: %@, %d", dataType, [self _storeType:dataType]); - - if ([dataType isEqualToString:NSTIFFPboardType] || - [dataType isEqualToString:NSPICTPboardType]) { - if ([types containsObject:NSTIFFPboardType]) { - continue; - } - [types addObject:NSTIFFPboardType]; - } - else { - [types addObject:dataType]; - } - } - -// NSLog(@"types: %@", types); - - return types; -} - -- (BOOL)_storeType:(NSString *)type -{ - NSDictionary *typeDict = [Clip availableTypeDictionary]; - return [[storeTypes objectForKey:[typeDict objectForKey:type]] boolValue]; -} - -- (BOOL)_frontProcessIsInExcludeList -{ -// NSLog(@"excludeIdentifiers: %@", self.excludeIdentifiers); - - BOOL result = NO; - - if ([self.excludeIdentifiers count] == 0) { - return result; - } - - ProcessSerialNumber psn; - GetFrontProcess(&psn); - NSDictionary *processInfo = (NSDictionary *)ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask); - - NSString *bundleIdentifier = [processInfo objectForKey:(NSString *)kCFBundleIdentifierKey]; - if (bundleIdentifier && [self.excludeIdentifiers containsObject:bundleIdentifier]) { -// NSLog(@"processInfo: %@", processInfo); - result = YES; - } - - if (processInfo) { - CFRelease(processInfo); - } - - return result; -} - -- (void)_trimHistorySize -{ - NSMutableSet *clipsProxy = [self mutableSetValueForKey:@"clips"]; - NSUInteger currentSize = [clipsProxy count]; - NSUInteger maxHistorySize = [[NSUserDefaults standardUserDefaults] integerForKey:CMPrefMaxHistorySizeKey]; - - if (maxHistorySize < currentSize) { - NSUInteger delta = currentSize - maxHistorySize; - NSRange range = NSMakeRange(currentSize-delta, delta); - NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:range]; - - NSArray *removeObjects = [self.sortedClips objectsAtIndexes:indexSet]; - [indexSet release], indexSet = nil; - - for (Clip *removeObject in removeObjects) { - [clipsProxy removeObject:removeObject]; - } - } -} - -- (void)_startPasteboardObservingTimer -{ - if (pboardObservingTimer) { - [pboardObservingTimer invalidate]; - } - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - CGFloat timeInterval = [defaults floatForKey:CMPrefTimeIntervalKey]; - if (timeInterval > MAX_TIME_INTERVAL) { - timeInterval = MAX_TIME_INTERVAL; - [defaults setFloat:timeInterval forKey:CMPrefTimeIntervalKey]; - } - - pboardObservingTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval - target:self - selector:@selector( _updateClips: ) - userInfo:nil - repeats:YES]; -} - -#pragma mark - Autosave - - -- (void)_autosave -{ -// NSLog(@"_autosave | updated: %@ | saved: %@", self.lastClipsUpdated, self.lastSaved); - - if ([self.lastSaved compare:self.lastClipsUpdated] == NSOrderedDescending) { - return; - } - - [NSThread detachNewThreadSelector:@selector( _fireSaveClips ) - toTarget:self - withObject:nil]; -} - -- (void)_fireSaveClips -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - -// NSLog(@"_autosave"); - - BOOL result = [self saveClips]; - - if (result == YES) { - NSDate *now = [[NSDate alloc] init]; - [self setLastSaved:now]; - [now release], now = nil; - } - else { - [self stopAutosaveTimer]; - - [NSApp activateIgnoringOtherApps:YES]; - NSRunAlertPanel(NSLocalizedString(@"Error", nil), - NSLocalizedString(@"Could not save your clipboard history to file.", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - - [self startAutosaveTimer]; - } - - [pool release], pool = nil; -} - -#pragma mark - Archiver - - -- (NSString *)_saveFilePath -{ - return [[CMUtilities applicationSupportFolder] stringByAppendingPathComponent:kClipsSaveDataName]; -} - -@end diff --git a/Source/CocoaExtensions/BaseNode.h b/Source/CocoaExtensions/BaseNode.h deleted file mode 100755 index de29737..0000000 --- a/Source/CocoaExtensions/BaseNode.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// File: BaseNode.h -// -// Abstract: Generic multi-use node object used with NSOutlineView and NSTreeController. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import - -@interface BaseNode : NSObject -{ - NSString *nodeTitle; - NSMutableArray *children; - BOOL isLeaf; - NSImage *nodeIcon; - NSString *urlString; -} - -- (id)initLeaf; - -- (void)setNodeTitle:(NSString*)newNodeTitle; -- (NSString*)nodeTitle; - -- (void)setChildren:(NSArray*)newChildren; -- (NSMutableArray*)children; - -- (void)setLeaf:(BOOL)flag; -- (BOOL)isLeaf; - -- (void)setNodeIcon:(NSImage*)icon; -- (NSImage*)nodeIcon; - -- (void)setURL:(NSString*)name; -- (NSString*)urlString; - -- (BOOL)isDraggable; - -- (NSComparisonResult)compare:(BaseNode*)aNode; - -- (NSArray*)mutableKeys; - -- (NSDictionary*)dictionaryRepresentation; -- (id)initWithDictionary:(NSDictionary*)dictionary; - -- (id)parentFromArray:(NSArray*)array; -- (void)removeObjectFromChildren:(id)obj; -- (NSArray*)descendants; -- (NSArray*)allChildLeafs; -- (NSArray*)groupChildren; -- (BOOL)isDescendantOfOrOneOfNodes:(NSArray*)nodes; -- (BOOL)isDescendantOfNodes:(NSArray*)nodes; -- (NSIndexPath*)indexPathInArray:(NSArray*)array; - -@end diff --git a/Source/CocoaExtensions/BaseNode.m b/Source/CocoaExtensions/BaseNode.m deleted file mode 100755 index dc41315..0000000 --- a/Source/CocoaExtensions/BaseNode.m +++ /dev/null @@ -1,565 +0,0 @@ -// -// File: BaseNode.m -// -// Abstract: Generic multi-use node object used with NSOutlineView and NSTreeController. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import "BaseNode.h" -#import "NSArray_Extensions.h" - -@implementation BaseNode - -// ------------------------------------------------------------------------------- -// init: -// ------------------------------------------------------------------------------- -- (id)init -{ - if (self = [super init]) - { - [self setNodeTitle:@"Untitled"]; - [self setChildren:[NSArray array]]; - [self setLeaf:NO]; // container by default - } - return self; -} - -// ------------------------------------------------------------------------------- -// initLeaf: -// ------------------------------------------------------------------------------- -- (id)initLeaf -{ - if (self = [self init]) - { - [self setLeaf:YES]; - } - return self; -} - -// ------------------------------------------------------------------------------- -// dealloc: -// ------------------------------------------------------------------------------- -- (void)dealloc -{ - [nodeTitle release]; - [children release]; - [nodeIcon release]; - [urlString release]; - - [super dealloc]; -} - -// ------------------------------------------------------------------------------- -// setNodeTitle:newNodeTitle -// ------------------------------------------------------------------------------- -- (void)setNodeTitle:(NSString*)newNodeTitle -{ - [newNodeTitle retain]; - [nodeTitle release]; - nodeTitle = newNodeTitle; -} - -// ------------------------------------------------------------------------------- -// nodeTitle: -// ------------------------------------------------------------------------------- -- (NSString*)nodeTitle -{ - return nodeTitle; -} - -// ------------------------------------------------------------------------------- -// setNodeIcon:icon -// ------------------------------------------------------------------------------- -- (void)setNodeIcon:(NSImage*)icon -{ - if (!nodeIcon || ![nodeIcon isEqual:icon]) - { - [nodeIcon release]; - nodeIcon = [icon retain]; - } -} - -// ------------------------------------------------------------------------------- -// nodeIcon: -// ------------------------------------------------------------------------------- -- (NSImage*)nodeIcon -{ - return nodeIcon; -} - -// ------------------------------------------------------------------------------- -// setChildren:newChildren -// ------------------------------------------------------------------------------- -- (void)setChildren:(NSArray*)newChildren -{ - if (children != newChildren) - { - [children autorelease]; - children = [[NSMutableArray alloc] initWithArray:newChildren]; - } -} - -// ------------------------------------------------------------------------------- -// children: -// ------------------------------------------------------------------------------- -- (NSMutableArray*)children -{ - return children; -} - -// ------------------------------------------------------------------------------- -// setLeaf:flag -// ------------------------------------------------------------------------------- -- (void)setLeaf:(BOOL)flag -{ - isLeaf = flag; - if (isLeaf) - [self setChildren:[NSArray arrayWithObject:self]]; - else - [self setChildren:[NSArray array]]; -} - -// ------------------------------------------------------------------------------- -// isLeaf: -// ------------------------------------------------------------------------------- -- (BOOL)isLeaf -{ - return isLeaf; -} - -// ------------------------------------------------------------------------------- -// setURL:urlStr -// ------------------------------------------------------------------------------- -- (void)setURL:(NSString*)urlStr -{ - if (!urlString || ![urlString isEqualToString:urlStr]) - { - [urlString release]; - urlString = [urlStr retain]; - } -} - -// ------------------------------------------------------------------------------- -// urlString: -// ------------------------------------------------------------------------------- -- (NSString*)urlString -{ - return urlString; -} - -// ------------------------------------------------------------------------------- -// compare:aNode -// ------------------------------------------------------------------------------- -- (NSComparisonResult)compare:(BaseNode*)aNode -{ - return [[[self nodeTitle] lowercaseString] compare:[[aNode nodeTitle] lowercaseString]]; -} - - -#pragma mark - Drag and Drop - -// ------------------------------------------------------------------------------- -// isDraggable: -// ------------------------------------------------------------------------------- -- (BOOL)isDraggable -{ - BOOL result = YES; - if ([[self urlString] isAbsolutePath] || [self nodeIcon] == nil) - result = NO; // don't allow file system objects to be dragged or special group nodes - return result; -} - -// ------------------------------------------------------------------------------- -// removeObjectFromChildren:obj -// -// Finds the receiver's parent from the nodes contained in the array. -// ------------------------------------------------------------------------------- -- (id)parentFromArray:(NSArray*)array -{ - id result = nil; - - for (id node in array) - { - if (node == self) // If we are in the root array, return nil - break; - - if ([[node children] containsObjectIdenticalTo:self]) - { - result = node; - break; - } - - if (![node isLeaf]) - { - id innerNode = [self parentFromArray:[node children]]; - if (innerNode) - { - result = innerNode; - break; - } - } - } - - return result; -} - -// ------------------------------------------------------------------------------- -// removeObjectFromChildren:obj -// -// Recursive method which searches children and children of all sub-nodes -// to remove the given object. -// ------------------------------------------------------------------------------- -- (void)removeObjectFromChildren:(id)obj -{ - // Remove object from children or the children of any sub-nodes - NSEnumerator *enumerator = [children objectEnumerator]; - id node = nil; - - while (node = [enumerator nextObject]) - { - if (node == obj) - { - [children removeObjectIdenticalTo:obj]; - return; - } - - if (![node isLeaf]) - [node removeObjectFromChildren:obj]; - } -} - -// ------------------------------------------------------------------------------- -// descendants: -// -// Generates an array of all descendants. -// ------------------------------------------------------------------------------- -- (NSArray*)descendants -{ - NSMutableArray *descendants = [NSMutableArray array]; - NSEnumerator *enumerator = [children objectEnumerator]; - id node = nil; - - while (node = [enumerator nextObject]) - { - [descendants addObject:node]; - - if (![node isLeaf]) - [descendants addObjectsFromArray:[node descendants]]; // Recursive - will go down the chain to get all - } - return descendants; -} - -// ------------------------------------------------------------------------------- -// allChildLeafs: -// -// Generates an array of all leafs in children and children of all sub-nodes. -// Useful for generating a list of leaf-only nodes. -// ------------------------------------------------------------------------------- -- (NSArray*)allChildLeafs -{ - NSMutableArray *childLeafs = [NSMutableArray array]; - NSEnumerator *enumerator = [children objectEnumerator]; - id node = nil; - - while (node = [enumerator nextObject]) - { - if ([node isLeaf]) - [childLeafs addObject:node]; - else - [childLeafs addObjectsFromArray:[node allChildLeafs]]; // Recursive - will go down the chain to get all - } - return childLeafs; -} - -// ------------------------------------------------------------------------------- -// groupChildren: -// -// Returns only the children that are group nodes. -// ------------------------------------------------------------------------------- -- (NSArray*)groupChildren -{ - NSMutableArray *groupChildren = [NSMutableArray array]; - NSEnumerator *childEnumerator = [children objectEnumerator]; - BaseNode *child; - - while (child = [childEnumerator nextObject]) - { - if (![child isLeaf]) - [groupChildren addObject:child]; - } - return groupChildren; -} - -// ------------------------------------------------------------------------------- -// isDescendantOfOrOneOfNodes:nodes -// -// Returns YES if self is contained anywhere inside the children or children of -// sub-nodes of the nodes contained inside the given array. -// ------------------------------------------------------------------------------- -- (BOOL)isDescendantOfOrOneOfNodes:(NSArray*)nodes -{ - // returns YES if we are contained anywhere inside the array passed in, including inside sub-nodes - NSEnumerator *enumerator = [nodes objectEnumerator]; - id node = nil; - - while (node = [enumerator nextObject]) - { - if (node == self) - return YES; // we found ourselv - - // check all the sub-nodes - if (![node isLeaf]) - { - if ([self isDescendantOfOrOneOfNodes:[node children]]) - return YES; - } - } - - return NO; -} - -// ------------------------------------------------------------------------------- -// isDescendantOfNodes:nodes -// -// Returns YES if any node in the array passed in is an ancestor of ours. -// ------------------------------------------------------------------------------- -- (BOOL)isDescendantOfNodes:(NSArray*)nodes -{ - NSEnumerator *enumerator = [nodes objectEnumerator]; - id node = nil; - - while (node = [enumerator nextObject]) - { - // check all the sub-nodes - if (![node isLeaf]) - { - if ([self isDescendantOfOrOneOfNodes:[node children]]) - return YES; - } - } - - return NO; -} - -// ------------------------------------------------------------------------------- -// indexPathInArray:array -// -// Returns the index path of within the given array, -// useful for drag and drop. -// ------------------------------------------------------------------------------- -- (NSIndexPath*)indexPathInArray:(NSArray*)array -{ - NSIndexPath *indexPath = nil; - NSMutableArray *reverseIndexes = [NSMutableArray array]; - id parent, doc = self; - NSInteger index; - - while (parent = [doc parentFromArray:array]) - { - index = [[parent children] indexOfObjectIdenticalTo:doc]; - if (index == NSNotFound) - return nil; - - [reverseIndexes addObject:[NSNumber numberWithInt:index]]; - doc = parent; - } - - // If parent is nil, we should just be in the parent array - index = [array indexOfObjectIdenticalTo:doc]; - if (index == NSNotFound) - return nil; - [reverseIndexes addObject:[NSNumber numberWithInt:index]]; - - // Now build the index path - for (NSNumber *indexNumber in [reverseIndexes reverseObjectEnumerator]) { - if (indexPath == nil) { - indexPath = [NSIndexPath indexPathWithIndex:[indexNumber intValue]]; - } - else { - indexPath = [indexPath indexPathByAddingIndex:[indexNumber intValue]]; - } - } - - return indexPath; -} - - -#pragma mark - Archiving And Copying Support - -// ------------------------------------------------------------------------------- -// mutableKeys: -// -// Override this method to maintain support for archiving and copying. -// ------------------------------------------------------------------------------- -- (NSArray*)mutableKeys -{ - return [NSArray arrayWithObjects: - @"nodeTitle", - @"isLeaf", // isLeaf MUST come before children for initWithDictionary: to work - @"children", - @"nodeIcon", - @"urlString", - nil]; -} - -// ------------------------------------------------------------------------------- -// initWithDictionary:dictionary -// ------------------------------------------------------------------------------- -- (id)initWithDictionary:(NSDictionary*)dictionary -{ - self = [self init]; - NSEnumerator *keysToDecode = [[self mutableKeys] objectEnumerator]; - NSString *key; - while (key = [keysToDecode nextObject]) - { - if ([key isEqualToString:@"children"]) - { - if ([[dictionary objectForKey:@"isLeaf"] boolValue]) - [self setChildren:[NSArray arrayWithObject:self]]; - else - { - NSArray *dictChildren = [dictionary objectForKey:key]; - NSMutableArray *newChildren = [NSMutableArray array]; - - for (id node in dictChildren) - { - id newNode = [[[self class] alloc] initWithDictionary:node]; - [newChildren addObject:newNode]; - [newNode release]; - } - [self setChildren:newChildren]; - } - } - else - [self setValue:[dictionary objectForKey:key] forKey:key]; - } - return self; -} - -// ------------------------------------------------------------------------------- -// dictionaryRepresentation: -// ------------------------------------------------------------------------------- -- (NSDictionary*)dictionaryRepresentation -{ - NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - NSEnumerator *keysToCode = [[self mutableKeys] objectEnumerator]; - NSString *key; - - while (key = [keysToCode nextObject]) - { - // convert all children to dictionaries - if ([key isEqualToString:@"children"]) - { - if (!isLeaf) - { - NSMutableArray *dictChildren = [NSMutableArray array]; - for (id node in children) - { - [dictChildren addObject:[node dictionaryRepresentation]]; - } - - [dictionary setObject:dictChildren forKey:key]; - } - } - else if ([self valueForKey:key]) - { - [dictionary setObject:[self valueForKey:key] forKey:key]; - } - } - return dictionary; -} - -// ------------------------------------------------------------------------------- -// initWithCoder:coder -// ------------------------------------------------------------------------------- -- (id)initWithCoder:(NSCoder*)coder -{ - self = [self init]; - NSEnumerator *keysToDecode = [[self mutableKeys] objectEnumerator]; - NSString *key; - while (key = [keysToDecode nextObject]) - [self setValue:[coder decodeObjectForKey:key] forKey:key]; - - return self; -} - -// ------------------------------------------------------------------------------- -// encodeWithCoder:coder -// ------------------------------------------------------------------------------- -- (void)encodeWithCoder:(NSCoder*)coder -{ - NSEnumerator *keysToCode = [[self mutableKeys] objectEnumerator]; - NSString *key; - while (key = [keysToCode nextObject]) - [coder encodeObject:[self valueForKey:key] forKey:key]; -} - -// ------------------------------------------------------------------------------- -// copyWithZone:zone -// ------------------------------------------------------------------------------- -- (id)copyWithZone:(NSZone*)zone -{ - id newNode = [[[self class] allocWithZone:zone] init]; - - NSEnumerator *keysToSet = [[self mutableKeys] objectEnumerator]; - NSString *key; - while (key = [keysToSet nextObject]) - [newNode setValue:[self valueForKey:key] forKey:key]; - - return newNode; -} - -// ------------------------------------------------------------------------------- -// setNilValueForKey:key -// -// Override this for any non-object values -// ------------------------------------------------------------------------------- -- (void)setNilValueForKey:(NSString*)key -{ - if ([key isEqualToString:@"isLeaf"]) - isLeaf = NO; - else - [super setNilValueForKey:key]; -} - -@end diff --git a/Source/CocoaExtensions/ImageAndTextCell.h b/Source/CocoaExtensions/ImageAndTextCell.h deleted file mode 100644 index e51859c..0000000 --- a/Source/CocoaExtensions/ImageAndTextCell.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// File: ImageAndTextCell.h -// -// Abstract: Subclass of NSTextFieldCell which can display text and an image simultaneously. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import - -@interface ImageAndTextCell : NSTextFieldCell -{ -@private - NSImage *image; -} - -- (void)setImage:(NSImage *)anImage; -- (NSImage*)image; - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView; -- (NSSize)cellSize; - -@end diff --git a/Source/CocoaExtensions/ImageAndTextCell.m b/Source/CocoaExtensions/ImageAndTextCell.m deleted file mode 100644 index 8185bba..0000000 --- a/Source/CocoaExtensions/ImageAndTextCell.m +++ /dev/null @@ -1,259 +0,0 @@ -// -// File: ImageAndTextCell.m -// -// Abstract: Subclass of NSTextFieldCell which can display text and an image simultaneously. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import "ImageAndTextCell.h" -//#import "BaseNode.h" - -@implementation ImageAndTextCell - -#define kIconImageSize 16.0 - -//#define kImageOriginXOffset 3 -//#define kImageOriginYOffset 1 -// -//#define kTextOriginXOffset 2 -//#define kTextOriginYOffset 2 -//#define kTextHeightAdjust 4 - - -#define kImageOriginXOffset 3 -#define kImageOriginYOffset 0 - -#define kTextOriginXOffset 3 -#define kTextOriginYOffset 0 -#define kTextHeightAdjust 0 - -// ------------------------------------------------------------------------------- -// init: -// ------------------------------------------------------------------------------- -- (id)init -{ - self = [super init]; - - // we want a smaller font - [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - - return self; -} - -// ------------------------------------------------------------------------------- -// dealloc: -// ------------------------------------------------------------------------------- -- (void)dealloc -{ - [image release]; - image = nil; - [super dealloc]; -} - -// ------------------------------------------------------------------------------- -// copyWithZone:zone -// ------------------------------------------------------------------------------- -- (id)copyWithZone:(NSZone*)zone -{ - ImageAndTextCell *cell = (ImageAndTextCell*)[super copyWithZone:zone]; - cell->image = [image retain]; - return cell; -} - -// ------------------------------------------------------------------------------- -// setImage:anImage -// ------------------------------------------------------------------------------- -- (void)setImage:(NSImage*)anImage -{ - if (anImage != image) - { - [image release]; - image = [anImage retain]; - [image setSize:NSMakeSize(kIconImageSize, kIconImageSize)]; - } -} - -// ------------------------------------------------------------------------------- -// image: -// ------------------------------------------------------------------------------- -- (NSImage*)image -{ - return image; -} - -// ------------------------------------------------------------------------------- -// isGroupCell: -// ------------------------------------------------------------------------------- -- (BOOL)isGroupCell -{ - return ([self image] == nil && [[self title] length] > 0); -} - -// ------------------------------------------------------------------------------- -// titleRectForBounds:cellRect -// -// Returns the proper bound for the cell's title while being edited -// ------------------------------------------------------------------------------- -- (NSRect)titleRectForBounds:(NSRect)cellRect -{ - // the cell has an image: draw the normal item cell - NSSize imageSize; - NSRect imageFrame; - - imageSize = [image size]; - NSDivideRect(cellRect, &imageFrame, &cellRect, 3 + imageSize.width, NSMinXEdge); - - imageFrame.origin.x += kImageOriginXOffset; - imageFrame.origin.y -= kImageOriginYOffset; - imageFrame.size = imageSize; - - imageFrame.origin.y += ceil((cellRect.size.height - imageFrame.size.height) / 2); - - NSRect newFrame = cellRect; - newFrame.origin.x += kTextOriginXOffset; - newFrame.origin.y += kTextOriginYOffset; - newFrame.size.height -= kTextHeightAdjust; - - return newFrame; -} - -// ------------------------------------------------------------------------------- -// editWithFrame:inView:editor:delegate:event -// ------------------------------------------------------------------------------- -- (void)editWithFrame:(NSRect)aRect inView:(NSView*)controlView editor:(NSText*)textObj delegate:(id)anObject event:(NSEvent*)theEvent -{ - NSRect textFrame = [self titleRectForBounds:aRect]; - [super editWithFrame:textFrame inView:controlView editor:textObj delegate:anObject event:theEvent]; -} - -// ------------------------------------------------------------------------------- -// selectWithFrame:inView:editor:delegate:event:start:length -// ------------------------------------------------------------------------------- -- (void)selectWithFrame:(NSRect)aRect inView:(NSView*)controlView editor:(NSText*)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength -{ - NSRect textFrame = [self titleRectForBounds:aRect]; - [super selectWithFrame:textFrame inView:controlView editor:textObj delegate:anObject start:selStart length:selLength]; -} - -// ------------------------------------------------------------------------------- -// drawWithFrame:cellFrame:controlView: -// ------------------------------------------------------------------------------- -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView -{ - if (image != nil) - { - // the cell has an image: draw the normal item cell - NSSize imageSize; - NSRect imageFrame; - - imageSize = [image size]; - NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge); - - imageFrame.origin.x += kImageOriginXOffset; - imageFrame.origin.y -= kImageOriginYOffset; - imageFrame.size = imageSize; - - if ([controlView isFlipped]) - imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2); - else - imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); - [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver]; - - NSRect newFrame = cellFrame; - newFrame.origin.x += kTextOriginXOffset; - newFrame.origin.y += kTextOriginYOffset; - newFrame.size.height -= kTextHeightAdjust; - [super drawWithFrame:newFrame inView:controlView]; - } - else - { - if ([self isGroupCell]) - { - // Center the text in the cellFrame, and call super to do thew ork of actually drawing. - CGFloat yOffset = floor((NSHeight(cellFrame) - [[self attributedStringValue] size].height) / 2.0); - cellFrame.origin.y += yOffset; - cellFrame.size.height -= (kTextOriginYOffset*yOffset); - [super drawWithFrame:cellFrame inView:controlView]; - } - } -} - -// ------------------------------------------------------------------------------- -// cellSize: -// ------------------------------------------------------------------------------- -- (NSSize)cellSize -{ - NSSize cellSize = [super cellSize]; - cellSize.width += (image ? [image size].width : 0) + 3; - return cellSize; -} - -// ------------------------------------------------------------------------------- -// hitTestForEvent: -// -// In 10.5, we need you to implement this method for blocking drag and drop of a given cell. -// So NSCell hit testing will determine if a row can be dragged or not. -// -// NSTableView calls this cell method when starting a drag, if the hit cell returns -// NSCellHitTrackableArea, the particular row will be tracked instead of dragged. -// -// ------------------------------------------------------------------------------- -//- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView -//{ -// NSInteger result = NSCellHitContentArea; -// -// NSOutlineView* hostingOutlineView = (NSOutlineView*)[self controlView]; -// if (hostingOutlineView) -// { -// NSInteger selectedRow = [hostingOutlineView selectedRow]; -// BaseNode* node = [[hostingOutlineView itemAtRow:selectedRow] representedObject]; -// -// if (![node isDraggable]) // is the node isDraggable (i.e. non-file system based objects) -// result = NSCellHitTrackableArea; -// } -// -// return result; -//} - -@end - diff --git a/Source/CocoaExtensions/NSArray_Extensions.h b/Source/CocoaExtensions/NSArray_Extensions.h deleted file mode 100755 index 189aa54..0000000 --- a/Source/CocoaExtensions/NSArray_Extensions.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// File: NSArray_Extensions.h -// -// Abstract: Category extension to NSArray. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import - -@interface NSArray (MyArrayExtensions) -- (BOOL)containsObjectIdenticalTo:(id)object; -- (BOOL)containsAnyObjectsIdenticalTo:(NSArray*)objects; -- (NSIndexSet*)indexesOfObjects:(NSArray*)objects; -@end diff --git a/Source/CocoaExtensions/NSArray_Extensions.m b/Source/CocoaExtensions/NSArray_Extensions.m deleted file mode 100755 index 22191fa..0000000 --- a/Source/CocoaExtensions/NSArray_Extensions.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// File: NSArray_Extensions.m -// -// Abstract: Category extension to NSArray. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import "NSArray_Extensions.h" - -@implementation NSArray (MyArrayExtensions) - -// ------------------------------------------------------------------------------- -// containsObjectIdenticalTo:obj: -// ------------------------------------------------------------------------------- -- (BOOL)containsObjectIdenticalTo:(id)obj -{ - return [self indexOfObjectIdenticalTo:obj] != NSNotFound; -} - -// ------------------------------------------------------------------------------- -// containsAnyObjectsIdenticalTo:objects: -// ------------------------------------------------------------------------------- -- (BOOL)containsAnyObjectsIdenticalTo:(NSArray*)objects -{ - NSEnumerator *e = [objects objectEnumerator]; - id obj; - while (obj = [e nextObject]) - { - if ([self containsObjectIdenticalTo:obj]) - return YES; - } - return NO; -} - -// ------------------------------------------------------------------------------- -// indexesOfObjects:objects: -// ------------------------------------------------------------------------------- -- (NSIndexSet*)indexesOfObjects:(NSArray*)objects -{ - NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; - NSEnumerator *enumerator = [objects objectEnumerator]; - id obj = nil; - NSInteger index; - while (obj = [enumerator nextObject]) - { - index = [self indexOfObject:obj]; - if (index != NSNotFound) - [indexSet addIndex:index]; - } - return indexSet; -} - -@end diff --git a/Source/CocoaExtensions/NSColor+String.h b/Source/CocoaExtensions/NSColor+String.h deleted file mode 100644 index 57b80c8..0000000 --- a/Source/CocoaExtensions/NSColor+String.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#import - -// Convert from a color name / string: -// E.g.: -// red, blue, green -// #RRGGBB, #RRGGBBAA -// rgb(r,g,b) rgba(r,g,b,a) - -@interface NSColor(TopDrawString) - -+ (NSArray *)colorNames; -+ (NSColor *)colorWithString:(NSString *)string; - -@end diff --git a/Source/CocoaExtensions/NSColor+String.m b/Source/CocoaExtensions/NSColor+String.m deleted file mode 100644 index 80febe6..0000000 --- a/Source/CocoaExtensions/NSColor+String.m +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#import "NSColor+String.h" - -typedef struct { - unsigned long value; - const char name[24]; // Longest name is 20 chars, pad out to multiple of 8 -} ColorNameRec; - -static ColorNameRec sColorTable[] = { - { 0xf0f8ff, "aliceblue" }, - { 0xfaebd7, "antiquewhite" }, - { 0x00ffff, "aqua" }, - { 0x7fffd4, "aquamarine" }, - { 0xf0ffff, "azure" }, - { 0xf5f5dc, "beige" }, - { 0xffe4c4, "bisque" }, - { 0x000000, "black" }, - { 0xffebcd, "blanchedalmond" }, - { 0x0000ff, "blue" }, - { 0x8a2be2, "blueviolet" }, - { 0xa52a2a, "brown" }, - { 0xdeb887, "burlywood" }, - { 0x5f9ea0, "cadetblue" }, - { 0x7fff00, "chartreuse" }, - { 0xd2691e, "chocolate" }, - { 0xff7f50, "coral" }, - { 0x6495ed, "cornflowerblue" }, - { 0xfff8dc, "cornsilk" }, - { 0xdc143c, "crimson" }, - { 0x00ffff, "cyan" }, - { 0x00008b, "darkblue" }, - { 0x008b8b, "darkcyan" }, - { 0xb8860b, "darkgoldenrod" }, - { 0xa9a9a9, "darkgray" }, - { 0xa9a9a9, "darkgrey" }, - { 0x006400, "darkgreen" }, - { 0xbdb76b, "darkkhaki" }, - { 0x8b008b, "darkmagenta" }, - { 0x556b2f, "darkolivegreen" }, - { 0xff8c00, "darkorange" }, - { 0x9932cc, "darkorchid" }, - { 0x8b0000, "darkred" }, - { 0xe9967a, "darksalmon" }, - { 0x8fbc8f, "darkseagreen" }, - { 0x483d8b, "darkslateblue" }, - { 0x2f4f4f, "darkslategray" }, - { 0x2f4f4f, "darkslategrey" }, - { 0x00ced1, "darkturquoise" }, - { 0x9400d3, "darkviolet" }, - { 0xff1493, "deeppink" }, - { 0x00bfff, "deepskyblue" }, - { 0x696969, "dimgray" }, - { 0x696969, "dimgrey" }, - { 0x1e90ff, "dodgerblue" }, - { 0xb22222, "firebrick" }, - { 0xfffaf0, "floralwhite" }, - { 0x228b22, "forestgreen" }, - { 0xff00ff, "fuchsia" }, - { 0xdcdcdc, "gainsboro" }, - { 0xf8f8ff, "ghostwhite" }, - { 0xffd700, "gold" }, - { 0xdaa520, "goldenrod" }, - { 0x808080, "gray" }, - { 0x808080, "grey" }, - { 0x008000, "green" }, - { 0xadff2f, "greenyellow" }, - { 0xf0fff0, "honeydew" }, - { 0xff69b4, "hotpink" }, - { 0xcd5c5c, "indianred" }, - { 0x4b0082, "indigo" }, - { 0xfffff0, "ivory" }, - { 0xf0e68c, "khaki" }, - { 0xe6e6fa, "lavender" }, - { 0xfff0f5, "lavenderblush" }, - { 0x7cfc00, "lawngreen" }, - { 0xfffacd, "lemonchiffon" }, - { 0xadd8e6, "lightblue" }, - { 0xf08080, "lightcoral" }, - { 0xe0ffff, "lightcyan" }, - { 0xfafad2, "lightgoldenrodyellow" }, - { 0xd3d3d3, "lightgray" }, - { 0xd3d3d3, "lightgrey" }, - { 0x90ee90, "lightgreen" }, - { 0xffb6c1, "lightpink" }, - { 0xffa07a, "lightsalmon" }, - { 0x20b2aa, "lightseagreen" }, - { 0x87cefa, "lightskyblue" }, - { 0x8470ff, "lightslateblue" }, - { 0x778899, "lightslategray" }, - { 0x778899, "lightslategrey" }, - { 0xb0c4de, "lightsteelblue" }, - { 0xffffe0, "lightyellow" }, - { 0x00ff00, "lime" }, - { 0x32cd32, "limegreen" }, - { 0xfaf0e6, "linen" }, - { 0xff00ff, "magenta" }, - { 0x800000, "maroon" }, - { 0x66cdaa, "mediumaquamarine" }, - { 0x0000cd, "mediumblue" }, - { 0xba55d3, "mediumorchid" }, - { 0x9370d8, "mediumpurple" }, - { 0x3cb371, "mediumseagreen" }, - { 0x7b68ee, "mediumslateblue" }, - { 0x00fa9a, "mediumspringgreen" }, - { 0x48d1cc, "mediumturquoise" }, - { 0xc71585, "mediumvioletred" }, - { 0x191970, "midnightblue" }, - { 0xf5fffa, "mintcream" }, - { 0xffe4e1, "mistyrose" }, - { 0xffe4b5, "moccasin" }, - { 0xffdead, "navajowhite" }, - { 0x000080, "navy" }, - { 0xfdf5e6, "oldlace" }, - { 0x808000, "olive" }, - { 0x6b8e23, "olivedrab" }, - { 0xffa500, "orange" }, - { 0xff4500, "orangered" }, - { 0xda70d6, "orchid" }, - { 0xeee8aa, "palegoldenrod" }, - { 0x98fb98, "palegreen" }, - { 0xafeeee, "paleturquoise" }, - { 0xd87093, "palevioletred" }, - { 0xffefd5, "papayawhip" }, - { 0xffdab9, "peachpuff" }, - { 0xcd853f, "peru" }, - { 0xffc0cb, "pink" }, - { 0xdda0dd, "plum" }, - { 0xb0e0e6, "powderblue" }, - { 0x800080, "purple" }, - { 0xff0000, "red" }, - { 0xbc8f8f, "rosybrown" }, - { 0x4169e1, "royalblue" }, - { 0x8b4513, "saddlebrown" }, - { 0xfa8072, "salmon" }, - { 0xf4a460, "sandybrown" }, - { 0x2e8b57, "seagreen" }, - { 0xfff5ee, "seashell" }, - { 0xa0522d, "sienna" }, - { 0xc0c0c0, "silver" }, - { 0x87ceeb, "skyblue" }, - { 0x6a5acd, "slateblue" }, - { 0x708090, "slategray" }, - { 0x708090, "slategrey" }, - { 0xfffafa, "snow" }, - { 0x00ff7f, "springgreen" }, - { 0x4682b4, "steelblue" }, - { 0xd2b48c, "tan" }, - { 0x008080, "teal" }, - { 0xd8bfd8, "thistle" }, - { 0xff6347, "tomato" }, - { 0x40e0d0, "turquoise" }, - { 0xee82ee, "violet" }, - { 0xd02090, "violetred" }, - { 0xf5deb3, "wheat" }, - { 0xffffff, "white" }, - { 0xf5f5f5, "whitesmoke" }, - { 0xffff00, "yellow" }, - { 0x9acd32, "yellowgreen" }, -}; - -@implementation NSColor(TopDrawString) -//------------------------------------------------------------------------------ -+ (NSArray *)colorNames { - static NSArray *sAllNames = nil; - - if (!sAllNames) { - int count = sizeof(sColorTable) / sizeof(sColorTable[0]); - NSMutableArray *names = [[NSMutableArray alloc] init]; - ColorNameRec *rec = sColorTable; - - for (int i = 0; i < count; ++i, ++rec) - [names addObject:[NSString stringWithUTF8String:rec->name]]; - - sAllNames = [[NSArray alloc] initWithArray:names]; - [names release]; - } - - return sAllNames; -} - -//------------------------------------------------------------------------------ -static NSColor *ColorWithUnsignedLong(unsigned long value, BOOL hasAlpha) { - float a = 1.0; - - // Extract alpha, if available - if (hasAlpha) { - a = (float)(0x00FF & value) / 255.0; - value >>= 8; - } - - float r = (float)(value >> 16) / 255.0; - float g = (float)(0x00FF & (value >> 8)) / 255.0; - float b = (float)(0x00FF & value) / 255.0; - - return [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a]; -} - -//------------------------------------------------------------------------------ -static NSColor *ColorWithHexDigits(NSString *str) { - NSScanner *scanner = [NSScanner scannerWithString:[str lowercaseString]]; - NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdef"]; - NSString *hexStr; - - [scanner scanUpToCharactersFromSet:hexSet intoString:nil]; - [scanner scanCharactersFromSet:hexSet intoString:&hexStr]; - - int len = [hexStr length]; - if (len >= 6) { - BOOL hasAlpha = (len == 8) ? YES : NO; - unsigned long value = strtoul([hexStr UTF8String], NULL, 16); - - return ColorWithUnsignedLong(value, hasAlpha); - } - - return nil; -} - -//------------------------------------------------------------------------------ -static NSColor *ColorWithCSSString(NSString *str) { - NSString *trimmed = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - NSString *lowerStr = [trimmed lowercaseString]; - NSScanner *scanner = [NSScanner scannerWithString:lowerStr]; - - if ([scanner scanString:@"rgb" intoString:NULL]) { - [scanner scanString:@"(" intoString:NULL]; - NSString *content; - [scanner scanUpToString:@")" intoString:&content]; - NSCharacterSet *spaceOrCommaSet = [NSCharacterSet characterSetWithCharactersInString:@" ,"]; - NSArray *components = [content componentsSeparatedByCharactersInSet:spaceOrCommaSet]; - int count = [components count]; - float a = 1.0; - - // Alpha in CSS-mode is a 0-1 float - if (count > 3) - a = (float)[[components objectAtIndex:3] floatValue]; - - float r = (float)strtoul([[components objectAtIndex:0] UTF8String], NULL, 10) / 255.0; - float g = (float)strtoul([[components objectAtIndex:1] UTF8String], NULL, 10) / 255.0; - float b = (float)strtoul([[components objectAtIndex:2] UTF8String], NULL, 10) / 255.0; - - return [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a]; - } - - return nil; -} - -//------------------------------------------------------------------------------ -+ (NSColor *)colorWithString:(NSString *)name { - if (![name length]) - return nil; - - NSArray *allNames = [self colorNames]; - NSUInteger count = [allNames count]; - NSUInteger idx = [allNames indexOfObject:[name lowercaseString]]; - - if (idx >= count) { - // If the string contains some hex digits, try to convert - // #RRGGBB or #RRGGBBAA - // rgb(r,g,b) or rgba(r,g,b,a) - NSColor *color = ColorWithHexDigits(name); - - if (!color) - color = ColorWithCSSString(name); - - return color; - } - - return ColorWithUnsignedLong(sColorTable[idx].value, NO); -} - -@end diff --git a/Source/CocoaExtensions/NSIndexPath_Extensions.h b/Source/CocoaExtensions/NSIndexPath_Extensions.h deleted file mode 100644 index 43b6862..0000000 --- a/Source/CocoaExtensions/NSIndexPath_Extensions.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// NSIndexPath_Extensions.h -// -// Created by naotaka on 08/10/19. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -/* - - File: NSTreeController_Extensions.h - - Abstract: Implementation for useful extensions to NSIndexPath and - NSTreeController for working with the internal objects and walking - around the tree. This implementation hides the opaque things from - the rest of our application. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple - Computer, Inc. ("Apple") in consideration of your agreement to the - following terms, and your use, installation, modification or - redistribution of this Apple software constitutes acceptance of these - terms. If you do not agree with these terms, please do not use, - install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and - subject to these terms, Apple grants you a personal, non-exclusive - license, under Apple's copyrights in this original Apple software (the - "Apple Software"), to use, reproduce, modify and redistribute the Apple - Software, with or without modifications, in source and/or binary forms; - provided that if you redistribute the Apple Software in its entirety and - without modifications, you must retain this notice and the following - text and disclaimers in all such redistributions of the Apple Software. - Neither the name, trademarks, service marks or logos of Apple Computer, - Inc. may be used to endorse or promote products derived from the Apple - Software without specific prior written permission from Apple. Except - as expressly stated in this notice, no other rights or licenses, express - or implied, are granted by Apple herein, including but not limited to - any patent rights that may be infringed by your derivative works or by - other works in which the Apple Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE - MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION - THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND - OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, - MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED - AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), - STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Copyright © 2005 Apple Computer, Inc., All Rights Reserved - - */ - - -#import - - -@interface NSIndexPath (MyExtensions) - -// get us the final piece of the index path, i.e, the one that tells -// us were this path fits among its siblings - -- (NSUInteger)lastIndex; - -// answer whether receiver is the ancestor (other is a descendant) - -- (BOOL)isAncestorOfIndexPath:(NSIndexPath *)other; - -// answer whether receiver has same immediate parent as other - -- (BOOL)isSiblingOfIndexPath:(NSIndexPath *)other; - -// find a common ancestor in the tree controller -// return nil if no common ancestor -// these may not be necessary - -- (NSIndexPath *)firstCommonAncestorWithIndexPath:(NSIndexPath *)other; -+ (NSIndexPath *)firstCommonAncestorAmongIndexPaths:(NSArray *)otherPaths; - -@end - - -@interface NSIndexPath (NaoAdditions) -- (NSIndexPath *)parentPathIndex; -- (NSIndexPath *)incrementLastNodeIndex; - -@end diff --git a/Source/CocoaExtensions/NSIndexPath_Extensions.m b/Source/CocoaExtensions/NSIndexPath_Extensions.m deleted file mode 100644 index ab2d6f5..0000000 --- a/Source/CocoaExtensions/NSIndexPath_Extensions.m +++ /dev/null @@ -1,174 +0,0 @@ -// -// NSIndexPath_Extensions.m -// -// Created by naotaka on 08/10/19. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -/* - - File: NSTreeController_Extensions.h - - Abstract: Implementation for useful extensions to NSIndexPath and - NSTreeController for working with the internal objects and walking - around the tree. This implementation hides the opaque things from - the rest of our application. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple - Computer, Inc. ("Apple") in consideration of your agreement to the - following terms, and your use, installation, modification or - redistribution of this Apple software constitutes acceptance of these - terms. If you do not agree with these terms, please do not use, - install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and - subject to these terms, Apple grants you a personal, non-exclusive - license, under Apple's copyrights in this original Apple software (the - "Apple Software"), to use, reproduce, modify and redistribute the Apple - Software, with or without modifications, in source and/or binary forms; - provided that if you redistribute the Apple Software in its entirety and - without modifications, you must retain this notice and the following - text and disclaimers in all such redistributions of the Apple Software. - Neither the name, trademarks, service marks or logos of Apple Computer, - Inc. may be used to endorse or promote products derived from the Apple - Software without specific prior written permission from Apple. Except - as expressly stated in this notice, no other rights or licenses, express - or implied, are granted by Apple herein, including but not limited to - any patent rights that may be infringed by your derivative works or by - other works in which the Apple Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE - MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION - THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND - OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, - MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED - AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), - STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Copyright © 2005 Apple Computer, Inc., All Rights Reserved - - */ - - -#import "NSIndexPath_Extensions.h" - -@implementation NSIndexPath (MyExtensions) - -- (NSUInteger)lastIndex; -{ - return [self indexAtPosition: [self length] - 1]; -} - -- (BOOL)isAncestorOfIndexPath:(NSIndexPath *)other; // i.e., other descends from receiver -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 < l2 ) { - NSUInteger elems1[l1], elems2[l2], i; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < l1; ++i ) - if ( elems1[i] != elems2[i] ) - return NO; - - return YES; - } - - return NO; -} - -- (BOOL)isSiblingOfIndexPath:(NSIndexPath *)other; // i.e., other has same parent as receiver -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 == l2 ) { - NSUInteger elems1[l1], elems2[l2], i; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < l1 - 1; ++i ) - if ( elems1[i] != elems2[i] ) - return NO; - - return YES; - } - - return NO; -} - -- (NSIndexPath *)firstCommonAncestorWithIndexPath:(NSIndexPath *)other; -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 && l2 ) { - NSUInteger elems1[l1], elems2[l2], i, min = ( l1 < l2 ) ? l1-1 : l2-1; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < min; ++i ) - if ( elems1[i] != elems2[i] ) - break; - - return i ? [NSIndexPath indexPathWithIndexes: elems1 length: i] : nil; - } - - return nil; -} - -+ (NSIndexPath *)firstCommonAncestorAmongIndexPaths:(NSArray *)paths; -{ - if ( [paths count] < 1 ) return nil; - - NSEnumerator *pathEnumerator = [paths objectEnumerator]; - NSIndexPath *path1 = [pathEnumerator nextObject], *path, *result = [path1 indexPathByRemovingLastIndex]; - - while ( path = [pathEnumerator nextObject] ) { - NSIndexPath *candidate = [path firstCommonAncestorWithIndexPath: path1]; - - if ( !candidate ) return nil; - - if ( [candidate length] < [result length] ) result = candidate; - } - - return result; -} - -@end - - -@implementation NSIndexPath (NaoAdditions) - -- (NSIndexPath *)parentPathIndex -{ - if ([self length] > 1) { - return [self indexPathByRemovingLastIndex]; - } - - return [NSIndexPath indexPathWithIndex:[self lastIndex]]; -} - -- (NSIndexPath *)incrementLastNodeIndex -{ - NSInteger lastNodeIndex = [self lastIndex]; - NSIndexPath *tempPath = [self indexPathByRemovingLastIndex]; - NSInteger insertionIndex = lastNodeIndex + 1; - - NSAssert(insertionIndex >= 0, @"The insertionIndex must be a positive number"); - - return (tempPath) - ? [tempPath indexPathByAddingIndex:insertionIndex] - : [NSIndexPath indexPathWithIndex:insertionIndex]; -} - -@end diff --git a/Source/CocoaExtensions/SeparatorCell.h b/Source/CocoaExtensions/SeparatorCell.h deleted file mode 100644 index 8e2ce8c..0000000 --- a/Source/CocoaExtensions/SeparatorCell.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// File: SeparatorCell.h -// -// Abstract: Subclass of NSActionCell which displays a separator line. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import - -@interface SeparatorCell : NSTextFieldCell -{} - -@end diff --git a/Source/CocoaExtensions/SeparatorCell.m b/Source/CocoaExtensions/SeparatorCell.m deleted file mode 100644 index a7bc855..0000000 --- a/Source/CocoaExtensions/SeparatorCell.m +++ /dev/null @@ -1,87 +0,0 @@ -// -// File: SeparatorCell.m -// -// Abstract: Subclass of NSActionCell which displays a separator line. -// -// Version: 1.0 -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") -// in consideration of your agreement to the following terms, and your use, -// installation, modification or redistribution of this Apple software -// constitutes acceptance of these terms. If you do not agree with these -// terms, please do not use, install, modify or redistribute this Apple -// software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non - exclusive -// license, under Apple's copyrights in this original Apple software ( the -// "Apple Software" ), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and / or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following text -// and disclaimers in all such redistributions of the Apple Software. Neither -// the name, trademarks, service marks or logos of Apple Inc. may be used to -// endorse or promote products derived from the Apple Software without specific -// prior written permission from Apple. Except as expressly stated in this -// notice, no other rights or licenses, express or implied, are granted by -// Apple herein, including but not limited to any patent rights that may be -// infringed by your derivative works or by other works in which the Apple -// Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION -// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION -// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER -// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR -// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2007 Apple Inc. All Rights Reserved. -// - -#import "SeparatorCell.h" - -@implementation SeparatorCell - -// ------------------------------------------------------------------------------- -// copyWithZone:zone -// ------------------------------------------------------------------------------- -- (id)copyWithZone:(NSZone*)zone -{ - SeparatorCell *cell = (SeparatorCell*)[super copyWithZone:zone]; - return cell; -} - -// ------------------------------------------------------------------------------- -// drawWithFrame:cellFrame:controlView: -// ------------------------------------------------------------------------------- -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView -{ - // draw the separator - CGFloat lineWidth = cellFrame.size.width; - CGFloat lineX = 0; - CGFloat lineY = (cellFrame.size.height - 2) / 2; - lineY += 0.5; - - [[NSColor colorWithDeviceRed:.349 green:.6 blue:.898 alpha:0.6] set]; - NSRectFill(NSMakeRect(cellFrame.origin.x + lineX, cellFrame.origin.y + lineY, lineWidth, 1)); - - [[NSColor colorWithDeviceRed:0.976 green:1.0 blue:1.0 alpha:1.0] set]; - NSRectFill(NSMakeRect(cellFrame.origin.x + lineX, cellFrame.origin.y + lineY + 1, lineWidth, 1)); -} - -// ------------------------------------------------------------------------------- -// selectWithFrame:inView:editor:delegate:event:start:length -// ------------------------------------------------------------------------------- -- (void)selectWithFrame:(NSRect)aRect inView:(NSView*)controlView editor:(NSText*)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength -{ -} - -@end - diff --git a/Source/DBPrefsWindowController/DBPrefsWindowController.h b/Source/DBPrefsWindowController/DBPrefsWindowController.h deleted file mode 100644 index 0668118..0000000 --- a/Source/DBPrefsWindowController/DBPrefsWindowController.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// DBPrefsWindowController.h -// -// Created by Dave Batton -// http://www.Mere-Mortal-Software.com/blog/ -// -// Documentation for this class is available here: -// http://www.mere-mortal-software.com/blog/details.php?d=2007-03-11 -// -// Copyright 2007. Some rights reserved. -// This work is licensed under a Creative Commons license: -// http://creativecommons.org/licenses/by/3.0/ -// -// 11 March 2007 : Initial 1.0 release -// 15 March 2007 : Version 1.1 -// Resizing is now handled along with the cross-fade by -// the NSViewAnimation routine. -// Cut the fade time in half to speed up the window resize. -// -setupToolbar is now called each time the window opens so -// you can configure it differently each time if you want. -// Holding down the shift key will now slow down the animation. -// This can be disabled by using the new -setShiftSlowsAnimation: -// method. -// 23 March 2007 : Version 1.1.1 -// The initial first responder now gets set when the view is -// swapped so that the user can tab to the objects displayed -// in the window. -// Also added a work-around to Cocoa's insistance on drawing -// a focus ring around the first toolbar icon when going from -// a view with a focusable item to a view without a focusable item. -// -// 31 May 2007 : Version 1.1.2 -// The window's title bar and toolbar heights are now calculated at -// runtime, rather than being hard-coded. -// Fixed a redraw problem and a window placement problem associated -// with large preference windows. -// Added some code to supress compiler warnings from unused parameters. -// Fixed a couple of objects that weren't being properly released. -// - - -#import - - -@interface DBPrefsWindowController : NSWindowController -{ - NSMutableArray *toolbarIdentifiers; - NSMutableDictionary *toolbarViews; - NSMutableDictionary *toolbarItems; - - BOOL _crossFade; - BOOL _shiftSlowsAnimation; - - NSView *contentSubview; - NSViewAnimation *viewAnimation; -} - - -+ (DBPrefsWindowController *)sharedPrefWindowController; -+ (NSString *)nibName; - -- (void)setupToolbar; -- (void)addView:(NSView *)view label:(NSString *)label; -- (void)addView:(NSView *)view label:(NSString *)label image:(NSImage *)image; - -- (BOOL)crossFade; -- (void)setCrossFade:(BOOL)fade; -- (BOOL)shiftSlowsAnimation; -- (void)setShiftSlowsAnimation:(BOOL)slows; - -- (void)displayViewForIdentifier:(NSString *)identifier animate:(BOOL)animate; -- (void)crossFadeView:(NSView *)oldView withView:(NSView *)newView; -- (NSRect)frameForView:(NSView *)view; - - -@end diff --git a/Source/DBPrefsWindowController/DBPrefsWindowController.m b/Source/DBPrefsWindowController/DBPrefsWindowController.m deleted file mode 100644 index 0978f5e..0000000 --- a/Source/DBPrefsWindowController/DBPrefsWindowController.m +++ /dev/null @@ -1,409 +0,0 @@ -// -// DBPrefsWindowController.m -// - -#import "DBPrefsWindowController.h" - - -static DBPrefsWindowController *_sharedPrefWindowController = nil; - - -@implementation DBPrefsWindowController - - - - -#pragma mark - -#pragma mark Class Methods - - -+ (DBPrefsWindowController *)sharedPrefWindowController -{ - if (!_sharedPrefWindowController) { - _sharedPrefWindowController = [[self alloc] initWithWindowNibName:[self nibName]]; - } - return _sharedPrefWindowController; -} - - - - -+ (NSString *)nibName - // Subclasses can override this to use a nib with a different name. -{ - return @"Preferences"; -} - - - - -#pragma mark - -#pragma mark Setup & Teardown - - -- (id)initWithWindow:(NSWindow *)window - // -initWithWindow: is the designated initializer for NSWindowController. -{ - self = [super initWithWindow:nil]; - if (self != nil) { - // Set up an array and some dictionaries to keep track - // of the views we'll be displaying. - toolbarIdentifiers = [[NSMutableArray alloc] init]; - toolbarViews = [[NSMutableDictionary alloc] init]; - toolbarItems = [[NSMutableDictionary alloc] init]; - - // Set up an NSViewAnimation to animate the transitions. - viewAnimation = [[NSViewAnimation alloc] init]; - [viewAnimation setAnimationBlockingMode:NSAnimationNonblocking]; - [viewAnimation setAnimationCurve:NSAnimationEaseInOut]; - [viewAnimation setDelegate:self]; - - [self setCrossFade:YES]; - [self setShiftSlowsAnimation:YES]; - } - return self; - - (void)window; // To prevent compiler warnings. -} - - - - -- (void)windowDidLoad -{ - // Create a new window to display the preference views. - // If the developer attached a window to this controller - // in Interface Builder, it gets replaced with this one. - NSWindow *window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,1000,1000) - styleMask:(NSTitledWindowMask | - NSClosableWindowMask | - NSMiniaturizableWindowMask) - backing:NSBackingStoreBuffered - defer:YES] autorelease]; - [self setWindow:window]; - contentSubview = [[[NSView alloc] initWithFrame:[[[self window] contentView] frame]] autorelease]; - [contentSubview setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)]; - [[[self window] contentView] addSubview:contentSubview]; - [[self window] setShowsToolbarButton:NO]; -} - - - - -- (void) dealloc { - [toolbarIdentifiers release]; - [toolbarViews release]; - [toolbarItems release]; - [viewAnimation release]; - [super dealloc]; -} - - - - -#pragma mark - -#pragma mark Configuration - - -- (void)setupToolbar -{ - // Subclasses must override this method to add items to the - // toolbar by calling -addView:label: or -addView:label:image:. -} - - - - -- (void)addView:(NSView *)view label:(NSString *)label -{ - [self addView:view - label:label - image:[NSImage imageNamed:label]]; -} - - - - -- (void)addView:(NSView *)view label:(NSString *)label image:(NSImage *)image -{ - NSAssert (view != nil, - @"Attempted to add a nil view when calling -addView:label:image:."); - - NSString *identifier = [[label copy] autorelease]; - - [toolbarIdentifiers addObject:identifier]; - [toolbarViews setObject:view forKey:identifier]; - - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:identifier] autorelease]; - [item setLabel:label]; - [item setImage:image]; - [item setTarget:self]; - [item setAction:@selector(toggleActivePreferenceView:)]; - - [toolbarItems setObject:item forKey:identifier]; -} - - - - -#pragma mark - -#pragma mark Accessor Methods - - -- (BOOL)crossFade -{ - return _crossFade; -} - - - - -- (void)setCrossFade:(BOOL)fade -{ - _crossFade = fade; -} - - - - -- (BOOL)shiftSlowsAnimation -{ - return _shiftSlowsAnimation; -} - - - - -- (void)setShiftSlowsAnimation:(BOOL)slows -{ - _shiftSlowsAnimation = slows; -} - - - - -#pragma mark - -#pragma mark Overriding Methods - - -- (IBAction)showWindow:(id)sender -{ - // This forces the resources in the nib to load. - (void)[self window]; - - // Clear the last setup and get a fresh one. - [toolbarIdentifiers removeAllObjects]; - [toolbarViews removeAllObjects]; - [toolbarItems removeAllObjects]; - [self setupToolbar]; - - NSAssert (([toolbarIdentifiers count] > 0), - @"No items were added to the toolbar in -setupToolbar."); - - if ([[self window] toolbar] == nil) { - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"DBPreferencesToolbar"]; - [toolbar setAllowsUserCustomization:NO]; - [toolbar setAutosavesConfiguration:NO]; - [toolbar setSizeMode:NSToolbarSizeModeDefault]; - [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; - [toolbar setDelegate:self]; - [[self window] setToolbar:toolbar]; - [toolbar release]; - } - - NSString *firstIdentifier = [toolbarIdentifiers objectAtIndex:0]; - [[[self window] toolbar] setSelectedItemIdentifier:firstIdentifier]; - [self displayViewForIdentifier:firstIdentifier animate:NO]; - - [[self window] center]; - - [super showWindow:sender]; -} - - - - -#pragma mark - -#pragma mark Toolbar - - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar -{ - return toolbarIdentifiers; - - (void)toolbar; -} - - - - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar -{ - return toolbarIdentifiers; - - (void)toolbar; -} - - - - -- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar -{ - return toolbarIdentifiers; - (void)toolbar; -} - - - - -- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)identifier willBeInsertedIntoToolbar:(BOOL)willBeInserted -{ - return [toolbarItems objectForKey:identifier]; - (void)toolbar; - (void)willBeInserted; -} - - - - -- (void)toggleActivePreferenceView:(NSToolbarItem *)toolbarItem -{ - [self displayViewForIdentifier:[toolbarItem itemIdentifier] animate:YES]; -} - - - - -- (void)displayViewForIdentifier:(NSString *)identifier animate:(BOOL)animate -{ - // Find the view we want to display. - NSView *newView = [toolbarViews objectForKey:identifier]; - - // See if there are any visible views. - NSView *oldView = nil; - if ([[contentSubview subviews] count] > 0) { - // Get a list of all of the views in the window. Usually at this - // point there is just one visible view. But if the last fade - // hasn't finished, we need to get rid of it now before we move on. - NSEnumerator *subviewsEnum = [[contentSubview subviews] reverseObjectEnumerator]; - - // The first one (last one added) is our visible view. - oldView = [subviewsEnum nextObject]; - - // Remove any others. - NSView *reallyOldView = nil; - while ((reallyOldView = [subviewsEnum nextObject]) != nil) { - [reallyOldView removeFromSuperviewWithoutNeedingDisplay]; - } - } - - if (![newView isEqualTo:oldView]) { - NSRect frame = [newView bounds]; - frame.origin.y = NSHeight([contentSubview frame]) - NSHeight([newView bounds]); - [newView setFrame:frame]; - [contentSubview addSubview:newView]; - [[self window] setInitialFirstResponder:newView]; - - if (animate && [self crossFade]) - [self crossFadeView:oldView withView:newView]; - else { - [oldView removeFromSuperviewWithoutNeedingDisplay]; - [newView setHidden:NO]; - [[self window] setFrame:[self frameForView:newView] display:YES animate:animate]; - } - - [[self window] setTitle:[[toolbarItems objectForKey:identifier] label]]; - } -} - - - - -#pragma mark - -#pragma mark Cross-Fading Methods - - -- (void)crossFadeView:(NSView *)oldView withView:(NSView *)newView -{ - [viewAnimation stopAnimation]; - - if ([self shiftSlowsAnimation] && [[[self window] currentEvent] modifierFlags] & NSShiftKeyMask) - [viewAnimation setDuration:1.25]; - else - [viewAnimation setDuration:0.25]; - - NSDictionary *fadeOutDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - oldView, NSViewAnimationTargetKey, - NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, - nil]; - - NSDictionary *fadeInDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - newView, NSViewAnimationTargetKey, - NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, - nil]; - - NSDictionary *resizeDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - [self window], NSViewAnimationTargetKey, - [NSValue valueWithRect:[[self window] frame]], NSViewAnimationStartFrameKey, - [NSValue valueWithRect:[self frameForView:newView]], NSViewAnimationEndFrameKey, - nil]; - - NSArray *animationArray = [NSArray arrayWithObjects: - fadeOutDictionary, - fadeInDictionary, - resizeDictionary, - nil]; - - [viewAnimation setViewAnimations:animationArray]; - [viewAnimation startAnimation]; -} - - - - -- (void)animationDidEnd:(NSAnimation *)animation -{ - NSView *subview; - - // Get a list of all of the views in the window. Hopefully - // at this point there are two. One is visible and one is hidden. - NSEnumerator *subviewsEnum = [[contentSubview subviews] reverseObjectEnumerator]; - - // This is our visible view. Just get past it. - subview = [subviewsEnum nextObject]; - - // Remove everything else. There should be just one, but - // if the user does a lot of fast clicking, we might have - // more than one to remove. - while ((subview = [subviewsEnum nextObject]) != nil) { - [subview removeFromSuperviewWithoutNeedingDisplay]; - } - - // This is a work-around that prevents the first - // toolbar icon from becoming highlighted. - [[self window] makeFirstResponder:nil]; - - (void)animation; -} - - - - -- (NSRect)frameForView:(NSView *)view - // Calculate the window size for the new view. -{ - NSRect windowFrame = [[self window] frame]; - NSRect contentRect = [[self window] contentRectForFrameRect:windowFrame]; - float windowTitleAndToolbarHeight = NSHeight(windowFrame) - NSHeight(contentRect); - - windowFrame.size.height = NSHeight([view frame]) + windowTitleAndToolbarHeight; - windowFrame.size.width = NSWidth([view frame]); - windowFrame.origin.y = NSMaxY([[self window] frame]) - NSHeight(windowFrame); - - return windowFrame; -} - - - - -@end diff --git a/Source/FolderNode.h b/Source/FolderNode.h deleted file mode 100644 index 857ffc2..0000000 --- a/Source/FolderNode.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// FolderNode.h -// ClipMenu -// -// Created by naotaka on 09/11/29. -// Copyright 2009 Naotaka Morimoto. All rights reserved. -// - -#import -#import "BaseNode.h" - - -@interface FolderNode : BaseNode -{ - NSManagedObject *folder; - - NSInteger index; - BOOL isEnabled; -} -@property(nonatomic, retain) NSManagedObject *folder; -@property(nonatomic, assign) NSInteger index; -@property(nonatomic, assign) BOOL isEnabled; -//@property(nonatomic, readonly) NSSet *snippets; -@property(nonatomic, assign) NSSet *snippets; - -@end diff --git a/Source/FolderNode.m b/Source/FolderNode.m deleted file mode 100644 index e386cec..0000000 --- a/Source/FolderNode.m +++ /dev/null @@ -1,130 +0,0 @@ -// -// FolderNode.m -// ClipMenu -// -// Created by naotaka on 09/11/29. -// Copyright 2009 Naotaka Morimoto. All rights reserved. -// - -#import "FolderNode.h" -#import "constants.h" - -#define DEFAULT_TITLE @"Untitled" - - -@implementation FolderNode - -@synthesize folder; - -//- (id)init -//{ -// self = [super init]; -// if (self == nil) { -// return nil; -// } -// -// [self addObserver:self -// forKeyPath:@"nodeTitle" -// options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld -// context:nil]; -// -// return self; -//} -// -//- (void)dealloc -//{ -// [self removeObserver:self forKeyPath:@"nodeTitle"]; -// -// [super dealloc]; -//} - -- (void)setNodeTitle:(NSString *)newNodeTitle -{ - [super setNodeTitle:newNodeTitle]; - - if (self.folder && - ![newNodeTitle isEqualToString:DEFAULT_TITLE] && - ![newNodeTitle isEqualToString:GROUP_NAME]) { - [self.folder setValue:newNodeTitle forKey:kTitle]; - } -} - -- (void)setIndex:(NSInteger)newIndex -{ - if (index == newIndex) { - return; - } - - index = newIndex; - - if (self.folder) { - [self.folder setValue:[NSNumber numberWithInteger:newIndex] forKey:kIndex]; - } -} - -- (NSInteger)index -{ - if (self.folder == nil) { - return -1; - } - - return [[self.folder valueForKey:kIndex] integerValue]; -} - -- (void)setIsEnabled:(BOOL)flag -{ - isEnabled = flag; - - if (self.folder) { - [self.folder setValue:[NSNumber numberWithBool:flag] forKey:kEnabled]; - } -} - -- (BOOL)isEnabled -{ - if (self.folder == nil) { - return YES; - } - - return [[self.folder valueForKey:kEnabled] boolValue]; -} - -- (void)setSnippets:(NSSet *)newSenippets -{ - if (self.folder == nil) { - return; - } - - [self.folder setValue:newSenippets forKey:kSnippets]; -} - -- (NSSet *)snippets -{ - if (self.folder == nil) { - return nil; - } - - return [self.folder valueForKey:kSnippets]; -} - -//#pragma mark - -//#pragma mark KVO -// -//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -//{ -// NSLog(@"change: %@", change); -// -// if ([keyPath isEqualToString:@"nodeTitle"]) { -// NSString *oldTitle = [change objectForKey:kOldKey]; -// if ([oldTitle isEqualToString:DEFAULT_TITLE]) { -// return; -// } -// -// NSString *newTitle = [change objectForKey:kNewKey]; -// NSLog(@"new: %@", newTitle); -// -// [self.folder setValue:newTitle forKey:kTitle]; -// } -//} - -@end diff --git a/Source/IndexedArrayController.h b/Source/IndexedArrayController.h deleted file mode 100644 index 9505f9d..0000000 --- a/Source/IndexedArrayController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// IndexedArrayController.h -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface IndexedArrayController : NSArrayController -{ -} - -- (void)renumber; - -@end diff --git a/Source/IndexedArrayController.m b/Source/IndexedArrayController.m deleted file mode 100644 index 9d535d2..0000000 --- a/Source/IndexedArrayController.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// IndexedArrayController.m -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "IndexedArrayController.h" -#import "constants.h" - - -@implementation IndexedArrayController - -- (void)awakeFromNib -{ - [super awakeFromNib]; - - NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:kIndex ascending:YES]; - [super setSortDescriptors:[NSArray arrayWithObject:descriptor]]; - [descriptor release], descriptor = nil; - - [self setAutomaticallyPreparesContent:YES]; -} - -- (void)addObject:(id)object -{ - NSUInteger lastIndex = [[self arrangedObjects] count]; - [object setValue:[NSNumber numberWithUnsignedInteger:lastIndex] forKey:kIndex]; -// NSLog(@"addObject: %@", object); - - [super addObject:object]; -} - -- (void)addObjects:(NSArray *)objects -{ - for (id object in objects) { - [self addObject:object]; - } -} - -- (void)insertObject:(id)object atArrangedObjectIndex:(NSUInteger)index -{ -// NSLog(@"insertObject: %@, index: %d", object, index); - - [(NSManagedObject *)object setValue:[NSNumber numberWithUnsignedInteger:index] forKey:kIndex]; - - [super insertObject:object atArrangedObjectIndex:index]; - [self renumber]; -} - -- (void)insertObjects:(NSArray *)objects atArrangedObjectIndexes:(NSIndexSet *)indexes -{ -// NSLog(@"insertObjects: %@", indexes); - - [super insertObjects:objects atArrangedObjectIndexes:indexes]; - [self renumber]; -} - -//- (void)removeObject:(id)object -//{ -//// NSLog(@"removeObject"); -// -// [super removeObject:object]; -// [self renumber]; -//} - -- (void)removeObjectAtArrangedObjectIndex:(NSUInteger)index -{ -// NSLog(@"removeObjectAtArrangedObjectIndex: %d", index); - - [super removeObjectAtArrangedObjectIndex:index]; - [self renumber]; -} - -- (void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet *)indexes -{ -// NSLog(@"removeObjectsAtArrangedObjectIndexes: %@", indexes); - - [super removeObjectsAtArrangedObjectIndexes:indexes]; - [self renumber]; -} - -#pragma mark - - -- (void)renumber -{ -// NSLog(@"renumber"); - - NSUInteger i = 0; - for (NSManagedObject *managedObject in [self arrangedObjects]) { -// NSLog(@"managedObject: %@", managedObject); - - [managedObject setValue:[NSNumber numberWithUnsignedInteger:i] forKey:kIndex]; - i++; - -// NSLog(@"managedObject: %@", managedObject); - } -} - -@end diff --git a/Source/JavaScriptSupport.h b/Source/JavaScriptSupport.h deleted file mode 100644 index ae41dee..0000000 --- a/Source/JavaScriptSupport.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// JavaScriptSupport.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/28. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import -#import - - -@interface JavaScriptSupport : NSObject -{ - WebScriptObject *scriptObject; -} -@property (nonatomic, retain) WebScriptObject *scriptObject; - -- (id)initWithScriptObject:(WebScriptObject *)webScriptObject; - -@end diff --git a/Source/JavaScriptSupport.m b/Source/JavaScriptSupport.m deleted file mode 100644 index f58878a..0000000 --- a/Source/JavaScriptSupport.m +++ /dev/null @@ -1,144 +0,0 @@ -// -// JavaScriptSupport.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/02/28. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "JavaScriptSupport.h" -#import "constants.h" -#import "CMUtilities.h" -#import "ActionController.h" - - -@interface JavaScriptSupport () -- (NSString *)_loadScript:(NSString *)filePath; - -- (BOOL)_require:(NSString *)filename; -- (void)_activate; -@end - -#pragma mark - - -@implementation JavaScriptSupport - -@synthesize scriptObject; - -- (id)initWithScriptObject:(WebScriptObject *)webScriptObject -{ - self = [super init]; - if (self) { - [self setScriptObject:webScriptObject]; - } - return self; -} - -- (void)dealloc -{ - [scriptObject release], scriptObject = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark WebSpripting protocol - -+ (NSString *)webScriptNameForSelector:(SEL)aSelector -{ -// NSLog(@"webScriptNameForSelector"); - - if (aSelector == @selector( _require: )) { - return @"require"; - } - else if (aSelector == @selector( _activate )) { - return @"activate"; - } - - return nil; -} - -+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector -{ - if (aSelector == @selector( _require: ) || - aSelector == @selector( _activate )) { - return NO; - } - return YES; -} - -//+ (BOOL)isKeyExcludedFromWebScript:(const char *)name -//{ -// return NO; -//} - -#pragma mark - -#pragma mark Private - -- (NSString *)_loadScript:(NSString *)filePath -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { - return nil; - } - - NSData *data = [NSData dataWithContentsOfFile:filePath]; - if (!data) { - return nil; - } - - return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; -} - -#pragma mark - JavaScript methods - - -- (BOOL)_require:(NSString *)filename -{ - if (!filename || [filename isEqualToString:kEmptyString]) { - return NO; - } - - /* Check lib directories existance */ - - NSMutableArray *libPaths = [NSMutableArray array]; - - // The first is user's lib directory - NSString *userLibFolder = [CMUtilities userLibFolder]; - if (userLibFolder) { - [libPaths addObject:userLibFolder]; - } - - NSString *scriptLibFolder = [CMUtilities scriptLibFolder]; - if (scriptLibFolder) { - [libPaths addObject:scriptLibFolder]; - } - - if ([libPaths count] == 0) { - return NO; - } - - /* Build script path */ - NSString *scriptName = ([[filename pathExtension] isEqualToString:kJavaScriptExtension]) - ? filename - : [filename stringByAppendingPathExtension:kJavaScriptExtension]; - - /* Load script */ - for (NSString *path in libPaths) { - NSString *scriptFilePath = [path stringByAppendingPathComponent:scriptName]; - NSString *script = [self _loadScript:scriptFilePath]; - if (script) { - [scriptObject evaluateWebScript:script]; - return YES; - } - } - - NSLog(@"Could not find the file"); - return NO; -} - -- (void)_activate -{ - /* for prompt called by JavaScript */ - [[ActionController sharedInstance] keepCurrentFrontProcessAndActivate]; -} - -@end diff --git a/Source/MenuController.h b/Source/MenuController.h deleted file mode 100644 index f266e56..0000000 --- a/Source/MenuController.h +++ /dev/null @@ -1,81 +0,0 @@ -// -// MenuController.h -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/06. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import - -typedef enum { - CMPopUpMenuTypeMain = 0, - CMPopUpMenuTypeHistory, - CMPopUpMenuTypeSnippets, - CMPopUpMenuTypeActions, -} CMPopUpMenuType; - -typedef enum { - CMPositionOfSnippetsNone = 0, - CMPositionOfSnippetsAboveClips, - CMPositionOfSnippetsBelowClips -} CMPositionOfSnippets; - -//extern NSString *const CMClipMenuWillPopUpNotification; -//extern NSString *const CMStatusMenuWillUpdateNotification; - - -@interface MenuController : NSObject -{ - NSMenu *clipMenu; - NSWindow *dummyWindow; - NSStatusItem *statusItem; - NSString *shortVersion; - - /* Menu Icons */ - NSImage *iconForStringPboardType; - NSImage *iconForRTFPboardType; - NSImage *iconForRTFDPboardType; - NSImage *iconForPDFPboardType; - NSImage *iconForFilenamesPboardType; - NSImage *iconForURLPboardType; - NSImage *iconForTIFFPboardType; - - - /* - Action - */ - NSImage *folderIcon; - NSImage *openFolderIcon; - NSImage *actionIcon; - NSImage *javaScriptIcon; - NSImage *snippetIcon; - - NSUInteger menuIconSize; - - NSMenuItem *highlightedMenuItem; -} -@property (nonatomic, retain) NSMenu *clipMenu; -@property (nonatomic, retain) NSWindow *dummyWindow; -@property (nonatomic, retain) NSStatusItem *statusItem; -@property (nonatomic, copy) NSString *shortVersion; -@property (nonatomic, retain) NSImage *iconForStringPboardType; -@property (nonatomic, retain) NSImage *iconForRTFPboardType; -@property (nonatomic, retain) NSImage *iconForRTFDPboardType; -@property (nonatomic, retain) NSImage *iconForPDFPboardType; -@property (nonatomic, retain) NSImage *iconForFilenamesPboardType; -@property (nonatomic, retain) NSImage *iconForURLPboardType; -@property (nonatomic, retain) NSImage *iconForTIFFPboardType; -@property (nonatomic, retain) NSImage *folderIcon; -@property (nonatomic, retain) NSImage *openFolderIcon; -@property (nonatomic, retain) NSImage *actionIcon; -@property (nonatomic, retain) NSImage *javaScriptIcon; -@property (nonatomic, retain) NSImage *snippetIcon; -@property (nonatomic, assign) NSUInteger menuIconSize; -@property (nonatomic, retain) NSMenuItem *highlightedMenuItem; - -+ (MenuController *)sharedInstance; - -- (void)createStatusItem; -- (void)updateStatusMenu; -- (void)popUpMenuForType:(CMPopUpMenuType)type; - -@end diff --git a/Source/MenuController.m b/Source/MenuController.m deleted file mode 100644 index 59da7a2..0000000 --- a/Source/MenuController.m +++ /dev/null @@ -1,1515 +0,0 @@ -// -// MenuController.m -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/06. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import "MenuController.h" -#import "constants.h" -#import "ActionController.h" -#import "ActionNode.h" -#import "ClipsController.h" -#import "Clip.h" -#import "SnippetsController.h" -#import "SnippetEditorController.h" -#import "PrefsWindowController.h" -#import "NSString+NaoAdditions.h" - - -//#define INLINE_CLIPS_DISPLAY_NUMBER 10 -//#define NUMBER_OF_ITEMS_IN_A_FOLDER 10 -#define kMaxKeyEquivalents 10 - -#define DEFAULT_MENU_FONT_SIZE 14.0 -#define LARGE_MENU_FONT_SIZE 28.0 -#define HUGE_MENU_FONT_SIZE 42.0 -#define SMALL_ICON_SIZE 16 -#define LARGE_ICON_SIZE 32 -#define HUGE_ICON_SIZE 48 -#define THUMBNAIL_ICON_SIZE 128 -#define MENU_TITLE_FORMAT @"%d. %@" -#define SHORTEN_SYMBOL @"..." - -#define STATUS_MENU_ICON @"StatusMenuIcon" -#define STATUS_MENU_ICON_POSTFIX @"_pressed" -#define STATUS_MENU_ICON_FILE_EXTENSION @".png" - -#pragma mark Static variables - -static MenuController *sharedInstance = nil; - -#pragma mark Functions - -BOOL CMIsPerformableAction(NSDictionary *action) -{ - // NSLog(@"action: %@", action); - - NSString *name = [action objectForKey:@"name"]; - NSString *type = [action objectForKey:@"type"]; - NSArray *selectedItemTypes; - - ActionController *actionController = [ActionController sharedInstance]; - NSInteger tag = [actionController selectedClipTag]; - - if (tag < 0) { - /* it's a snippet */ - selectedItemTypes = [NSArray arrayWithObject:NSStringPboardType]; - } - else { - /* its a clip */ - Clip *clip = [[[ClipsController sharedInstance] sortedClips] objectAtIndex:tag]; - selectedItemTypes = [clip types]; - } - - // if ([selectedClipTypes containsObject:NSStringPboardType]) { - // return YES; - // } - - if ([type isEqualToString:CMBuiltinActionTypeKey]) { - NSDictionary *builtInActions = [[actionController builtInActionController] valueForKey:@"actions"]; - NSDictionary *builtInAction = [builtInActions objectForKey:name]; - // NSLog(@"builtInAction: %@", builtInAction); - - for (NSString *key in [builtInAction objectForKey:@"types"]) { - // NSLog(@"key: %@", key); - if ([selectedItemTypes containsObject:key]) { - return YES; - } - } - } - else if ([type isEqualToString:CMJavaScriptActionTypeKey]) { - if ([selectedItemTypes containsObject:NSStringPboardType]) { - return YES; - } - } - - return NO; -} - -NSUInteger firstIndexOfMenuItems() -{ - if ([[NSUserDefaults standardUserDefaults] boolForKey:CMPrefMenuItemsTitleStartWithZeroKey]) { - return 0; - } - return 1; -} - -NSUInteger incrementListNumber(NSUInteger listNumber, NSUInteger max, NSUInteger start) -{ - listNumber++; - - if (listNumber == max - && max == 10 - && start == 1) { - listNumber = 0; - } - - return listNumber; -} - -NSString *trimTitle(NSString *clipString) -{ - if (clipString == nil) { - return kEmptyString; - } - - NSString *theString = [clipString strip]; - - NSRange aRange = NSMakeRange(0,0); - NSUInteger lineStart = 0, lineEnd = 0, contentsEnd = 0; - [theString getLineStart:&lineStart end:&lineEnd contentsEnd:&contentsEnd forRange:aRange]; - - // NSLog(@"start:%d, lineEnd:%d, contentsEnd:%d", lineStart, lineEnd, contentsEnd); - - NSString *titleString = (lineEnd == [theString length]) - ? theString - : [theString substringToIndex:contentsEnd]; - - NSUInteger maxMenuItemTitleLength = [[NSUserDefaults standardUserDefaults] integerForKey:CMPrefMaxMenuItemTitleLengthKey]; - if (maxMenuItemTitleLength < [SHORTEN_SYMBOL length]) { - maxMenuItemTitleLength = [SHORTEN_SYMBOL length]; - } - - if ([titleString length] > maxMenuItemTitleLength) { - titleString = [NSString stringWithFormat:@"%@%@", - [titleString substringToIndex:(maxMenuItemTitleLength - [SHORTEN_SYMBOL length])], - SHORTEN_SYMBOL]; - } - - return titleString; -} - -NSAttributedString *makeAttributedTitle(NSString *title) -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL isChangeFontSize = [defaults boolForKey:CMPrefChangeFontSizeKey]; - NSInteger howToChangeFontSize = [defaults integerForKey:CMPrefHowToChangeFontSizeKey]; - BOOL isShowIcon = [defaults boolForKey:CMPrefShowIconInTheMenuKey]; - - if (!isChangeFontSize) { - return nil; - } - - CGFloat fontSize = DEFAULT_MENU_FONT_SIZE; - - if (howToChangeFontSize == 0 && isShowIcon) { - NSUInteger iconSize = [defaults integerForKey:CMPrefMenuIconSizeKey]; - switch (iconSize) { - case LARGE_ICON_SIZE: - fontSize = LARGE_MENU_FONT_SIZE; - break; - case HUGE_ICON_SIZE: - fontSize = HUGE_MENU_FONT_SIZE; - break; - } - } - else if (howToChangeFontSize == 1) { - fontSize = [defaults floatForKey:CMPrefSelectedFontSizeKey]; - } - - NSFont *font = [NSFont systemFontOfSize:fontSize]; - NSDictionary *attrsDict = [NSDictionary dictionaryWithObject:font - forKey:NSFontAttributeName]; - NSAttributedString *attrString = [[[NSAttributedString alloc] initWithString:title - attributes:attrsDict] autorelease]; - return attrString; -} - -#pragma mark - - -@interface MenuController () -- (void)_buildClipMenu; -- (void)_addClipsToMenu:(NSMenu *)aMenu; -- (void)_addSnippetsToMenu:(NSMenu *)aMenu atPosition:(CMPositionOfSnippets)positionOfSnippets; - -- (NSString *)_menuItemTitleWithString:(NSString *)titileWithMark listNumber:(NSUInteger)listNumber boolean:(BOOL)isMarkWithNumber; -- (NSMenuItem *)_makeMenuItemForClip:(Clip *)clip withCount:(NSUInteger)count andListNumber:(NSUInteger)listNumber; -- (NSMenuItem *)_makeMenuItemForSnippet:(NSManagedObject *)snippet withListNumber:(NSUInteger)listNumber; -- (NSMenuItem *)_makeSubmenuItemWithCount:(NSUInteger)count start:(NSUInteger)start end:(NSUInteger)end numberOfItems:(NSUInteger)numberOfItems; -- (NSMenuItem *)_makeSubmenuItemWithTitle:(NSString *)title; -- (NSMenuItem *)_makeMenuItemWithTitle:(NSString *)itemName action:(SEL)anAction; -//- (NSMenuItem *)_makeSortMenuItem; - -- (NSEvent *)_makeEventFromCurrentEvent:(NSEvent *)currentEvent mousePoint:(NSPoint)mousePoint windowNumber:(NSInteger)windowNumber; -- (NSEvent *)_makeEventForActionFromCurrentEvent:(NSEvent *)currentEvent mousePoint:(NSPoint)mousePoint windowNumber:(NSInteger)windowNumber; -- (NSMenu *)_makeHistoryMenu; -- (NSMenu *)_makeSnippetsMenu; -- (NSMenu *)_makeActionMenu; -- (NSMenuItem *)_makeActionMenuItemFromNode:(ActionNode *)node; -//- (BOOL)_isAppropriateAction:(NSDictionary *)action; - -- (void)_changeStatusItem:(NSUInteger)tag; -- (void)_removeStatusItem; -- (void)_refreshStatusItem; - -- (NSImage *)_iconForPboardType:(NSString *)type; -- (NSString *)_iconCacheKeyForType:(NSString *)type; -- (NSImage *)_iconForSnippet; -- (void)_cacheIconForTypes; -- (void)_cacheFolderIcon; -- (void)_cacheOpenFolderIcon; -- (void)_cacheActionIcon; -- (void)_cacheJavaScriptIcon; -- (void)_cacheSnippetIcon; -- (void)_resetMenuIconSize; -- (void)_resetIconCaches; -- (void)_unhighlightMenuItem; - -- (void)_handlePreferencePanelWillClose:(NSNotification *)aNotification; -- (void)_handleSnippetEditorWillClose:(NSNotification *)aNotification; -- (void)_handleStatusMenuWillUpdate:(NSNotification *)aNotification; - -- (id)_init; -@end - -#pragma mark - -@implementation MenuController - -@synthesize clipMenu; -@synthesize dummyWindow; -@synthesize statusItem; -@synthesize shortVersion; -@synthesize iconForStringPboardType; -@synthesize iconForRTFPboardType; -@synthesize iconForRTFDPboardType; -@synthesize iconForPDFPboardType; -@synthesize iconForFilenamesPboardType; -@synthesize iconForURLPboardType; -@synthesize iconForTIFFPboardType; -@synthesize folderIcon; -@synthesize openFolderIcon; -@synthesize actionIcon; -@synthesize javaScriptIcon; -@synthesize snippetIcon; -@synthesize menuIconSize; -@synthesize highlightedMenuItem; - -#pragma mark - -#pragma mark Initialize - -+ (void)initialize -{ - if (sharedInstance == nil) { - sharedInstance = [[self alloc] _init]; - } -} - -+ (MenuController *)sharedInstance -{ - return [[sharedInstance retain] autorelease]; -} - -- (id)init -{ - NSAssert(self != sharedInstance, @"Should never send init to the singleton instance"); - - [self release]; - [sharedInstance retain]; - return sharedInstance; -} - -- (id)_init -{ - self = [super init]; - if (self) { - [self setShortVersion:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]]; - - [self _buildClipMenu]; // need to edit snippet. should be improved. - - dummyWindow = [[NSWindow alloc] initWithContentRect:NSZeroRect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:YES]; - [dummyWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - -// if ([defaults integerForKey:CMPrefShowStatusItemKey]) { -// [self _createStatusItem]; -// } - - [self _resetIconCaches]; - - /* KVO */ - [defaults addObserver:self - forKeyPath:CMPrefShowStatusItemKey - options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) - context:nil]; - [defaults addObserver:self - forKeyPath:CMPrefMenuIconSizeKey - options:NSKeyValueObservingOptionNew - context:nil]; - - /* Notification */ - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector( _handlePreferencePanelWillClose: ) - name:CMPreferencePanelWillCloseNotification - object:nil]; - [nc addObserver:self - selector:@selector( _handleSnippetEditorWillClose: ) - name:CMSnippetEditorWillCloseNotification - object:nil]; - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - /* KVO */ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults removeObserver:self - forKeyPath:CMPrefShowStatusItemKey]; - [defaults removeObserver:self - forKeyPath:CMPrefMenuIconSizeKey]; - - - [clipMenu release], clipMenu = nil; - [dummyWindow release], dummyWindow = nil; - - if (statusItem) { - [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; - [statusItem release], statusItem = nil; - } - - [shortVersion release], shortVersion = nil; - [iconForStringPboardType release], iconForStringPboardType = nil; - [iconForRTFPboardType release], iconForRTFPboardType = nil; - [iconForRTFDPboardType release], iconForRTFDPboardType = nil; - [iconForPDFPboardType release], iconForPDFPboardType = nil; - [iconForFilenamesPboardType release], iconForFilenamesPboardType = nil; - [iconForURLPboardType release], iconForURLPboardType = nil; - [iconForTIFFPboardType release], iconForTIFFPboardType = nil; - - [folderIcon release], folderIcon = nil; - [openFolderIcon release], openFolderIcon = nil; - [actionIcon release], actionIcon = nil; - [javaScriptIcon release], javaScriptIcon = nil; - [snippetIcon release], snippetIcon = nil; - - [highlightedMenuItem release], highlightedMenuItem = nil; - - [super dealloc]; -} - -#pragma mark - -#pragma mark KVO - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ -// NSLog(@"observeValueForKeyPath: %@ - change: %@", keyPath, change); - - if ([keyPath isEqualToString:CMPrefShowStatusItemKey]) { -// [self _toggleStatusItem]; - - NSInteger old = [[change objectForKey:kOldKey] integerValue]; - NSInteger new = [[change objectForKey:kNewKey] integerValue]; - - if (new == 0) { - [self _removeStatusItem]; - } - else if (new != old) { - [self _changeStatusItem:new]; - } - } - else if ([keyPath isEqualToString:CMPrefMenuIconSizeKey]) { - [self _resetMenuIconSize]; - } -} - -#pragma mark - -#pragma mark Delegate -#pragma mark - NSMenu - - -//- (void)menuNeedsUpdate:(NSMenu *)menu -//{ -//// NSLog(@"menuNeedsUpdate"); -// -// [[NSNotificationCenter defaultCenter] postNotificationName:CMClipMenuWillPopUpNotification object:nil]; -//} - -- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item -{ - if (highlightedMenuItem && ![item isEqualTo:highlightedMenuItem]) { - [self _unhighlightMenuItem]; - } - - if (![item hasSubmenu]) { - return; - } - - if ([item image] && openFolderIcon) { - [self setHighlightedMenuItem:item]; - [item setImage:openFolderIcon]; - } -} - -- (void)menuDidClose:(NSMenu *)menu -{ - if (highlightedMenuItem) { - [self _unhighlightMenuItem]; - } -} - -#pragma mark - -#pragma mark Public - -- (void)createStatusItem -{ - if (statusItem == nil) { - NSUInteger statusMenuIconTag = [[NSUserDefaults standardUserDefaults] - integerForKey:CMPrefShowStatusItemKey]; - - [self _changeStatusItem:statusMenuIconTag]; - } -} - -- (void)updateStatusMenu -{ -// NSLog(@"updateStatusMenu: %@", statusItem); - - if (statusItem) { -// [self _resetMenuIconSize]; // XXX Need to modify? - - [self _buildClipMenu]; - [statusItem setMenu:clipMenu]; - } -} - -- (void)popUpMenuForType:(CMPopUpMenuType)type -{ - NSEvent *currentEvent = [NSApp currentEvent]; - NSPoint locationInWindow = [currentEvent locationInWindow]; - NSPoint mouseLocation; // for Actions - NSPoint mousePoint; - NSEvent *newEvent; - -// NSLog(@"currentEvent: %@", currentEvent); -// NSLog(@"origin: %@", NSStringFromPoint([currentEvent locationInWindow])); - - [dummyWindow makeKeyAndOrderFront:self]; - [dummyWindow setFrameOrigin:locationInWindow]; - NSInteger windowNumber = [dummyWindow windowNumber]; - -// NSLog(@"popUpClipMenu: %@", NSStringFromPoint(mousePoint)); - - NSMenu *menu; - - switch (type) { - case CMPopUpMenuTypeMain: - mousePoint = [dummyWindow convertScreenToBase:locationInWindow]; - newEvent = [self _makeEventFromCurrentEvent:currentEvent - mousePoint:mousePoint - windowNumber:windowNumber]; - [self _buildClipMenu]; - menu = clipMenu; - break; - case CMPopUpMenuTypeHistory: - mousePoint = [dummyWindow convertScreenToBase:locationInWindow]; - newEvent = [self _makeEventFromCurrentEvent:currentEvent - mousePoint:mousePoint - windowNumber:windowNumber]; - menu = [self _makeHistoryMenu]; - break; - case CMPopUpMenuTypeSnippets: - mousePoint = [dummyWindow convertScreenToBase:locationInWindow]; - newEvent = [self _makeEventFromCurrentEvent:currentEvent - mousePoint:mousePoint - windowNumber:windowNumber]; - menu = [self _makeSnippetsMenu]; - break; - case CMPopUpMenuTypeActions: - mouseLocation = [NSEvent mouseLocation]; - mousePoint = [dummyWindow convertScreenToBase:mouseLocation]; - newEvent = [self _makeEventForActionFromCurrentEvent:currentEvent - mousePoint:mousePoint - windowNumber:windowNumber]; - menu = [self _makeActionMenu]; - break; - default: - NSAssert(NO, @"Unknown pop up menu type"); - break; - } - -// /* Highlight the first menu item */ -// NSMenuItem *firstItem = [menu itemAtIndex:1]; -// if (firstItem) { -// NSLog(@"item: %@", firstItem); -// [menu _setHighlightedItem:firstItem informingDelegate:YES]; -// NSLog(@"hilighted: %@", [menu highlightedItem]); -// } - - [NSMenu popUpContextMenu:menu withEvent:newEvent forView:nil]; - [dummyWindow orderOut:self]; -} - -#pragma mark - -#pragma mark Private - -#pragma mark - Menu - - -- (void)_buildClipMenu -{ - NSMenu *newMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:kClipMenuIdentifier]; - [newMenu setDelegate:self]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - CMPositionOfSnippets positionOfSnippets = [defaults integerForKey:CMPrefPositionOfSnippetsKey]; - BOOL addClearHistory = [defaults boolForKey:CMPrefAddClearHistoryMenuItemKey]; - - if (CMPositionOfSnippetsAboveClips == positionOfSnippets) { - [self _addSnippetsToMenu:newMenu atPosition:positionOfSnippets]; - } - - [self _addClipsToMenu:newMenu]; - - if (CMPositionOfSnippetsBelowClips == positionOfSnippets) { - [self _addSnippetsToMenu:newMenu atPosition:positionOfSnippets]; - } - - [newMenu addItem:[NSMenuItem separatorItem]]; - - if (addClearHistory) { - [newMenu addItem:[self _makeMenuItemWithTitle:NSLocalizedString(@"Clear History", nil) - action:@selector( clearHistory: )]]; - } - - [newMenu addItem:[self _makeMenuItemWithTitle:NSLocalizedString(@"Edit Snippets...", nil) - action:@selector( showSnippetEditor: )]]; - - [newMenu addItem:[self _makeMenuItemWithTitle:NSLocalizedString(@"Preferences...", nil) - action:@selector( showPreferencePanel: )]]; - - // [newMenu addItemWithTitle:NSLocalizedString(@"About ClipMenu", nil) - // action:@selector( orderFrontStandardAboutPanel: ) - // keyEquivalent:kEmptyString]; - [newMenu addItem:[NSMenuItem separatorItem]]; - [newMenu addItem:[self _makeMenuItemWithTitle:NSLocalizedString(@"Quit ClipMenu", nil) - action:@selector( terminate: )]]; - - [self setValue:newMenu forKey:@"clipMenu"]; - [newMenu release], newMenu = nil; -} - -- (void)_addClipsToMenu:(NSMenu *)aMenu -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSUInteger numberOfItemsPlaceInline = [defaults integerForKey:CMPrefNumberOfItemsPlaceInlineKey]; - NSUInteger numberOfItemsPlaceInsideFolder = [defaults integerForKey:CMPrefNumberOfItemsPlaceInsideFolderKey]; - NSUInteger maxHistory = [defaults integerForKey:CMPrefMaxHistorySizeKey]; - BOOL showLabelsInMenu = [defaults boolForKey:CMPrefShowLabelsInMenuKey]; - - ClipsController *clipsController = [ClipsController sharedInstance]; - NSArray *clips = [clipsController sortedClips]; - NSUInteger currentSize = [clips count]; - - // if (currentSize < maxHistory) { - // maxHistory = currentSize; - // } - - if (showLabelsInMenu) { - NSMenuItem *labelItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:NSLocalizedString(@"History", nil) - action:NULL - keyEquivalent:kEmptyString]; - [labelItem setEnabled:NO]; - [aMenu addItem:labelItem]; - [labelItem release], labelItem = nil; - } - - NSUInteger firstIndex = firstIndexOfMenuItems(); - NSUInteger listNumber = firstIndex; - NSUInteger submenuCount = numberOfItemsPlaceInline; - NSUInteger submenuIndex = (0 < [aMenu numberOfItems]) ? [aMenu numberOfItems] : 0; - submenuIndex += numberOfItemsPlaceInline; - - NSUInteger i = 0; - - for (Clip *clip in clips) { - // NSLog(@"CHECK i: %d", i); - - if ((numberOfItemsPlaceInline < 1) || - (numberOfItemsPlaceInline - 1) < i) { - /* inside a folder */ - if (i == submenuCount) { - NSMenuItem *submenuItem = [self _makeSubmenuItemWithCount:submenuCount - start:firstIndex - end:currentSize - numberOfItems:numberOfItemsPlaceInsideFolder]; - [aMenu addItem:submenuItem]; - listNumber = firstIndex; - } - - // NSLog(@"CHECK submenuCount: %d", submenuCount); - // NSLog(@"CHECK submenuIndex: %d", submenuIndex); - - // NSUInteger indexOfSubmenu = (enableAction) - // ? submenuIndex + numberOfItemsPlaceInline - // : submenuIndex; - - NSUInteger indexOfSubmenu = submenuIndex; - - // if (showLabelsInMenu) { - // indexOfSubmenu++; - // } - - // NSLog(@"CHECK indexOfSubmenu: %d", indexOfSubmenu); - - NSMenu *submenu = [[aMenu itemAtIndex:indexOfSubmenu] submenu]; - NSMenuItem *menuItem = [self _makeMenuItemForClip:clip - withCount:i - andListNumber:listNumber]; - [submenu addItem:menuItem]; - - listNumber = incrementListNumber(listNumber, numberOfItemsPlaceInsideFolder, firstIndex); - } - else { - /* display clips inline */ - NSMenuItem *menuItem = [self _makeMenuItemForClip:clip - withCount:i - andListNumber:listNumber]; - [aMenu addItem:menuItem]; - - listNumber = incrementListNumber(listNumber, numberOfItemsPlaceInline, firstIndex); - } - - i++; - // listNumber = incrementListNumber(listNumber, numberOfItemsPlaceInsideFolder); - if (i == (submenuCount + numberOfItemsPlaceInsideFolder)) { - submenuCount += numberOfItemsPlaceInsideFolder; - submenuIndex++; - } - - if (maxHistory <= i) { - break; - } - } -} - -- (void)_addSnippetsToMenu:(NSMenu *)aMenu atPosition:(CMPositionOfSnippets)positionOfSnippets -{ - SnippetsController *snippetsController = [SnippetsController sharedInstance]; - NSArray *snippetFolders = [snippetsController folders]; - if (!snippetFolders || [snippetFolders count] < 1) { - return; - } - - if (CMPositionOfSnippetsBelowClips == positionOfSnippets) { - [aMenu addItem:[NSMenuItem separatorItem]]; - } - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL showLabelsInMenu = [defaults boolForKey:CMPrefShowLabelsInMenuKey]; - - if (showLabelsInMenu) { - NSMenuItem *snippetsLabelItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:NSLocalizedString(@"Snippets", nil) - action:NULL - keyEquivalent:kEmptyString]; - [snippetsLabelItem setEnabled:NO]; - [aMenu addItem:snippetsLabelItem]; - [snippetsLabelItem release], snippetsLabelItem = nil; - } - - NSArray *sortDescriptors = [SnippetsController sortDescriptors]; - - BOOL enabled; - NSUInteger submenuIndex = [aMenu numberOfItems] - 1; - NSUInteger firstIndex = firstIndexOfMenuItems(); - - // NSLog(@"numberOfItems: %d", [aMenu numberOfItems]); - // NSLog(@"submenuIndex: %@", [aMenu itemAtIndex:submenuIndex]); - - for (NSManagedObject *folder in snippetFolders) { - /* Add folder to menu */ - enabled = [[folder valueForKey:kEnabled] boolValue]; - if (!enabled) { - continue; - } - - NSString *folderTitle = [folder valueForKey:kTitle]; - NSMenuItem *subMenuItem = [self _makeSubmenuItemWithTitle:folderTitle]; - [aMenu addItem:subMenuItem]; - submenuIndex++; - - /* Get snippets */ - NSManagedObjectContext *managedObjectContext = [folder managedObjectContext]; - NSEntityDescription *entity = [NSEntityDescription entityForName:kSnippetEntity - inManagedObjectContext:managedObjectContext]; - NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; - [request setEntity:entity]; - [request setSortDescriptors:sortDescriptors]; - - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", kFolder, folder]; - [request setPredicate:predicate]; - - NSError *error = nil; - NSArray *fetchResluts = [managedObjectContext executeFetchRequest:request - error:&error]; - if (!fetchResluts || [fetchResluts count] < 1) { - continue; - } - - /* Add snippets into submenu */ - NSUInteger i = firstIndex; - - for (NSManagedObject *snippet in fetchResluts) { - enabled = [[snippet valueForKey:kEnabled] boolValue]; - if (!enabled) { - continue; - } - -// NSLog(@"snippet: %@", snippet); - - NSMenuItem *menuItem = [self _makeMenuItemForSnippet:snippet withListNumber:i]; - - NSMenu *subMenu = [[aMenu itemAtIndex:submenuIndex] submenu]; - [subMenu addItem:menuItem]; - i++; - } - } - - if (CMPositionOfSnippetsAboveClips == positionOfSnippets) { - [aMenu addItem:[NSMenuItem separatorItem]]; - } -} - -- (NSString *)_menuItemTitleWithString:(NSString *)titleString listNumber:(NSUInteger)listNumber boolean:(BOOL)isMarkWithNumber -{ - if (isMarkWithNumber) { - return [NSString stringWithFormat:MENU_TITLE_FORMAT, listNumber, titleString]; - } - - return titleString; -} - -- (NSMenuItem *)_makeMenuItemForClip:(Clip *)clip withCount:(NSUInteger)count andListNumber:(NSUInteger)listNumber -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL isMarkWithNumber = [defaults boolForKey:CMPrefMenuItemsAreMarkedWithNumbersKey]; - BOOL isShowToolTip = [defaults boolForKey:CMPrefShowToolTipOnMenuItemKey]; - BOOL isShowIcon = [defaults boolForKey:CMPrefShowIconInTheMenuKey]; - BOOL isShowImage = [defaults boolForKey:CMPrefShowImageInTheMenuKey]; - BOOL addNumericKeyEquivalents = [defaults boolForKey:CMPrefAddNumericKeyEquivalentsKey]; - - NSString *keyEquivalent = kEmptyString; - - if (addNumericKeyEquivalents && (count <= kMaxKeyEquivalents)) { - BOOL isStartFromZero = [defaults boolForKey:CMPrefMenuItemsTitleStartWithZeroKey]; - - NSUInteger shortCutNumber = (isStartFromZero) ? count : count + 1; - if (shortCutNumber == kMaxKeyEquivalents) { - shortCutNumber = 0; - } - - keyEquivalent = [NSString stringWithFormat:@"%d", shortCutNumber]; - } - - NSArray *pbTypes = [clip types]; - NSString *primaryPboardType = [clip primaryPboardType]; - NSImage *icon = nil; - - if (pbTypes && [pbTypes count] > 0) { - if (isShowIcon) { - icon = [self _iconForPboardType:primaryPboardType]; - } - } - - /* stringValue */ - NSString *clipString = [clip stringValue]; - NSString *title = trimTitle(clipString); - NSString *titleWithMark = [self _menuItemTitleWithString:title - listNumber:listNumber - boolean:isMarkWithNumber]; - - NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:titleWithMark - action:@selector( selectMenuItem: ) - keyEquivalent:keyEquivalent] autorelease]; - [menuItem setTag:count]; - - /* Tool Tip */ - if (isShowToolTip) { - NSUInteger maxLengthOfToolTip = [defaults integerForKey:CMPrefMaxLengthOfToolTipKey]; - NSUInteger toIndex = ([clipString length] < maxLengthOfToolTip) - ? [clipString length] - : maxLengthOfToolTip; - [menuItem setToolTip:[clipString substringToIndex:toIndex]]; - } - - /* Change Menu Font Size */ - NSAttributedString *attrString = makeAttributedTitle(titleWithMark); - if (attrString) { - [menuItem setAttributedTitle:attrString]; - } - - if ([primaryPboardType isEqualToString:NSTIFFPboardType] - || [primaryPboardType isEqualToString:NSPICTPboardType]) { - [menuItem setTitle:[self _menuItemTitleWithString:@"(Image)" - listNumber:listNumber - boolean:isMarkWithNumber]]; - } - else if ([primaryPboardType isEqualToString:NSPDFPboardType]) { - [menuItem setTitle:[self _menuItemTitleWithString:@"(PDF)" - listNumber:listNumber - boolean:isMarkWithNumber]]; - } - else if ([primaryPboardType isEqualToString:NSFilenamesPboardType] - && [title isEqualToString:kEmptyString]) { - [menuItem setTitle:[self _menuItemTitleWithString:@"(Filenames)" - listNumber:listNumber - boolean:isMarkWithNumber]]; - } - - /* image */ - NSImage *image = clip.image; - if (isShowImage && - image && - ![primaryPboardType isEqualToString:NSFilenamesPboardType]) { - NSInteger thumbnailWidth = [defaults integerForKey:CMPrefThumbnailWidthKey]; - NSInteger thumbnailHeight = [defaults integerForKey:CMPrefThumbnailHeightKey]; - - image = [clip thumbnailOfSize:NSMakeSize(thumbnailWidth, thumbnailHeight)]; - if (image) { - [menuItem setImage:image]; - } - } - - /* icon for menuItem */ - if (icon && !image) { - [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [menuItem setImage:icon]; - } - - return menuItem; -} - -- (NSMenuItem *)_makeMenuItemForSnippet:(NSManagedObject *)snippet withListNumber:(NSUInteger)listNumber -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL isMarkWithNumber = [defaults boolForKey:CMPrefMenuItemsAreMarkedWithNumbersKey]; - BOOL isShowIcon = [defaults boolForKey:CMPrefShowIconInTheMenuKey]; - // BOOL addNumericKeyEquivalents = [defaults boolForKey:CMPrefAddNumericKeyEquivalentsKey]; - - NSString *keyEquivalent = kEmptyString; - // if (addNumericKeyEquivalents) { - // BOOL isStartFromZero = [defaults boolForKey:CMPrefMenuItemsTitleStartWithZeroKey]; - // NSUInteger shortCutNumber = (isStartFromZero) - // ? listNumber - // : ((listNumber == kMaxKeyEquivalents) ? 0 : listNumber); - // - // if (listNumber <= kMaxKeyEquivalents) { - // keyEquivalent = [NSString stringWithFormat:@"%d", shortCutNumber]; - // } - // } - - NSImage *icon = nil; - - if (isShowIcon) { - icon = [self _iconForSnippet]; - } - - /* stringValue */ - NSString *title = trimTitle([snippet valueForKey:kTitle]); - NSString *titleWithMark = [self _menuItemTitleWithString:title - listNumber:listNumber - boolean:isMarkWithNumber]; - - NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:titleWithMark - action:@selector( selectSnippetMenuItem: ) - keyEquivalent:keyEquivalent] autorelease]; - [menuItem setRepresentedObject:snippet]; - // [menuItem setTag:count]; - [menuItem setToolTip:[snippet valueForKey:kContent]]; - - /* Change Menu Font Size */ - NSAttributedString *attrString = makeAttributedTitle(titleWithMark); - if (attrString) { - [menuItem setAttributedTitle:attrString]; - } - - /* icon for menuItem */ - if (icon) { - [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [menuItem setImage:icon]; - } - - return menuItem; -} - -- (NSMenuItem *)_makeSubmenuItemWithCount:(NSUInteger)count start:(NSUInteger)start end:(NSUInteger)end numberOfItems:(NSUInteger)numberOfItems -{ - if (start == 0) { - count--; - } - - NSUInteger lastNumber = count + numberOfItems; - // NSLog(@"count: %d, start:%d, end:%d, lastNumber: %d", count, start, end, lastNumber); - - if (end < lastNumber) { - lastNumber = end; - } - - NSString *menuItemTitle = [NSString stringWithFormat:@"%d - %d", - count + 1, - lastNumber]; - return [self _makeSubmenuItemWithTitle:menuItemTitle]; -} - -- (NSMenuItem *)_makeSubmenuItemWithTitle:(NSString *)title -{ - // NSLog(@"_makeSubmenu"); - - NSMenu *submenu = [[NSMenu allocWithZone:[NSMenu menuZone]] init]; - NSMenuItem *submenuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:title - action:NULL - keyEquivalent:kEmptyString] autorelease]; - [submenuItem setSubmenu:submenu]; - [submenu release], submenu = nil; - - NSAttributedString *attrString = makeAttributedTitle(title); - if (attrString) { - [submenuItem setAttributedTitle:attrString]; - } - - /* icon */ - if ([[NSUserDefaults standardUserDefaults] boolForKey:CMPrefShowIconInTheMenuKey] - && folderIcon) { - // [folderIcon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [submenuItem setImage:folderIcon]; - } - - return submenuItem; -} - -- (NSMenuItem *)_makeMenuItemWithTitle:(NSString *)itemName action:(SEL)anAction -{ - NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:itemName - action:anAction - keyEquivalent:kEmptyString] autorelease]; - - NSAttributedString *attrString = makeAttributedTitle(itemName); - if (attrString) { - [menuItem setAttributedTitle:attrString]; - } - - return menuItem; -} - -//- (NSMenuItem *)_makeSortMenuItem -//{ -// NSString *title = @"Sort"; -// BOOL isAscending = NO; -// -// NSCellStateValue ascMenuItemState; -// NSCellStateValue descMenuItemState; -// -// if (isAscending) { -// ascMenuItemState = NSOnState; -// descMenuItemState = NSOffState; -// } -// else { -// ascMenuItemState = NSOffState; -// descMenuItemState = NSOnState; -// } -// -// NSMenu *submenu = [[NSMenu allocWithZone:[NSMenu menuZone]] init]; -// -// NSMenuItem *ascMenuItem = [self _makeMenuItemWithTitle:@"Ascending" action:NULL]; -// [ascMenuItem setState:ascMenuItemState]; -// [submenu addItem:ascMenuItem]; -// -// NSMenuItem *descMenuItem = [self _makeMenuItemWithTitle:@"Descending" action:NULL]; -// [descMenuItem setState:descMenuItemState]; -// [submenu addItem:descMenuItem]; -// -// NSMenuItem *submenuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] -// initWithTitle:title -// action:NULL -// keyEquivalent:kEmptyString] autorelease]; -// [submenuItem setSubmenu:submenu]; -// [submenu release], submenu = nil; -// -// NSAttributedString *attrString = makeAttributedTitle(title); -// if (attrString) { -// [submenuItem setAttributedTitle:attrString]; -// } -// -// return submenuItem; -//} - -#pragma mark - Menu Pop Up - - -- (NSEvent *)_makeEventFromCurrentEvent:(NSEvent *)currentEvent mousePoint:(NSPoint)mousePoint windowNumber:(NSInteger)windowNumber -{ - return [NSEvent otherEventWithType:[currentEvent type] - location:mousePoint - modifierFlags:[currentEvent modifierFlags] - timestamp:[currentEvent timestamp] - windowNumber:windowNumber - context:[currentEvent context] - subtype:[currentEvent subtype] - data1:[currentEvent data1] - data2:[currentEvent data2]]; -} - -- (NSEvent *)_makeEventForActionFromCurrentEvent:(NSEvent *)currentEvent mousePoint:(NSPoint)mousePoint windowNumber:(NSInteger)windowNumber -{ - NSEvent *newEvent; - - switch ([currentEvent type]) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSKeyDown: - /* default behavior */ - newEvent = [NSEvent otherEventWithType:NSApplicationDefined - location:mousePoint - modifierFlags:0 - timestamp:0 - windowNumber:windowNumber - context:nil - subtype:0 - data1:0 - data2:0]; - break; - default: - /* not reach here? */ - newEvent = [NSEvent otherEventWithType:[currentEvent type] - location:mousePoint - modifierFlags:[currentEvent modifierFlags] - timestamp:[currentEvent timestamp] - windowNumber:windowNumber - context:[currentEvent context] - subtype:[currentEvent subtype] - data1:[currentEvent data1] - data2:[currentEvent data2]]; - break; - } - - return newEvent; -} - -- (NSMenu *)_makeHistoryMenu -{ - NSMenu *newMenu = [[[NSMenu allocWithZone:[NSMenu menuZone]] - initWithTitle:kHistoryMenuIdentifier] autorelease]; - [newMenu setDelegate:self]; - [self _addClipsToMenu:newMenu]; - - return newMenu; -} - -- (NSMenu *)_makeSnippetsMenu -{ - // NSLog(@"_makeSnippetsMenu"); - - NSMenu *newMenu = [[[NSMenu allocWithZone:[NSMenu menuZone]] - initWithTitle:kSnippetsMenuIdentifier] autorelease]; - [newMenu setDelegate:self]; - [self _addSnippetsToMenu:newMenu atPosition:CMPositionOfSnippetsNone]; - - return newMenu; -} - -- (NSMenu *)_makeActionMenu -{ - // NSLog(@"_makeActionMenu"); - - NSMenu *newMenu = [[[NSMenu allocWithZone:[NSMenu menuZone]] - initWithTitle:kActionMenuIdentifier] autorelease]; - [newMenu setDelegate:self]; - - NSArray *actionNodes = [[ActionController sharedInstance] actionNodes]; - for (ActionNode *node in actionNodes) { - // NSLog(@"node: %@", [node nodeTitle]); - - NSMenuItem *newActionMenuItem = nil; - if (newActionMenuItem = [self _makeActionMenuItemFromNode:node]) { - [newMenu addItem:newActionMenuItem]; - } - } - - // [newMenu addItem:[NSMenuItem separatorItem]]; - // - // NSMenuItem *menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:NSLocalizedString(@"Remove", nil) - // action:@selector(selectAction:) - // keyEquivalent:kEmptyString]; - // [menuItem setRepresentedObject:[NSString stringWithString:@"Remove"]]; - // [newMenu addItem:menuItem]; - // [menuItem release], menuItem = nil; - - return newMenu; -} - -- (NSMenuItem *)_makeActionMenuItemFromNode:(ActionNode *)node -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - BOOL isShowIcon = [defaults boolForKey:CMPrefShowIconInTheMenuKey]; - - if ([node isLeaf]) { - NSMenuItem *actionMenuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:[node nodeTitle] - action:@selector( selectActionMenuItem: ) - keyEquivalent:kEmptyString] autorelease]; - - NSDictionary *action = [node action]; - - if (action) { - // if (![self _isAppropriateAction:action]) { - // return nil; - // } - - if (!CMIsPerformableAction(action)) { - return nil; - } - - [actionMenuItem setRepresentedObject:action]; - - /* Tool Tip */ - BOOL isShowToolTip = [defaults boolForKey:CMPrefShowToolTipOnMenuItemKey]; - if (isShowToolTip) { - NSDictionary *toolTips = [[[ActionController sharedInstance] builtInActionController] valueForKey:@"toolTips"]; - NSString *actionName = [action objectForKey:@"name"]; - NSString *toolTipOfAction = nil; - if (toolTipOfAction = [toolTips objectForKey:actionName]) { - [actionMenuItem setToolTip:toolTipOfAction]; - } - } - } - - /* icon for menuItem */ - if (isShowIcon) { - NSString *type = [action objectForKey:@"type"]; - if ([type isEqualToString:CMBuiltinActionTypeKey] && actionIcon) { - [actionMenuItem setImage:actionIcon]; - } - else if ([type isEqualToString:CMJavaScriptActionTypeKey] && javaScriptIcon) { - [actionMenuItem setImage:javaScriptIcon]; - } - } - - return actionMenuItem; - } - else { - NSMenu *subMenu = [[[NSMenu allocWithZone:[NSMenu menuZone]] init] autorelease]; - - for (ActionNode *childNode in [node children]) { - NSMenuItem *newActionMenuItem = nil; - if (newActionMenuItem = [self _makeActionMenuItemFromNode:childNode]) { - [subMenu addItem:newActionMenuItem]; - } - } - - if ([subMenu numberOfItems] == 0) { - return nil; - } - - NSMenuItem *folderMenuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:[node nodeTitle] - action:NULL - keyEquivalent:kEmptyString] autorelease]; - [folderMenuItem setSubmenu:subMenu]; - - /* icon for menuItem */ - if (isShowIcon && folderIcon) { - // [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [folderMenuItem setImage:folderIcon]; - } - - return folderMenuItem; - } -} - -//- (BOOL)_isAppropriateAction:(NSDictionary *)action -//{ -//// NSLog(@"action: %@", action); -// -// NSString *name = [action objectForKey:@"name"]; -// NSString *type = [action objectForKey:@"type"]; -//// if ([type isEqualToString:CMBuiltinActionTypeKey]) { -//// return YES; -//// } -// -// ActionController *actionController = [ActionController sharedInstance]; -// NSInteger tag = [actionController selectedClipTag]; -// Clip *clip = [[[ClipsController sharedInstance] clips] objectAtIndex:tag]; -// NSArray *selectedClipTypes = [clip types]; -// -//// NSLog(@"selectedClipTypes: %@", selectedClipTypes); -// -//// if ([selectedClipTypes containsObject:NSStringPboardType]) { -//// return YES; -//// } -// -// if ([type isEqualToString:CMBuiltinActionTypeKey]) { -// NSDictionary *builtInActions = [[actionController builtInActionController] valueForKey:@"actions"]; -// NSDictionary *builtInAction = [builtInActions objectForKey:name]; -//// NSLog(@"builtInAction: %@", builtInAction); -// -// for (NSString *key in [builtInAction objectForKey:@"types"]) { -//// NSLog(@"key: %@", key); -// if ([selectedClipTypes containsObject:key]) { -// return YES; -// } -// } -// } -// else if ([type isEqualToString:CMJavaScriptActionTypeKey]) { -// if ([selectedClipTypes containsObject:NSStringPboardType]) { -// return YES; -// } -// } -// -// return NO; -//} - -#pragma mark - StatusItem - - -- (void)_changeStatusItem:(NSUInteger)tag -{ - [self _removeStatusItem]; - - NSString *statusMenuIconName; - - switch (tag) { - case 1: - statusMenuIconName = STATUS_MENU_ICON; - break; - case 2: - statusMenuIconName = @"StatusMenuIconFirst"; - break; - case 3: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors1-bw-left"; - break; - case 4: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors1-bw-right"; - break; - case 5: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors1-color-left"; - break; - case 6: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors1-color-right"; - break; - case 7: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-diagonal-bw"; - break; - case 8: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-diagonal-color"; - break; - case 9: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors2-bw-left"; - break; - case 10: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors2-bw-right"; - break; - case 11: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors2-color-left"; - break; - case 12: - statusMenuIconName = @"StatusMenuIconByDaveUlrich-scissors2-color-right"; - break; - case 13: - statusMenuIconName = @"StatusMenuIconBySuphiAksoy"; - break; - default: - /* default filename */ - statusMenuIconName = STATUS_MENU_ICON; - break; - } - - NSString *pressedStatusMenuIconName = [statusMenuIconName stringByAppendingString:STATUS_MENU_ICON_POSTFIX]; - - NSImage *statusIcon = [NSImage imageNamed: - [statusMenuIconName stringByAppendingString:STATUS_MENU_ICON_FILE_EXTENSION]]; - if (statusIcon == nil) { - statusIcon = [NSImage imageNamed:STATUS_MENU_ICON]; - } - - NSImage *statusIconPressed = [NSImage imageNamed: - [pressedStatusMenuIconName stringByAppendingString:STATUS_MENU_ICON_FILE_EXTENSION]]; - if (statusIconPressed == nil) { - statusIconPressed = statusIcon; - } - - NSString *toolTipLabel = [NSString stringWithFormat:@"%@ %@", kApplicationName, self.shortVersion]; - - NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; - - statusItem = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain]; - [statusItem setImage:statusIcon]; - [statusItem setAlternateImage:statusIconPressed]; - [statusItem setHighlightMode:YES]; - [statusItem setToolTip:toolTipLabel]; - - if (clipMenu) { - - [statusItem setMenu:clipMenu]; - } -} - -- (void)_removeStatusItem -{ - if (statusItem) { - [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; - [statusItem release], statusItem = nil; - } -} - -- (void)_refreshStatusItem -{ - if (statusItem) { - [statusItem setMenu:clipMenu]; - } -} - -#pragma mark - Icon - - -- (NSImage *)_iconForPboardType:(NSString *)type -{ - if (!type) { - return nil; - } - - NSString *key = [self _iconCacheKeyForType:type]; - if (!key) { - return nil; - } - - NSImage *icon = [self valueForKey:key]; - - return icon; -} - -- (NSString *)_iconCacheKeyForType:(NSString *)type -{ - if (!type) { - return nil; - } - - // NSRange range = [type rangeOfString:@"NS"]; - // NSMutableString *key = [NSMutableString stringWithString:type]; - // [key replaceCharactersInRange:range withString:@"iconFor"]; - // - // return key; - - if ([type isEqualToString:NSStringPboardType]) { - return @"iconForStringPboardType"; - } - else if ([type isEqualToString:NSRTFPboardType]) { - return @"iconForRTFPboardType"; - } - else if ([type isEqualToString:NSRTFDPboardType]) { - return @"iconForRTFDPboardType"; - } - else if ([type isEqualToString:NSPDFPboardType]) { - return @"iconForPDFPboardType"; - } - else if ([type isEqualToString:NSFilenamesPboardType]) { - return @"iconForFilenamesPboardType"; - } - else if ([type isEqualToString:NSURLPboardType]) { - return @"iconForURLPboardType"; - } - else if ([type isEqualToString:NSTIFFPboardType] || [type isEqualToString:NSPICTPboardType]) { - return @"iconForTIFFPboardType"; - } - - return nil; -} - -- (NSImage *)_iconForSnippet -{ - return [self valueForKey:@"snippetIcon"]; -} - -- (void)_cacheIconForTypes -{ - NSArray *types = [Clip availableTypes]; - for (NSString *type in types) { - NSImage *icon = [Clip fileTypeIconForPboardType:type]; - if (icon) { - // NSRange range = [type rangeOfString:@"NS"]; - // NSMutableString *key = [NSMutableString stringWithString:type]; - // [key replaceCharactersInRange:range withString:@"iconFor"]; - - NSString *key = [self _iconCacheKeyForType:type]; - if (key) { - [self setValue:icon forKey:key]; - } - } - } -} - -- (void)_cacheFolderIcon -{ - // [self _resetMenuIconSize]; - - NSImage *icon = [[NSWorkspace sharedWorkspace] - iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)]; - [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [self setFolderIcon:icon]; -} - -- (void)_cacheOpenFolderIcon -{ - NSImage *icon = [[NSWorkspace sharedWorkspace] - iconForFileType:NSFileTypeForHFSTypeCode(kOpenFolderIcon)]; - [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [self setOpenFolderIcon:icon]; -} - -- (void)_cacheActionIcon -{ - NSString *imageResource = nil; - switch (menuIconSize) { - case SMALL_ICON_SIZE: - imageResource = @"ActionIcon"; - break; - case LARGE_ICON_SIZE: - imageResource = @"ActionIconLarge"; - break; - default: - imageResource = @"ActionIconLarge"; - break; - } - - NSString *fileName = [[NSBundle mainBundle] pathForImageResource:imageResource]; - if (fileName) { - [self setActionIcon:[[[NSImage alloc] initWithContentsOfFile:fileName] autorelease]]; - } -} - -- (void)_cacheJavaScriptIcon -{ - NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFileType:@"js"]; - [icon setSize:NSMakeSize(menuIconSize,menuIconSize)]; - [self setJavaScriptIcon:icon]; -} - -- (void)_cacheSnippetIcon -{ - NSImage *icon = [[NSWorkspace sharedWorkspace] - iconForFileType:NSFileTypeForHFSTypeCode(kClippingTextTypeIcon)]; - [icon setSize:NSMakeSize(menuIconSize, menuIconSize)]; - [self setSnippetIcon:icon]; -} - -- (void)_resetMenuIconSize -{ - NSUInteger iconSize = [[NSUserDefaults standardUserDefaults] integerForKey:CMPrefMenuIconSizeKey]; - [self setMenuIconSize:iconSize]; -} - -- (void)_resetIconCaches -{ - if ([[NSUserDefaults standardUserDefaults] boolForKey:CMPrefShowIconInTheMenuKey]) { - [self _cacheIconForTypes]; - [self _resetMenuIconSize]; - - [self _cacheFolderIcon]; - [self _cacheOpenFolderIcon]; - [self _cacheActionIcon]; - [self _cacheJavaScriptIcon]; - [self _cacheSnippetIcon]; - } -} - -- (void)_unhighlightMenuItem -{ - [highlightedMenuItem setImage:folderIcon]; - [self setHighlightedMenuItem:nil]; -} - -#pragma mark - Notification - - -- (void)_handlePreferencePanelWillClose:(NSNotification *)aNotification -{ - [self _resetIconCaches]; - - NSUInteger showStatusItem = [[NSUserDefaults standardUserDefaults] - integerForKey:CMPrefShowStatusItemKey]; - if (showStatusItem) { - [self updateStatusMenu]; - } -} - -- (void)_handleSnippetEditorWillClose:(NSNotification *)aNotification -{ - [self updateStatusMenu]; -} - -- (void)_handleStatusMenuWillUpdate:(NSNotification *)aNotification -{ - [self updateStatusMenu]; -} - -@end - diff --git a/Source/NaoAdditions/NMLoginItems.h b/Source/NaoAdditions/NMLoginItems.h deleted file mode 100644 index 7809201..0000000 --- a/Source/NaoAdditions/NMLoginItems.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// NMLoginItems.m -// -// Some code copyright 2009 Naotaka Morimoto. -// -// Much of this code was taken and adapted from GTMLoginItems of Google -// Toolbox for Mac and QSBPreferenceWindowController of Quick Search Box -// for the Mac by Google Inc. -// This code is also released under Apache License, Version 2.0. -// - -// -// Copyright (c) 2008-2009 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#import - - -@interface NMLoginItems : NSObject - -/// Check if the given path is in the current user's Login Items -// -// Args: -// path: path to the application -// -// Returns: -// YES if the path is in the Login Items -// -+ (BOOL)pathInLoginItems:(NSString *)path; - -/// Add the given path to the current user's Login Items. Does nothing if the -/// path is already there. -// -// Args: -// path: path to add -// hide: Set to YES to have the item launch hidden -// -+ (void)addPathToLoginItems:(NSString *)path hide:(BOOL)hide; - -/// Remove the given path from the current user's Login Items. Does nothing if -/// the path is not there. -// -// Args: -// path: the path to remove -// -+ (void)removePathFromLoginItems:(NSString *)path; - -@end diff --git a/Source/NaoAdditions/NMLoginItems.m b/Source/NaoAdditions/NMLoginItems.m deleted file mode 100644 index 4ecbbe0..0000000 --- a/Source/NaoAdditions/NMLoginItems.m +++ /dev/null @@ -1,165 +0,0 @@ -// -// NMLoginItems.m -// -// Some code copyright 2009 Naotaka Morimoto. -// -// Much of this code was taken and adapted from GTMLoginItems of Google -// Toolbox for Mac and QSBPreferenceWindowController of Quick Search Box -// for the Mac by Google Inc. -// This code is also released under Apache License, Version 2.0. -// - -// -// Copyright (c) 2008-2009 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#import "NMLoginItems.h" - -#ifndef kLSSharedFileListLoginItemHidden // defined on Mac OS X 10.6 -#define kLSSharedFileListLoginItemHidden CFSTR("com.apple.loginitem.HideOnLaunch") -#endif - -@implementation NMLoginItems - -+ (BOOL)pathInLoginItems:(NSString *)path -{ - if (!path) { - return NO; - } - - LSSharedFileListRef loginItemList = LSSharedFileListCreate(NULL, - kLSSharedFileListSessionLoginItems, - NULL); - if (!loginItemList) { - return NO; - } - - UInt32 snapshotSeed; - NSArray *loginItems = (NSArray *)LSSharedFileListCopySnapshot(loginItemList, &snapshotSeed); - if (!loginItems) { - return NO; - } - - NSURL *url = [NSURL fileURLWithPath:path]; - BOOL found = NO; - - for (id item in loginItems) { - CFURLRef itemURL; - - if (LSSharedFileListItemResolve((LSSharedFileListItemRef)item, 0, &itemURL, NULL) == noErr) { - if ([url isEqual:(NSURL *)itemURL]) { - found = YES; - } - } - - CFRelease(itemURL); - - if (found) { - break; - } - } - - [loginItems release], loginItems = nil; - CFRelease(loginItemList); - - return found; -} - -+ (void)addPathToLoginItems:(NSString *)path hide:(BOOL)hide -{ - if (!path) { - return; - } - - LSSharedFileListRef loginItemList = LSSharedFileListCreate(NULL, - kLSSharedFileListSessionLoginItems, - NULL); - if (!loginItemList) { - return; - } - - NSURL *url = [NSURL fileURLWithPath:path]; - NSDictionary *propertiesToSet = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:hide] - forKey:(id)kLSSharedFileListLoginItemHidden]; - - LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItemList, - kLSSharedFileListItemLast, - NULL, - NULL, - (CFURLRef)url, - (CFDictionaryRef)propertiesToSet, - NULL); - if (item) { - CFRelease(item); - } - - CFRelease(loginItemList); -} - -+ (void)removePathFromLoginItems:(NSString *)path -{ - if (!path) { - return; - } - - LSSharedFileListRef loginItemList = LSSharedFileListCreate(NULL, - kLSSharedFileListSessionLoginItems, - NULL); - if (!loginItemList) { - return; - } - - UInt32 snapshotSeed; - NSArray *loginItems = (NSArray *)LSSharedFileListCopySnapshot(loginItemList, &snapshotSeed); - if (!loginItems) { - return; - } - - NSURL *url = [NSURL fileURLWithPath:path]; - - for (id item in loginItems) { - CFURLRef itemURL; - - if (LSSharedFileListItemResolve((LSSharedFileListItemRef)item, 0, &itemURL, NULL) == noErr) { - if ([url isEqual:(NSURL *)itemURL]) { - OSStatus status = LSSharedFileListItemRemove(loginItemList, (LSSharedFileListItemRef)item); - if (status) { - NSLog(@"Unable to remove %@ from open at login (%d)", itemURL, status); - } - } - } - - CFRelease(itemURL); - } - - [loginItems release], loginItems = nil; - CFRelease(loginItemList); -} - -@end diff --git a/Source/NaoAdditions/NSIndexPath+NaoAdditions.h b/Source/NaoAdditions/NSIndexPath+NaoAdditions.h deleted file mode 100644 index 31e6b1e..0000000 --- a/Source/NaoAdditions/NSIndexPath+NaoAdditions.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// NSIndexPath+NaoAdditions.h -// ClipMenu -// -// Created by naotaka on 08/10/19. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface NSIndexPath (MyExtensions) - -// get us the final piece of the index path, i.e, the one that tells -// us were this path fits among its siblings - -- (NSUInteger)lastIndex; - -// answer whether receiver is the ancestor (other is a descendant) - -- (BOOL)isAncestorOfIndexPath:(NSIndexPath *)other; - -// answer whether receiver has same immediate parent as other - -- (BOOL)isSiblingOfIndexPath:(NSIndexPath *)other; - -// find a common ancestor in the tree controller -// return nil if no common ancestor -// these may not be necessary - -- (NSIndexPath *)firstCommonAncestorWithIndexPath:(NSIndexPath *)other; -+ (NSIndexPath *)firstCommonAncestorAmongIndexPaths:(NSArray *)otherPaths; - -@end - - -@interface NSIndexPath (NaoAdditions) -- (NSIndexPath *)parentPathIndex; -- (NSIndexPath *)incrementLastNodeIndex; - -@end diff --git a/Source/NaoAdditions/NSIndexPath+NaoAdditions.m b/Source/NaoAdditions/NSIndexPath+NaoAdditions.m deleted file mode 100644 index 31d4392..0000000 --- a/Source/NaoAdditions/NSIndexPath+NaoAdditions.m +++ /dev/null @@ -1,124 +0,0 @@ -// -// NSIndexPath+NaoAdditions.m -// ClipMenu -// -// Created by naotaka on 08/10/19. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "NSIndexPath+NaoAdditions.h" -//#import "NSTreeController_Extensions.h" - -@implementation NSIndexPath (MyExtensions) - -- (NSUInteger)lastIndex; -{ - return [self indexAtPosition: [self length] - 1]; -} - -- (BOOL)isAncestorOfIndexPath:(NSIndexPath *)other; // i.e., other descends from receiver -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 < l2 ) { - NSUInteger elems1[l1], elems2[l2], i; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < l1; ++i ) - if ( elems1[i] != elems2[i] ) - return NO; - - return YES; - } - - return NO; -} - -- (BOOL)isSiblingOfIndexPath:(NSIndexPath *)other; // i.e., other has same parent as receiver -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 == l2 ) { - NSUInteger elems1[l1], elems2[l2], i; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < l1 - 1; ++i ) - if ( elems1[i] != elems2[i] ) - return NO; - - return YES; - } - - return NO; -} - -- (NSIndexPath *)firstCommonAncestorWithIndexPath:(NSIndexPath *)other; -{ - NSUInteger l1 = [self length], l2 = [other length]; - - if ( l1 && l2 ) { - NSUInteger elems1[l1], elems2[l2], i, min = ( l1 < l2 ) ? l1-1 : l2-1; - - [self getIndexes: elems1]; - [other getIndexes: elems2]; - - for ( i = 0; i < min; ++i ) - if ( elems1[i] != elems2[i] ) - break; - - return i ? [NSIndexPath indexPathWithIndexes: elems1 length: i] : nil; - } - - return nil; -} - -+ (NSIndexPath *)firstCommonAncestorAmongIndexPaths:(NSArray *)paths; -{ - if ( [paths count] < 1 ) return nil; - - NSEnumerator *pathEnumerator = [paths objectEnumerator]; - NSIndexPath *path1 = [pathEnumerator nextObject], *path, *result = [path1 indexPathByRemovingLastIndex]; - - while ( path = [pathEnumerator nextObject] ) { - NSIndexPath *candidate = [path firstCommonAncestorWithIndexPath: path1]; - - if ( !candidate ) return nil; - - if ( [candidate length] < [result length] ) result = candidate; - } - - return result; -} - -@end - - -@implementation NSIndexPath (NaoAdditions) - -- (NSIndexPath *)parentPathIndex -{ - if ([self length] > 1) { - return [self indexPathByRemovingLastIndex]; - } - - return [NSIndexPath indexPathWithIndex:[self lastIndex]]; -} - -- (NSIndexPath *)incrementLastNodeIndex -{ - NSInteger lastNodeIndex = [self lastIndex]; - NSIndexPath *tempPath = [self indexPathByRemovingLastIndex]; - NSInteger insertionIndex = lastNodeIndex + 1; - - NSAssert(insertionIndex >= 0, @"The insertionIndex must be a positive number"); - - return (tempPath) - ? [tempPath indexPathByAddingIndex:insertionIndex] - : [NSIndexPath indexPathWithIndex:insertionIndex]; -} - -@end diff --git a/Source/NaoAdditions/NSString+NaoAdditions.h b/Source/NaoAdditions/NSString+NaoAdditions.h deleted file mode 100644 index b63e047..0000000 --- a/Source/NaoAdditions/NSString+NaoAdditions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSStringAdditions.h -// -// Created by Naotaka Morimoto on 07/11/03. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface NSString (NaoAdditions) - -- (NSString *)strip; -- (NSString *)entityReference; - -@end diff --git a/Source/NaoAdditions/NSString+NaoAdditions.m b/Source/NaoAdditions/NSString+NaoAdditions.m deleted file mode 100644 index 51d7df2..0000000 --- a/Source/NaoAdditions/NSString+NaoAdditions.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// NSString+NaoAdditions.m -// -// Created by Naotaka Morimoto on 07/11/03. -// Copyright 2007 Naotaka Morimoto. All rights reserved. -// - -#import "NSString+NaoAdditions.h" - -#define EMPTY_STRING @"" - - -@implementation NSString (NaoAdditions) - -- (NSString *)strip -{ - return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; -} - -- (NSString *)entityReference -{ - if (!self || [self isEqualToString:EMPTY_STRING]) { - return self; - } - - NSString *convertedString; - convertedString = (NSString *)CFBridgingRelease(CFXMLCreateStringByEscapingEntities(NULL, - (__bridge CFStringRef)self,NULL)); - return convertedString; -} - -@end diff --git a/Source/NaoAdditions/NSTreeController+NaoAdditions.h b/Source/NaoAdditions/NSTreeController+NaoAdditions.h deleted file mode 100644 index a6c2923..0000000 --- a/Source/NaoAdditions/NSTreeController+NaoAdditions.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// NSTreeController+NaoAdditions.h -// -// Created by Naotaka Morimoto on 08/02/02. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import -#import "NSTreeController_Extensions.h" -#import "NSIndexPath+NaoAdditions.h" - - diff --git a/Source/PTHotKeys/PTHotKey.h b/Source/PTHotKeys/PTHotKey.h deleted file mode 100644 index c875879..0000000 --- a/Source/PTHotKeys/PTHotKey.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// PTHotKey.h -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// -// Contributors: -// Andy Kim - -#import -#import -#import "PTKeyCombo.h" - -@interface PTHotKey : NSObject -{ - NSString* mIdentifier; - NSString* mName; - PTKeyCombo* mKeyCombo; - id mTarget; - SEL mAction; - - NSUInteger mCarbonHotKeyID; - EventHotKeyRef mCarbonEventHotKeyRef; -} - -- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo; -- (id)init; - -- (void)setIdentifier: (id)ident; -- (id)identifier; - -- (void)setName: (NSString*)name; -- (NSString*)name; - -- (void)setKeyCombo: (PTKeyCombo*)combo; -- (PTKeyCombo*)keyCombo; - -- (void)setTarget: (id)target; -- (id)target; -- (void)setAction: (SEL)action; -- (SEL)action; - -- (NSUInteger)carbonHotKeyID; -- (void)setCarbonHotKeyID: (NSUInteger)hotKeyID; - -- (EventHotKeyRef)carbonEventHotKeyRef; -- (void)setCarbonEventHotKeyRef:(EventHotKeyRef)hotKeyRef; - -- (void)invoke; - -@end diff --git a/Source/PTHotKeys/PTHotKey.m b/Source/PTHotKeys/PTHotKey.m deleted file mode 100644 index 7c16e05..0000000 --- a/Source/PTHotKeys/PTHotKey.m +++ /dev/null @@ -1,136 +0,0 @@ -// -// PTHotKey.m -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// - -#import "PTHotKey.h" - -#import "PTHotKeyCenter.h" -#import "PTKeyCombo.h" - -@implementation PTHotKey - -- (id)init -{ - return [self initWithIdentifier: nil keyCombo: nil]; -} - -- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo -{ - self = [super init]; - - if( self ) - { - [self setIdentifier: identifier]; - [self setKeyCombo: combo]; - } - - return self; -} - -- (void)dealloc -{ - [mIdentifier release]; - [mName release]; - [mKeyCombo release]; - - [super dealloc]; -} - -- (NSString*)description -{ - return [NSString stringWithFormat: @"<%@: %@, %@>", NSStringFromClass( [self class] ), [self identifier], [self keyCombo]]; -} - -#pragma mark - - -- (void)setIdentifier: (id)ident -{ - [ident retain]; - [mIdentifier release]; - mIdentifier = ident; -} - -- (id)identifier -{ - return mIdentifier; -} - -- (void)setKeyCombo: (PTKeyCombo*)combo -{ - if( combo == nil ) - combo = [PTKeyCombo clearKeyCombo]; - - [combo retain]; - [mKeyCombo release]; - mKeyCombo = combo; -} - -- (PTKeyCombo*)keyCombo -{ - return mKeyCombo; -} - -- (void)setName: (NSString*)name -{ - [name retain]; - [mName release]; - mName = name; -} - -- (NSString*)name -{ - return mName; -} - -- (void)setTarget: (id)target -{ - mTarget = target; -} - -- (id)target -{ - return mTarget; -} - -- (void)setAction: (SEL)action -{ - mAction = action; -} - -- (SEL)action -{ - return mAction; -} - -- (NSUInteger)carbonHotKeyID -{ - return mCarbonHotKeyID; -} - -- (void)setCarbonHotKeyID: (NSUInteger)hotKeyID; -{ - mCarbonHotKeyID = hotKeyID; -} - -- (EventHotKeyRef)carbonEventHotKeyRef -{ - return mCarbonEventHotKeyRef; -} - -- (void)setCarbonEventHotKeyRef: (EventHotKeyRef)hotKeyRef -{ - mCarbonEventHotKeyRef = hotKeyRef; -} - -#pragma mark - - -- (void)invoke -{ - [mTarget performSelector: mAction withObject: self]; -} - -@end diff --git a/Source/PTHotKeys/PTHotKeyCenter.h b/Source/PTHotKeys/PTHotKeyCenter.h deleted file mode 100644 index 4b09bf9..0000000 --- a/Source/PTHotKeys/PTHotKeyCenter.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// PTHotKeyCenter.h -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// -// Contributors: -// Quentin D. Carnicelli -// Finlay Dobbie -// Vincent Pottier -// Andy Kim - -#import - -@class PTHotKey; - -@interface PTHotKeyCenter : NSObject -{ - NSMutableDictionary* mHotKeys; //Keys are carbon hot key IDs - BOOL mEventHandlerInstalled; - UInt32 mHotKeyCount; // Used to assign new hot key ID -} - -+ (PTHotKeyCenter *)sharedCenter; - -- (BOOL)registerHotKey: (PTHotKey*)hotKey; -- (void)unregisterHotKey: (PTHotKey*)hotKey; - -- (NSArray*)allHotKeys; -- (PTHotKey*)hotKeyWithIdentifier: (id)ident; - -- (void)sendEvent: (NSEvent*)event; - -@end diff --git a/Source/PTHotKeys/PTHotKeyCenter.m b/Source/PTHotKeys/PTHotKeyCenter.m deleted file mode 100644 index 2e510e6..0000000 --- a/Source/PTHotKeys/PTHotKeyCenter.m +++ /dev/null @@ -1,267 +0,0 @@ -// -// PTHotKeyCenter.m -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// - -#import "PTHotKeyCenter.h" -#import "PTHotKey.h" -#import "PTKeyCombo.h" -#import - -@interface PTHotKeyCenter (Private) -- (PTHotKey*)_hotKeyForCarbonHotKey: (EventHotKeyRef)carbonHotKey; -- (PTHotKey*)_hotKeyForCarbonHotKeyID: (EventHotKeyID)hotKeyID; - -- (void)_updateEventHandler; -- (void)_hotKeyDown: (PTHotKey*)hotKey; -- (void)_hotKeyUp: (PTHotKey*)hotKey; -static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon ); -@end - -@implementation PTHotKeyCenter - -static PTHotKeyCenter *_sharedHotKeyCenter = nil; - -+ (PTHotKeyCenter*)sharedCenter -{ - if( _sharedHotKeyCenter == nil ) - { - _sharedHotKeyCenter = [[self alloc] init]; - } - - return _sharedHotKeyCenter; -} - -- (id)init -{ - self = [super init]; - - if( self ) - { - mHotKeys = [[NSMutableDictionary alloc] init]; - } - - return self; -} - -- (void)dealloc -{ - [mHotKeys release]; - [super dealloc]; -} - -#pragma mark - - -- (BOOL)registerHotKey: (PTHotKey*)hotKey -{ - OSStatus err; - EventHotKeyID hotKeyID; - EventHotKeyRef carbonHotKey; - - if( [[self allHotKeys] containsObject: hotKey] == YES ) - [self unregisterHotKey: hotKey]; - - if( [[hotKey keyCombo] isValidHotKeyCombo] == NO ) - return YES; - - hotKeyID.signature = 'PTHk'; - hotKeyID.id = ++mHotKeyCount; - - err = RegisterEventHotKey( (SInt32)[[hotKey keyCombo] keyCode], - (UInt32)[[hotKey keyCombo] modifiers], - hotKeyID, - GetEventDispatcherTarget(), - 0, - &carbonHotKey ); - - if( err ) - return NO; - - [hotKey setCarbonHotKeyID:hotKeyID.id]; - [hotKey setCarbonEventHotKeyRef:carbonHotKey]; - - if( hotKey ) - [mHotKeys setObject: hotKey forKey: [NSNumber numberWithInteger:hotKeyID.id]]; - - [self _updateEventHandler]; - - return YES; -} - -- (void)unregisterHotKey: (PTHotKey*)hotKey -{ - EventHotKeyRef carbonHotKey; - - if( [[self allHotKeys] containsObject: hotKey] == NO ) - return; - - carbonHotKey = [hotKey carbonEventHotKeyRef]; - - if( carbonHotKey ) - { - UnregisterEventHotKey( carbonHotKey ); - //Watch as we ignore 'err': - - [mHotKeys removeObjectForKey: [NSNumber numberWithInteger:[hotKey carbonHotKeyID]]]; - - [hotKey setCarbonHotKeyID:0]; - [hotKey setCarbonEventHotKeyRef:NULL]; - - [self _updateEventHandler]; - - //See that? Completely ignored - } -} - -- (NSArray*)allHotKeys -{ - return [mHotKeys allValues]; -} - -- (PTHotKey*)hotKeyWithIdentifier: (id)ident -{ - NSEnumerator* hotKeysEnum = [[self allHotKeys] objectEnumerator]; - PTHotKey* hotKey; - - if( !ident ) - return nil; - - while( (hotKey = [hotKeysEnum nextObject]) != nil ) - { - if( [[hotKey identifier] isEqual: ident] ) - return hotKey; - } - - return nil; -} - -#pragma mark - - -- (PTHotKey*)_hotKeyForCarbonHotKey: (EventHotKeyRef)carbonHotKeyRef -{ - NSEnumerator *e = [mHotKeys objectEnumerator]; - PTHotKey *hotkey = nil; - - while( (hotkey = [e nextObject]) ) - { - if( [hotkey carbonEventHotKeyRef] == carbonHotKeyRef ) - return hotkey; - } - - return nil; -} - -- (PTHotKey*)_hotKeyForCarbonHotKeyID: (EventHotKeyID)hotKeyID -{ - return [mHotKeys objectForKey:[NSNumber numberWithInteger:hotKeyID.id]]; -} - -- (void)_updateEventHandler -{ - if( [mHotKeys count] && mEventHandlerInstalled == NO ) - { - EventTypeSpec eventSpec[2] = { - { kEventClassKeyboard, kEventHotKeyPressed }, - { kEventClassKeyboard, kEventHotKeyReleased } - }; - - InstallEventHandler( GetEventDispatcherTarget(), - (EventHandlerProcPtr)hotKeyEventHandler, - 2, eventSpec, nil, nil); - - mEventHandlerInstalled = YES; - } -} - -- (void)_hotKeyDown: (PTHotKey*)hotKey -{ - [hotKey invoke]; -} - -- (void)_hotKeyUp: (PTHotKey*)hotKey -{ -} - -- (void)sendEvent: (NSEvent*)event -{ - // Not sure why this is needed? - Andy Kim (Aug 23, 2009) - - short subType; - EventHotKeyRef carbonHotKey; - - if( [event type] == NSSystemDefined ) - { - subType = [event subtype]; - - if( subType == 6 ) //6 is hot key down - { - carbonHotKey= (EventHotKeyRef)[event data1]; //data1 is our hot key ref - if( carbonHotKey != nil ) - { - PTHotKey* hotKey = [self _hotKeyForCarbonHotKey: carbonHotKey]; - [self _hotKeyDown: hotKey]; - } - } - else if( subType == 9 ) //9 is hot key up - { - carbonHotKey= (EventHotKeyRef)[event data1]; - if( carbonHotKey != nil ) - { - PTHotKey* hotKey = [self _hotKeyForCarbonHotKey: carbonHotKey]; - [self _hotKeyUp: hotKey]; - } - } - } -} - -- (OSStatus)sendCarbonEvent: (EventRef)event -{ - OSStatus err; - EventHotKeyID hotKeyID; - PTHotKey* hotKey; - - NSAssert( GetEventClass( event ) == kEventClassKeyboard, @"Unknown event class" ); - - err = GetEventParameter( event, - kEventParamDirectObject, - typeEventHotKeyID, - nil, - sizeof(EventHotKeyID), - nil, - &hotKeyID ); - if( err ) - return err; - - - NSAssert( hotKeyID.signature == 'PTHk', @"Invalid hot key id" ); - NSAssert( hotKeyID.id != 0, @"Invalid hot key id" ); - - hotKey = [self _hotKeyForCarbonHotKeyID:hotKeyID]; - - switch( GetEventKind( event ) ) - { - case kEventHotKeyPressed: - [self _hotKeyDown: hotKey]; - break; - - case kEventHotKeyReleased: - [self _hotKeyUp: hotKey]; - break; - - default: - NSAssert( 0, @"Unknown event kind" ); - break; - } - - return noErr; -} - -static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon ) -{ - return [[PTHotKeyCenter sharedCenter] sendCarbonEvent: inEvent]; -} - -@end diff --git a/Source/PTHotKeys/PTKeyCodeTranslator.h b/Source/PTHotKeys/PTKeyCodeTranslator.h deleted file mode 100644 index 27e7ba7..0000000 --- a/Source/PTHotKeys/PTKeyCodeTranslator.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// PTKeyCodeTranslator.h -// Chercher -// -// Created by Finlay Dobbie on Sat Oct 11 2003. -// Copyright (c) 2003 Cliché Software. All rights reserved. -// - -#import - -@interface PTKeyCodeTranslator : NSObject -{ - TISInputSourceRef keyboardLayout; - const UCKeyboardLayout *uchrData; - UInt32 keyTranslateState; - UInt32 deadKeyState; -} - -+ (id)currentTranslator; - -- (id)initWithKeyboardLayout:(TISInputSourceRef)aLayout; -- (NSString *)translateKeyCode:(short)keyCode; - -- (TISInputSourceRef)keyboardLayout; - -@end diff --git a/Source/PTHotKeys/PTKeyCodeTranslator.m b/Source/PTHotKeys/PTKeyCodeTranslator.m deleted file mode 100644 index 6f878d6..0000000 --- a/Source/PTHotKeys/PTKeyCodeTranslator.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// PTKeyCodeTranslator.m -// Chercher -// -// Created by Finlay Dobbie on Sat Oct 11 2003. -// Copyright (c) 2003 Cliché Software. All rights reserved. -// - -#import "PTKeyCodeTranslator.h" - - -@implementation PTKeyCodeTranslator - -+ (id)currentTranslator -{ - static PTKeyCodeTranslator *current = nil; - TISInputSourceRef currentLayout = TISCopyCurrentKeyboardLayoutInputSource(); - - if (current == nil) { - current = [[PTKeyCodeTranslator alloc] initWithKeyboardLayout:currentLayout]; - } else if ([current keyboardLayout] != currentLayout) { - [current release]; - current = [[PTKeyCodeTranslator alloc] initWithKeyboardLayout:currentLayout]; - } - - CFRelease(currentLayout); - - return current; -} - -- (id)initWithKeyboardLayout:(TISInputSourceRef)aLayout -{ - if ((self = [super init]) != nil) { - keyboardLayout = aLayout; - - CFRetain(keyboardLayout); - - CFDataRef uchr = TISGetInputSourceProperty( keyboardLayout , kTISPropertyUnicodeKeyLayoutData ); - uchrData = ( const UCKeyboardLayout* )CFDataGetBytePtr(uchr); - } - - return self; -} - -- (void)dealloc -{ - CFRelease(keyboardLayout); - - [super dealloc]; -} - -- (NSString *)translateKeyCode:(short)keyCode { - UniCharCount maxStringLength = 4, actualStringLength; - UniChar unicodeString[4]; - UCKeyTranslate( uchrData, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, maxStringLength, &actualStringLength, unicodeString ); - return [NSString stringWithCharacters:unicodeString length:1]; -} - -- (TISInputSourceRef)keyboardLayout { - return keyboardLayout; -} - -- (NSString *)description { - NSString *kind; - kind = @"uchr"; - - NSString *layoutName; - layoutName = TISGetInputSourceProperty( keyboardLayout, kTISPropertyLocalizedName ); - return [NSString stringWithFormat:@"PTKeyCodeTranslator layout=%@ (%@)", layoutName, kind]; -} - -@end diff --git a/Source/PTHotKeys/PTKeyCombo.h b/Source/PTHotKeys/PTKeyCombo.h deleted file mode 100644 index 4af0163..0000000 --- a/Source/PTHotKeys/PTKeyCombo.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// PTKeyCombo.h -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// - -#import - -@interface PTKeyCombo : NSObject -{ - NSInteger mKeyCode; - NSUInteger mModifiers; -} - -+ (id)clearKeyCombo; -+ (id)keyComboWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers; -- (id)initWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers; - -- (id)initWithPlistRepresentation: (id)plist; -- (id)plistRepresentation; - -- (BOOL)isEqual: (PTKeyCombo*)combo; - -- (NSInteger)keyCode; -- (NSUInteger)modifiers; - -- (BOOL)isClearCombo; -- (BOOL)isValidHotKeyCombo; - -@end - - -@interface PTKeyCombo (UserDisplayAdditions) -- (NSString*)keyCodeString; -- (NSUInteger)modifierMask; -@end diff --git a/Source/PTHotKeys/PTKeyCombo.m b/Source/PTHotKeys/PTKeyCombo.m deleted file mode 100644 index 7532c26..0000000 --- a/Source/PTHotKeys/PTKeyCombo.m +++ /dev/null @@ -1,245 +0,0 @@ -// -// PTKeyCombo.m -// Protein -// -// Created by Quentin Carnicelli on Sat Aug 02 2003. -// Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved. -// - -#import "PTKeyCombo.h" -#import "PTKeyCodeTranslator.h" - -@implementation PTKeyCombo - -+ (id)clearKeyCombo -{ - return [self keyComboWithKeyCode: -1 modifiers: -1]; -} - -+ (id)keyComboWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers -{ - return [[[self alloc] initWithKeyCode: keyCode modifiers: modifiers] autorelease]; -} - -- (id)initWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers -{ - self = [super init]; - - if( self ) - { - mKeyCode = keyCode; - mModifiers = modifiers; - } - - return self; -} - -- (id)initWithPlistRepresentation: (id)plist -{ - NSInteger keyCode, modifiers; - - if( !plist || ![plist count] ) - { - keyCode = -1; - modifiers = -1; - } - else - { - keyCode = [[plist objectForKey: @"keyCode"] intValue]; - if( keyCode < 0 ) keyCode = -1; - - modifiers = [[plist objectForKey: @"modifiers"] intValue]; - if( modifiers <= 0 ) modifiers = -1; - } - - return [self initWithKeyCode: keyCode modifiers: modifiers]; -} - -- (id)plistRepresentation -{ - return [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInteger: [self keyCode]], @"keyCode", - [NSNumber numberWithInteger: [self modifiers]], @"modifiers", - nil]; -} - -- (id)copyWithZone:(NSZone*)zone; -{ - return [self retain]; -} - -- (BOOL)isEqual: (PTKeyCombo*)combo -{ - return [self keyCode] == [combo keyCode] && - [self modifiers] == [combo modifiers]; -} - -#pragma mark - - -- (NSInteger)keyCode -{ - return mKeyCode; -} - -- (NSUInteger)modifiers -{ - return mModifiers; -} - -- (BOOL)isValidHotKeyCombo -{ - return mKeyCode >= 0 && mModifiers > 0; -} - -- (BOOL)isClearCombo -{ - return mKeyCode == -1 && mModifiers == -1; -} - -@end - -#pragma mark - - -@implementation PTKeyCombo (UserDisplayAdditions) - -+ (NSString*)_stringForModifiers: (long)modifiers -{ - static unichar modToChar[4][2] = - { - { cmdKey, kCommandUnicode }, - { optionKey, kOptionUnicode }, - { controlKey, kControlUnicode }, - { shiftKey, kShiftUnicode } - }; - - NSString* str = [NSString string]; - long i; - - for( i = 0; i < 4; i++ ) - { - if( modifiers & modToChar[i][0] ) - str = [str stringByAppendingString: [NSString stringWithCharacters: &modToChar[i][1] length: 1]]; - } - - return str; -} - -+ (NSDictionary*)_keyCodesDictionary -{ - static NSDictionary* keyCodes = nil; - - if( keyCodes == nil ) - { - NSURL *url = [NSURL fileURLWithPath:[[NSBundle bundleForClass: self] pathForResource: @"PTKeyCodes" ofType: @"plist"]]; - NSString *contents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL]; - keyCodes = [[contents propertyList] retain]; - } - - return keyCodes; -} - -+ (NSString*)_stringForKeyCode: (short)keyCode legacyKeyCodeMap: (NSDictionary*)dict -{ - id key; - NSString* str; - - key = [NSString stringWithFormat: @"%d", keyCode]; - str = [dict objectForKey: key]; - - if( !str ) - str = [NSString stringWithFormat: @"%X", keyCode]; - - return str; -} - -+ (NSString*)_stringForKeyCode: (short)keyCode newKeyCodeMap: (NSDictionary*)dict -{ - NSString* result; - NSString* keyCodeStr; - NSDictionary* unmappedKeys; - NSArray* padKeys; - - keyCodeStr = [NSString stringWithFormat: @"%d", keyCode]; - - //Handled if its not handled by translator - unmappedKeys = [dict objectForKey:@"unmappedKeys"]; - result = [unmappedKeys objectForKey: keyCodeStr]; - if( result ) - return result; - - //Translate it - result = [[[PTKeyCodeTranslator currentTranslator] translateKeyCode:keyCode] uppercaseString]; - - //Handle if its a key-pad key - padKeys = [dict objectForKey:@"padKeys"]; - if( [padKeys indexOfObject: keyCodeStr] != NSNotFound ) - { - result = [NSString stringWithFormat:@"%@ %@", [dict objectForKey:@"padKeyString"], result]; - } - - return result; -} - -+ (NSString*)_stringForKeyCode: (short)keyCode -{ - NSDictionary* dict; - - dict = [self _keyCodesDictionary]; - if( [[dict objectForKey: @"version"] intValue] <= 0 ) - return [self _stringForKeyCode: keyCode legacyKeyCodeMap: dict]; - - return [self _stringForKeyCode: keyCode newKeyCodeMap: dict]; -} - -- (NSString*)keyCodeString -{ - // special case: the modifiers for the "clear" key are 0x0 - if ( [self isClearCombo] ) return @""; - - return [[self class] _stringForKeyCode:[self keyCode]]; -} - -- (NSUInteger)modifierMask -{ - // special case: the modifiers for the "clear" key are 0x0 - if ( [self isClearCombo] ) return 0; - - static NSUInteger modToChar[4][2] = - { - { cmdKey, NSCommandKeyMask }, - { optionKey, NSAlternateKeyMask }, - { controlKey, NSControlKeyMask }, - { shiftKey, NSShiftKeyMask } - }; - - NSUInteger i, ret = 0; - - for ( i = 0; i < 4; i++ ) - { - if ( [self modifiers] & modToChar[i][0] ) { - ret |= modToChar[i][1]; - } - } - - return ret; -} - -- (NSString*)description -{ - NSString* desc; - - if( [self isValidHotKeyCombo] ) //This might have to change - { - desc = [NSString stringWithFormat: @"%@%@", - [[self class] _stringForModifiers: [self modifiers]], - [[self class] _stringForKeyCode: [self keyCode]]]; - } - else - { - desc = NSLocalizedString( @"(None)", @"Hot Keys: Key Combo text for 'empty' combo" ); - } - - return desc; -} - -@end diff --git a/Source/PrefsWindowController.h b/Source/PrefsWindowController.h deleted file mode 100644 index 795b9f8..0000000 --- a/Source/PrefsWindowController.h +++ /dev/null @@ -1,135 +0,0 @@ -// -// PrefsWindowController.h -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/04. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import -#import "DBPrefsWindowController.h" - - -#pragma mark Preference Keys -/* General */ -extern NSString *const CMPrefLoginItemKey; -extern NSString *const CMPrefSuppressAlertForLoginItemKey; -extern NSString *const CMPrefInputPasteCommandKey; -extern NSString *const CMPrefReorderClipsAfterPasting; -extern NSString *const CMPrefMaxHistorySizeKey; -extern NSString *const CMPrefAutosaveDelayKey; -extern NSString *const CMPrefSaveHistoryOnQuitKey; -extern NSString *const CMPrefExportHistoryAsSingleFileKey; -extern NSString *const CMPrefTagOfSeparatorForExportHistoryToFileKey; -extern NSString *const CMPrefShowStatusItemKey; -extern NSString *const CMPrefTimeIntervalKey; -extern NSString *const CMPrefStoreTypesKey; -extern NSString *const CMPrefExcludeAppsKey; -/* Menu */ -extern NSString *const CMPrefMaxMenuItemTitleLengthKey; -extern NSString *const CMPrefNumberOfItemsPlaceInlineKey; -extern NSString *const CMPrefNumberOfItemsPlaceInsideFolderKey; -extern NSString *const CMPrefMenuItemsAreMarkedWithNumbersKey; -extern NSString *const CMPrefMenuItemsTitleStartWithZeroKey; -extern NSString *const CMPrefAddNumericKeyEquivalentsKey; -extern NSString *const CMPrefAddClearHistoryMenuItemKey; -extern NSString *const CMPrefShowAlertBeforeClearHistoryKey; -extern NSString *const CMPrefShowLabelsInMenuKey; -extern NSString *const CMPrefShowToolTipOnMenuItemKey; -extern NSString *const CMPrefMaxLengthOfToolTipKey; -extern NSString *const CMPrefChangeFontSizeKey; -extern NSString *const CMPrefHowToChangeFontSizeKey; -extern NSString *const CMPrefSelectedFontSizeKey; -extern NSString *const CMPrefShowImageInTheMenuKey; -extern NSString *const CMPrefThumbnailWidthKey; -extern NSString *const CMPrefThumbnailHeightKey; -extern NSString *const CMPrefShowIconInTheMenuKey; -/* - Menu Icon - */ -extern NSString *const CMPrefMenuIconSizeKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForStringKey; -extern NSString *const CMPrefMenuIconOfFileTypeForStringKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForRTFKey; -extern NSString *const CMPrefMenuIconOfFileTypeForRTFKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForRTFDKey; -extern NSString *const CMPrefMenuIconOfFileTypeForRTFDKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForPDFKey; -extern NSString *const CMPrefMenuIconOfFileTypeForPDFKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForFilenamesKey; -extern NSString *const CMPrefMenuIconOfFileTypeForFilenamesKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForURLKey; -extern NSString *const CMPrefMenuIconOfFileTypeForURLKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForTIFFKey; -extern NSString *const CMPrefMenuIconOfFileTypeForTIFFKey; -extern NSString *const CMPrefMenuIconOfFileTypeTagForPICTKey; -extern NSString *const CMPrefMenuIconOfFileTypeForPICTKey; -/* Hot Keys */ -extern NSString *const CMPrefHotKeysKey; - -/* Action */ -extern NSString *const CMPrefEnableActionKey; -extern NSString *const CMPrefInvokeActionImmediatelyKey; -extern NSString *const CMPrefContorlClickBehaviorKey; -extern NSString *const CMPrefShiftClickBehaviorKey; -extern NSString *const CMPrefOptionClickBehaviorKey; -extern NSString *const CMPrefCommandClickBehaviorKey; -/* Snippet */ -extern NSString *const CMPrefPositionOfSnippetsKey; -/* Updates */ -extern NSString *const CMEnableAutomaticCheckKey; -extern NSString *const CMEnableAutomaticCheckPreReleaseKey; -extern NSString *const CMUpdateCheckIntervalKey; - - -#pragma mark Notifications -extern NSString *const CMPreferencePanelWillCloseNotification; - - -@class SRRecorderControl, ActionNodeController, ActionPopUpButton; - -@interface PrefsWindowController : DBPrefsWindowController -{ - IBOutlet NSView *generalPrefsView; - IBOutlet NSView *menuPrefsView; - IBOutlet NSView *iconPrefsView; - IBOutlet NSView *actionPrefsView; - IBOutlet NSView *shortcutPrefsView; - IBOutlet NSView *updatesPrefsView; - - IBOutlet ActionNodeController *actionNodeController; - - /* Hot Keys */ - IBOutlet SRRecorderControl *shortcutRecorder; - IBOutlet SRRecorderControl *historyShortCutRecorder; - IBOutlet SRRecorderControl *snippetsShortcutRecorder; - NSMutableArray *shortcutRecorders; - - NSMutableDictionary *storeTypes; - NSArray *fontSizePopUpMenuItems; - - /* Modifiers pop up bottons */ - NSArray *modifiersPopUpMenuItems; - IBOutlet NSPopUpButton *controlPopUpButton; - IBOutlet NSPopUpButton *shiftPopUpButton; - IBOutlet NSPopUpButton *optionPopUpButton; - IBOutlet NSPopUpButton *commandPopUpButton; - - /* Exclude List */ - IBOutlet NSArrayController *excludeListController; - IBOutlet NSPanel *excludeListPanel; - IBOutlet ActionPopUpButton *addExcludeListButtion; - NSMutableArray *excludeList; -} -@property (nonatomic, copy) NSMutableArray *shortcutRecorders; -@property (nonatomic, copy) NSMutableDictionary *storeTypes; -@property (nonatomic, retain) NSArray *fontSizePopUpMenuItems; -@property (retain) NSArray *modifiersPopUpMenuItems; -@property (nonatomic, copy) NSMutableArray *excludeList; - -- (IBAction)openExcludeOptions:(id)sender; -- (IBAction)doneExcludeListPanel:(id)sender; -- (IBAction)cancelExcludeListPanel:(id)sender; -- (void)addToExcludeList:(id)sender; - -- (IBAction)exportHistory:(id)sender; - -@end diff --git a/Source/PrefsWindowController.m b/Source/PrefsWindowController.m deleted file mode 100644 index 17bbf64..0000000 --- a/Source/PrefsWindowController.m +++ /dev/null @@ -1,961 +0,0 @@ -// -// PrefsWindowController.m -// ClipMenu -// -// Created by Naotaka Morimoto on 08/03/04. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "PrefsWindowController.h" -#import "constants.h" -#import "CMUtilities.h" -#import "ClipsController.h" -#import "MenuController.h" -#import "ActionNodeController.h" -#import "ActionNode.h" -#import "ActionController.h" -#import "ImageAndTextCell.h" -#import "NMLoginItems.h" - -#import "PTHotKey.h" -#import "PTHotKeyCenter.h" -#import - - -#pragma mark Preference Keys -/* General */ -NSString *const CMPrefLoginItemKey = @"loginItem"; -NSString *const CMPrefSuppressAlertForLoginItemKey = @"suppressAlertForLoginItem"; -NSString *const CMPrefInputPasteCommandKey = @"inputPasteCommand"; -NSString *const CMPrefReorderClipsAfterPasting = @"reorderClipsAfterPasting"; -NSString *const CMPrefMaxHistorySizeKey = @"maxHistorySize"; -NSString *const CMPrefAutosaveDelayKey = @"autosaveDelay"; -NSString *const CMPrefSaveHistoryOnQuitKey = @"saveHistoryOnQuit"; -NSString *const CMPrefExportHistoryAsSingleFileKey = @"exportHistoryAsSingleFile";; -NSString *const CMPrefTagOfSeparatorForExportHistoryToFileKey = @"tagOfSeparatorForExportHistoryToFile"; -NSString *const CMPrefShowStatusItemKey = @"showStatusItem"; -NSString *const CMPrefTimeIntervalKey = @"timeInterval"; -NSString *const CMPrefStoreTypesKey = @"storeTypes"; -NSString *const CMPrefExcludeAppsKey = @"excludeApps"; -/* Menu */ -NSString *const CMPrefMaxMenuItemTitleLengthKey = @"maxMenuItemTitleLength"; -NSString *const CMPrefNumberOfItemsPlaceInlineKey = @"numberOfItemsPlaceInline"; -NSString *const CMPrefNumberOfItemsPlaceInsideFolderKey = @"numberOfItemsPlaceInsideFolder"; -NSString *const CMPrefMenuItemsAreMarkedWithNumbersKey = @"menuItemsAreMarkedWithNumbers"; -NSString *const CMPrefMenuItemsTitleStartWithZeroKey = @"menuItemsTitleStartWithZero"; -NSString *const CMPrefAddNumericKeyEquivalentsKey = @"addNumericKeyEquivalents"; -NSString *const CMPrefAddClearHistoryMenuItemKey = @"addClearHistoryMenuItem"; -NSString *const CMPrefShowAlertBeforeClearHistoryKey = @"showAlertBeforeClearHistory"; -NSString *const CMPrefShowLabelsInMenuKey = @"showLabelsInMenu"; -NSString *const CMPrefShowToolTipOnMenuItemKey = @"showToolTipOnMenuItem"; -NSString *const CMPrefMaxLengthOfToolTipKey = @"maxLengthOfToolTipKey"; -NSString *const CMPrefChangeFontSizeKey = @"changeFontSize"; -NSString *const CMPrefHowToChangeFontSizeKey = @"howToChangeFontSize"; -NSString *const CMPrefSelectedFontSizeKey = @"selectedFontSize"; -NSString *const CMPrefShowImageInTheMenuKey = @"showImageInTheMenu"; -NSString *const CMPrefThumbnailWidthKey = @"thumbnailWidth"; -NSString *const CMPrefThumbnailHeightKey = @"thumbnailHeight"; -NSString *const CMPrefShowIconInTheMenuKey = @"showIconInTheMenu"; -/* - Menu Icon - */ -NSString *const CMPrefMenuIconSizeKey = @"menuIconSize"; -NSString *const CMPrefMenuIconOfFileTypeTagForStringKey = @"menuIconOfFileTypeTagForString"; -NSString *const CMPrefMenuIconOfFileTypeForStringKey = @"menuIconOfFileTypeForString"; -NSString *const CMPrefMenuIconOfFileTypeTagForRTFKey = @"menuIconOfFileTypeTagForRTF"; -NSString *const CMPrefMenuIconOfFileTypeForRTFKey = @"menuIconOfFileTypeForRTF"; -NSString *const CMPrefMenuIconOfFileTypeTagForRTFDKey = @"menuIconOfFileTypeTagForRTFD"; -NSString *const CMPrefMenuIconOfFileTypeForRTFDKey = @"menuIconOfFileTypeForRTFD"; -NSString *const CMPrefMenuIconOfFileTypeTagForPDFKey = @"menuIconOfFileTypeTagForPDF"; -NSString *const CMPrefMenuIconOfFileTypeForPDFKey = @"menuIconOfFileTypeForPDF"; -NSString *const CMPrefMenuIconOfFileTypeTagForFilenamesKey = @"menuIconOfFileTypeTagForFilenames"; -NSString *const CMPrefMenuIconOfFileTypeForFilenamesKey = @"menuIconOfFileTypeForFilenames"; -NSString *const CMPrefMenuIconOfFileTypeTagForURLKey = @"menuIconOfFileTypeTagForURL"; -NSString *const CMPrefMenuIconOfFileTypeForURLKey = @"menuIconOfFileTypeForURL"; -NSString *const CMPrefMenuIconOfFileTypeTagForTIFFKey = @"menuIconOfFileTypeTagForTIFF"; -NSString *const CMPrefMenuIconOfFileTypeForTIFFKey = @"menuIconOfFileTypeForTIFF"; -NSString *const CMPrefMenuIconOfFileTypeTagForPICTKey = @"menuIconOfFileTypeTagForPICT"; -NSString *const CMPrefMenuIconOfFileTypeForPICTKey = @"menuIconOfFileTypeForPICT"; -/* Hot Keys */ -NSString *const CMPrefHotKeysKey = @"hotKeys"; -/* Action */ -NSString *const CMPrefEnableActionKey = @"enableAction"; -NSString *const CMPrefInvokeActionImmediatelyKey = @"invokeActionImmediately"; -NSString *const CMPrefContorlClickBehaviorKey = @"controlClickBehavior"; -NSString *const CMPrefShiftClickBehaviorKey = @"shiftClickBehavior"; -NSString *const CMPrefOptionClickBehaviorKey = @"optionClickBehavior"; -NSString *const CMPrefCommandClickBehaviorKey = @"commandClickBehavior"; -/* Snippet */ -NSString *const CMPrefPositionOfSnippetsKey = @"positionOfSnippets"; -/* Updates */ -NSString *const CMEnableAutomaticCheckKey = @"enableAutomaticCheck"; -NSString *const CMEnableAutomaticCheckPreReleaseKey = @"enableAutomaticCheckPreReleaseKey"; -NSString *const CMUpdateCheckIntervalKey = @"updateCheckInterval"; - - -#pragma mark Notifications -NSString *const CMPreferencePanelWillCloseNotification = @"CMPreferencePanelWillCloseNotification"; - - -@interface PrefsWindowController () -- (void)_prepareHotKeys; -- (void)_changeHotKeyByShortcutRecorder:(SRRecorderControl *)aRecorder withKeyCombo:(KeyCombo)keyCombo; -- (void)_prepareFontSizePopUpMenuItems; -- (NSArray *)_actionsFromNodes:(NSArray *)nodes; -- (void)_prepareModifiersPopUpMenuItems; -- (void)_buildModifiersPopUpMenuItems; - -//- (void)_checkLoginItemState; -//- (void)_changeLoginItemWithNumber:(NSNumber *)number; - -- (void)_prepareAddToExcludeListMenu; -- (void)_addAppInfoToExcludeList:(NSDictionary *)appInfo; -- (void)_addSelectedAppToExcludeList:(id)sender; - -- (void)_exportHistoryAsSingleFile; -- (void)_exportHistoryAsMultipleFiles; -- (void)_exportHistoryAsSingleFile:(BOOL)singleFile sheet:(NSSavePanel *)sheet returnCode:(NSInteger)returnCode; -@end - - -@implementation PrefsWindowController - -@synthesize shortcutRecorders; -@synthesize storeTypes; -@synthesize fontSizePopUpMenuItems; -@synthesize modifiersPopUpMenuItems; -@synthesize excludeList; - - -NSDictionary *separatorItemDict() -{ - return [NSDictionary dictionaryWithObjectsAndKeys: - @"-", kTitle, - [NSNull null], kBehavior, - nil]; -} - -BOOL sameBehaviors(id a, id b) -{ - if ([a isEqualTo:b] - || ([a respondsToSelector:@selector( isEqualToString: )] - && [a isEqualToString:b])) { - return YES; - } - return NO; -} - -#pragma mark Initialize - -/* -initWithWindow: is the designated initializer for NSWindowController. */ -- (id)initWithWindow:(NSWindow *)window -{ - self = [super initWithWindow:nil]; - if (self) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - [self setStoreTypes:[defaults objectForKey:CMPrefStoreTypesKey]]; -// [self setExcludeList:[defaults objectForKey:CMPrefExcludeAppsKey]]; - [self _prepareFontSizePopUpMenuItems]; - } - return self; -} - -- (void)dealloc -{ - [[self window] setDelegate:nil]; - - [shortcutRecorders release], shortcutRecorders = nil; - [storeTypes release], storeTypes = nil; - [fontSizePopUpMenuItems release], fontSizePopUpMenuItems = nil; - [modifiersPopUpMenuItems release], modifiersPopUpMenuItems = nil; - [excludeList release], excludeList = nil; - - [super dealloc]; -} - -- (void)awakeFromNib -{ -// NSLog(@"awakeFromNib"); - - [actionNodeController handleAwakeFromNib]; - - [self _prepareHotKeys]; - - /* Pop up menus for modified click */ - [NSThread detachNewThreadSelector:@selector( _prepareModifiersPopUpMenuItems ) - toTarget:self - withObject:nil]; -} - -- (void)windowDidLoad -{ - [super windowDidLoad]; - - NSWindow *window = [self window]; - [window setDelegate:self]; - [window setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; -} - -#pragma mark - -#pragma mark Accessors - -#pragma mark - Write - - -- (void)setShortcutRecorders:(NSMutableArray *)newRecorders -{ - if (shortcutRecorders != newRecorders) { - [shortcutRecorders release]; - shortcutRecorders = [newRecorders mutableCopy]; - } -} - -- (void)setStoreTypes:(NSMutableDictionary *)newTypes -{ - if (storeTypes != newTypes) { - [storeTypes release]; - storeTypes = [newTypes mutableCopy]; - } -} - -- (void)setExcludeList:(NSMutableArray *)newList -{ - if (excludeList != newList) { - [excludeList release]; - excludeList = [newList mutableCopy]; - } -} - -#pragma mark - -#pragma mark Delegate -#pragma mark - NSWindow - - -- (void)windowWillClose:(NSNotification *)aNotification -{ -// NSLog(@"windowWillClose"); - - /* Save pref settings */ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:storeTypes forKey:CMPrefStoreTypesKey]; - - /* Save actions */ - [[ActionController sharedInstance] setValue:[actionNodeController actionNodes] - forKey:@"actionNodes"]; - - /* Pop up menus for modified click */ - NSString *representedObject; - representedObject = [[controlPopUpButton selectedItem] representedObject]; - [defaults setObject:representedObject forKey:CMPrefContorlClickBehaviorKey]; - - representedObject = [[shiftPopUpButton selectedItem] representedObject]; - [defaults setObject:representedObject forKey:CMPrefShiftClickBehaviorKey]; - - representedObject = [[optionPopUpButton selectedItem] representedObject]; - [defaults setObject:representedObject forKey:CMPrefOptionClickBehaviorKey]; - - representedObject = [[commandPopUpButton selectedItem] representedObject]; - [defaults setObject:representedObject forKey:CMPrefCommandClickBehaviorKey]; - - /* Window */ - NSWindow *window = [self window]; - if (![window makeFirstResponder:window]) { - [window endEditingFor:nil]; - } - [NSApp deactivate]; - - /* Send Notification */ - [[NSNotificationCenter defaultCenter] postNotificationName:CMPreferencePanelWillCloseNotification - object:nil]; -} - -//- (void)windowDidBecomeKey:(NSNotification *)aNotification -//{ -// NSLog(@"become"); -// [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; -// -//// NSInteger newWindowLevel = [[self window] level] + 1; -//// [[self window] setLevel:newWindowLevel]; -//} - -//- (void)windowDidResignKey:(NSNotification *)aNotification -//{ -// NSLog(@"resign"); -// [[self window] setLevel:NSNormalWindowLevel]; -//} - -#pragma mark - SRRecorderControl - - -//- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags reason:(NSString **)aReason -//{ -// if (aRecorder == shortcutRecorder || aRecorder == snippetsShortcutRecorder) -// { -//// BOOL isTaken = NO; -// -// NSArray *allKeys = [[PTHotKeyCenter sharedCenter] allHotKeys]; -// for (PTHotKey *hotKey in allKeys) { -// PTKeyCombo *keyCombo = [hotKey keyCombo]; -// NSInteger registerdkeyCode = [keyCombo keyCode]; -// NSInteger registerdFlags = [aRecorder carbonToCocoaFlags:[keyCombo modifiers]]; -// -// NSLog(@"registerdkeyCode: %d, registerdFlags: %d - code: %d, flags: %d", registerdkeyCode, registerdFlags, keyCode, flags); -// -// if (registerdkeyCode == keyCode && registerdkeyCode == flags) { -// *aReason = @"reason"; // need to change!!! -// return YES; -// } -// } -// -//// KeyCombo kc = [delegateDisallowRecorder keyCombo]; -//// -//// if (kc.code == keyCode && kc.flags == flags) { -//// isTaken = YES; -//// } -//// -//// *aReason = @"reason"; // need to change!!! -//// -//// return isTaken; -// } -// -// return NO; -//} - -- (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo -{ -// NSLog(@"aRecorder: %@", aRecorder); - - if ([shortcutRecorders containsObject:aRecorder]) - { -// NSLog(@"keyComboDidChange: flags: %d, code: %d", newKeyCombo.code, newKeyCombo.flags); - [self _changeHotKeyByShortcutRecorder:aRecorder withKeyCombo:newKeyCombo]; - } -} - -#pragma mark - NSTableView - - -- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex -{ -// NSLog(@"cell: %d, %@", rowIndex, [aCell image]); - - if ([[aTableColumn identifier] isEqualToString:kImageAndTextCellColumn]) { - // we are displaying the single and only column - if ([aCell isKindOfClass:[ImageAndTextCell class]]) { - NSWorkspace *workSpace = [NSWorkspace sharedWorkspace]; - - NSDictionary *appInfo = [excludeList objectAtIndex:rowIndex]; - if (appInfo == nil) { - return; - } - - NSString *identifier = [appInfo objectForKey:kCMBundleIdentifierKey]; - if (identifier == nil) { - return; - } - - NSString *path = [workSpace absolutePathForAppBundleWithIdentifier:identifier]; - NSImage *icon = nil; - - if (path) { - icon = [workSpace iconForFile:path]; - } - - if (icon == nil) { - icon = [workSpace iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; - } - - if (icon == nil) { - return; - } - - [icon setSize:NSMakeSize(16, 16)]; - [(ImageAndTextCell *)aCell setImage:icon]; // set the cell's image - } - } -} - -#pragma mark - -#pragma mark Public - -#pragma mark - Exclude List - - -- (IBAction)openExcludeOptions:(id)sender -{ - if (excludeList == nil) { - [self setExcludeList:[[NSUserDefaults standardUserDefaults] objectForKey:CMPrefExcludeAppsKey]]; - } - - [self _prepareAddToExcludeListMenu]; - - [NSApp beginSheet:excludeListPanel - modalForWindow:self.window - modalDelegate:self - didEndSelector:@selector( excludeListPanelDidEnd:returnCode:contextInfo: ) - contextInfo:nil]; -} - -- (IBAction)doneExcludeListPanel:(id)sender -{ - [NSApp endSheet:excludeListPanel returnCode:NSOKButton]; - - [[NSUserDefaults standardUserDefaults] setObject:self.excludeList - forKey:CMPrefExcludeAppsKey]; -} - -- (IBAction)cancelExcludeListPanel:(id)sender -{ - [NSApp endSheet:excludeListPanel returnCode:NSCancelButton]; - [self setExcludeList:[[NSUserDefaults standardUserDefaults] objectForKey:CMPrefExcludeAppsKey]]; -} - -- (void)excludeListPanelDidEnd:(NSPanel *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo -{ - [sheet orderOut:self]; -} - -- (void)addToExcludeList:(id)sender -{ - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - [openPanel setAllowedFileTypes:[NSArray arrayWithObject:@"app"]]; - [openPanel setAllowsMultipleSelection:YES]; - [openPanel setResolvesAliases:YES]; - [openPanel setPrompt:NSLocalizedString(@"Add", nil)]; - - NSArray *directories = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSLocalDomainMask, YES); - NSString *basePath = (0 < [directories count]) ? [directories objectAtIndex:0] : NSHomeDirectory(); - - [openPanel beginSheetForDirectory:basePath - file:nil - modalForWindow:excludeListPanel - modalDelegate:self - didEndSelector:@selector( addToExcludeListPanelDidEnd:returnCode:contextInfo: ) - contextInfo:NULL]; -} - -- (void)addToExcludeListPanelDidEnd:(NSOpenPanel *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo -{ -// NSLog(@"addToExcludeListPanelDidEnd: %d", returnCode); - - if (returnCode == NSOKButton) { - NSDictionary *appInfo; - - NSBundle *bundle; - NSDictionary *infoDict; - BOOL isSnowLeopardOrLater = ([NSBundle respondsToSelector:@selector( bundleWithURL: )]) - ? YES : NO; - - for (NSURL *url in [sheet URLs]) { - if (isSnowLeopardOrLater) { - /* Mac OS X 10.6 or lator */ - bundle = [NSBundle bundleWithURL:url]; - } - else { - bundle = [NSBundle bundleWithPath:[url path]]; - } - - infoDict = [bundle infoDictionary]; - NSString *bundleIdentifier = [infoDict objectForKey:(NSString *)kCFBundleIdentifierKey]; -// NSLog(@"bundleIdentifier: %@", bundleIdentifier); - if (bundleIdentifier == nil) { - continue; - } - - NSString *appName = [infoDict objectForKey:(NSString *)kCFBundleNameKey]; -// NSLog(@"appName: %@", appName); - if (appName == nil) { - appName = [infoDict objectForKey:(NSString *)kCFBundleExecutableKey]; - if (appName == nil) { - continue; - } - } - - appInfo = [[NSDictionary alloc] initWithObjectsAndKeys: - bundleIdentifier, kCMBundleIdentifierKey, - appName, kCMNameKey, - nil]; - [self _addAppInfoToExcludeList:appInfo]; - [appInfo release], appInfo = nil; - } - } - - [sheet orderOut:self]; -} - -#pragma mark - NSSavePanel - - -- (IBAction)exportHistory:(id)sender -{ - BOOL singleFile = [[NSUserDefaults standardUserDefaults] - boolForKey:CMPrefExportHistoryAsSingleFileKey]; - if (singleFile) { - [self _exportHistoryAsSingleFile]; - } - else { - [self _exportHistoryAsMultipleFiles]; - } -} - -- (void)savePanelDidEnd:(NSSavePanel *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo -{ - BOOL singleFile = [[NSUserDefaults standardUserDefaults] - boolForKey:CMPrefExportHistoryAsSingleFileKey]; - - [self _exportHistoryAsSingleFile:singleFile sheet:sheet returnCode:returnCode]; -} - -#pragma mark - DBPrefsWindowController - - -/* Override */ -- (IBAction)showWindow:(id)sender -{ -// NSLog(@"showWindow"); - - [super showWindow:sender]; - [NSApp activateIgnoringOtherApps:YES]; - [[self window] makeKeyAndOrderFront:self]; - -// /* Check whether login item or not */ -// [NSThread detachNewThreadSelector:@selector( _checkLoginItemState ) -// toTarget:self -// withObject:nil]; -} - -- (void)setupToolbar -{ - NSImage *image; - - if (image = [NSImage imageNamed:NSImageNamePreferencesGeneral]) { - [self addView:generalPrefsView label:NSLocalizedString(@"General", nil) image:image]; - } - - if (image = [NSImage imageNamed:@"Menu"]) { - [self addView:menuPrefsView label:NSLocalizedString(@"Menu", nil) image:image]; - } - - image = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; - if (image) { - [image setSize:NSMakeSize(32, 32)]; - [self addView:iconPrefsView label:NSLocalizedString(@"Type", nil) image:image]; - } - - if (image = [NSImage imageNamed:@"ActionIconLarge"]) { - [self addView:actionPrefsView label:NSLocalizedString(@"Action", nil) image:image]; - } - - if (image = [NSImage imageNamed:@"PTKeyboardIcon"]) { - [self addView:shortcutPrefsView label:NSLocalizedString(@"Shortcuts", nil) image:image]; - } - - if (image = [NSImage imageNamed:@"SparkleIcon"]) { - [self addView:updatesPrefsView label:NSLocalizedString(@"Updates", nil) image:image]; - } - - [self setCrossFade:YES]; - [self setShiftSlowsAnimation:NO]; -} - -#pragma mark - -#pragma mark Private - -- (void)_prepareHotKeys -{ - NSMutableArray *recorders = [NSMutableArray arrayWithObjects: - shortcutRecorder, historyShortCutRecorder, snippetsShortcutRecorder, - nil]; - [self setShortcutRecorders:recorders]; - - NSDictionary *hotKeyMap = [CMUtilities hotKeyMap]; - NSDictionary *hotKeyCombos = [[NSUserDefaults standardUserDefaults] objectForKey:CMPrefHotKeysKey]; - for (NSString *identifier in hotKeyCombos) { -// NSLog(@"identifier: %@", identifier); - id keyComboPlist = [hotKeyCombos objectForKey:identifier]; -// NSLog(@"keyComboPlist: %@", keyComboPlist); - - KeyCombo keyCombo; - keyCombo.code = [[keyComboPlist objectForKey:@"keyCode"] unsignedIntValue]; - keyCombo.flags = [shortcutRecorder carbonToCocoaFlags:[[keyComboPlist objectForKey:@"modifiers"] unsignedIntValue]]; - - NSUInteger index = [[[hotKeyMap objectForKey:identifier] objectForKey:kIndex] - unsignedIntegerValue]; - SRRecorderControl *recorder = [recorders objectAtIndex:index]; - [recorder setKeyCombo:keyCombo]; - [recorder setAnimates:YES]; - } -} - -- (void)_changeHotKeyByShortcutRecorder:(SRRecorderControl *)aRecorder withKeyCombo:(KeyCombo)keyCombo -{ -// NSLog(@"_changeHotKeyByShortcutRecorder: %@", aRecorder); - - PTKeyCombo *newKeyCombo = [PTKeyCombo keyComboWithKeyCode:keyCombo.code - modifiers:[aRecorder cocoaToCarbonFlags:keyCombo.flags]]; - - NSString *identifier = nil; - if (aRecorder == shortcutRecorder) { - identifier = kClipMenuIdentifier; - } - else if (aRecorder == historyShortCutRecorder) { - identifier = kHistoryMenuIdentifier; - } - else if (aRecorder == snippetsShortcutRecorder) { - identifier = kSnippetsMenuIdentifier; - } - else { - NSAssert(NO, @"Couldn't find the identifier of the recorder"); - } -// NSLog(@"identifier: %@", identifier); - - PTHotKeyCenter *hotKeyCenter = [PTHotKeyCenter sharedCenter]; - PTHotKey *oldHotKey = [hotKeyCenter hotKeyWithIdentifier:identifier]; - [hotKeyCenter unregisterHotKey:oldHotKey]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSMutableDictionary *hotKeyPrefs = [[[defaults objectForKey:CMPrefHotKeysKey] mutableCopy] - autorelease]; - [hotKeyPrefs setObject:[newKeyCombo plistRepresentation] forKey:identifier]; - [defaults setObject:hotKeyPrefs forKey:CMPrefHotKeysKey]; -} - -- (void)_prepareFontSizePopUpMenuItems -{ - NSMutableArray *items = [NSMutableArray array]; - for (NSInteger i = 9; i <= 24; i++) { - [items addObject:[NSNumber numberWithInt:i]]; - } - [items addObjectsFromArray:[NSArray arrayWithObjects:@"36", @"48", @"64", @"72", @"96", nil]]; - - [self setValue:items forKey:@"fontSizePopUpMenuItems"]; -} - -- (NSArray *)_actionsFromNodes:(NSArray *)nodes -{ - NSMutableArray *results = [NSMutableArray array]; - - for (ActionNode *node in nodes) { - if ([node isLeaf]) { - NSString *title = [node nodeTitle]; - NSDictionary *action = [node action]; - if (action && title) { - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: - title, kTitle, - action, kBehavior, - nil]; - [results addObject:dict]; - } - } - else { - NSArray *children = [self _actionsFromNodes:[node children]]; - [results addObjectsFromArray:children]; - } - } - - if ([results count] < 1) { - return nil; - } - - return results; -} - -- (void)_prepareModifiersPopUpMenuItems -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSMutableArray *items = [NSMutableArray arrayWithObjects: - [NSDictionary dictionaryWithObjectsAndKeys: - NSLocalizedString(@"None", nil), kTitle, - kEmptyString, kBehavior, - nil], - [NSDictionary dictionaryWithObjectsAndKeys: - NSLocalizedString(@"Pop up Action Menu", nil), kTitle, - kPopUpActionMenu, kBehavior, - nil], - nil]; - - [items addObject:separatorItemDict()]; - - NSArray *builtinNodes = [actionNodeController builtinNodes]; - if ([self _actionsFromNodes:builtinNodes]) { - [items addObjectsFromArray:[self _actionsFromNodes:builtinNodes]]; - } - - [items addObject:separatorItemDict()]; - - NSArray *bundledNodes = [actionNodeController bundledNodes]; - if ([self _actionsFromNodes:bundledNodes]) { - [items addObjectsFromArray:[self _actionsFromNodes:bundledNodes]]; - } - - [items addObject:separatorItemDict()]; - - NSArray *usersNodes = [actionNodeController usersNodes]; - if ([self _actionsFromNodes:usersNodes]) { - [items addObjectsFromArray:[self _actionsFromNodes:usersNodes]]; - } - - [self setModifiersPopUpMenuItems:items]; - - [self _buildModifiersPopUpMenuItems]; - - [pool drain]; -} - -- (void)_buildModifiersPopUpMenuItems -{ - NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"modifiersPopUpMenu"]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSString *controlClickBehavior = [defaults objectForKey:CMPrefContorlClickBehaviorKey]; - NSString *shiftClickBehavior = [defaults objectForKey:CMPrefShiftClickBehaviorKey]; - NSString *optionClickBehavior = [defaults objectForKey:CMPrefOptionClickBehaviorKey]; - NSString *commandClickBehavior = [defaults objectForKey:CMPrefCommandClickBehaviorKey]; - -// NSLog(@"controlKeyBehavior: %@", controlClickBehavior); - - NSInteger indexOfTargetForControlKey = 0; - NSInteger indexOfTargetForShiftKey = 0; - NSInteger indexOfTargetForOptionKey = 0; - NSInteger indexOfTargetForCommandKey = 0; - - NSUInteger i = 0; - for (NSDictionary *item in modifiersPopUpMenuItems) { - NSMenuItem *menuItem; - NSString *title = [item objectForKey:kTitle]; - if ([title isEqualToString:@"-"]) { - menuItem = [NSMenuItem separatorItem]; - } - else { - menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:title action:NULL keyEquivalent:kEmptyString] autorelease]; - } - - id behavior = [item objectForKey:kBehavior]; - - if (![behavior isEqualTo:[NSNull null]]) { - if (sameBehaviors(behavior, controlClickBehavior)) { - indexOfTargetForControlKey = i; - } - if (sameBehaviors(behavior, shiftClickBehavior)) { - indexOfTargetForShiftKey = i; - } - if (sameBehaviors(behavior, optionClickBehavior)) { - indexOfTargetForOptionKey = i; - } - if (sameBehaviors(behavior, commandClickBehavior)) { - indexOfTargetForCommandKey = i; - } - - [menuItem setRepresentedObject:behavior]; - } - - [menu addItem:menuItem]; - i++; - } - - [controlPopUpButton setMenu:menu]; - [controlPopUpButton selectItemAtIndex:indexOfTargetForControlKey]; - - [shiftPopUpButton setMenu:[[menu copy] autorelease]]; - [shiftPopUpButton selectItemAtIndex:indexOfTargetForShiftKey]; - [optionPopUpButton setMenu:[[menu copy] autorelease]]; - [optionPopUpButton selectItemAtIndex:indexOfTargetForOptionKey]; - [commandPopUpButton setMenu:[[menu copy] autorelease]]; - [commandPopUpButton selectItemAtIndex:indexOfTargetForCommandKey]; - - [menu release], menu = nil; -} - -//- (void)_checkLoginItemState -//{ -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -// -// NSString *appPath = [[NSBundle mainBundle] bundlePath]; -// BOOL isInLoginItems = [NMLoginItems pathInLoginItems:appPath]; -// [self performSelectorOnMainThread:@selector( _changeLoginItemWithNumber: ) -// withObject:[NSNumber numberWithBool:isInLoginItems] -// waitUntilDone:NO]; -// -// [pool drain]; -//} -// -//- (void)_changeLoginItemWithNumber:(NSNumber *)number -//{ -// NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; -// BOOL currentState = [defaults boolForKey:CMPrefLoginItemKey]; -// BOOL state = [number boolValue]; -// -// if (currentState != state) { -// [defaults setBool:state forKey:CMPrefLoginItemKey]; -// } -//} - -#pragma mark - Exclude List - - -- (void)_prepareAddToExcludeListMenu -{ - NSWorkspace *workSpace = [NSWorkspace sharedWorkspace]; - NSArray *launchedApps = [workSpace launchedApplications]; - - NSMenu *popUpMenu = [[[NSMenu allocWithZone:[NSMenu menuZone]] init] autorelease]; - NSMenuItem *menuItem; - NSDictionary *appInfo; - - for (NSDictionary *app in launchedApps) { - NSString *appName = [app objectForKey:@"NSApplicationName"]; - if (appName == nil) { - continue; - } - - NSString *bundleIdentifier = [app objectForKey:@"NSApplicationBundleIdentifier"]; - if (bundleIdentifier == nil) { - continue; - } - - NSString *appPath = [app objectForKey:@"NSApplicationPath"]; - if (appPath == nil) { - return; - } - - appInfo = [[NSDictionary alloc] initWithObjectsAndKeys: - bundleIdentifier, kCMBundleIdentifierKey, - appName, kCMNameKey, - nil]; - - /* Make menuItem */ - menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:appName - action:@selector( _addSelectedAppToExcludeList: ) - keyEquivalent:kEmptyString]; - [menuItem setTarget:self]; - [menuItem setRepresentedObject:appInfo]; - [appInfo release], appInfo = nil; - - /* Icon */ - NSImage *icon = [workSpace iconForFile:appPath]; - - if (icon == nil) { - icon = [workSpace iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; - } - - if (icon) { - [icon setSize:NSMakeSize(16, 16)]; - [menuItem setImage:icon]; - } - - [popUpMenu addItem:menuItem]; - [menuItem release], menuItem = nil; - } - - [popUpMenu addItem:[NSMenuItem separatorItem]]; - - menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] - initWithTitle:NSLocalizedString(@"Other...", nil) - action:@selector( addToExcludeList: ) - keyEquivalent:kEmptyString]; - [menuItem setTarget:self]; - [popUpMenu addItem:menuItem]; - [menuItem release], menuItem = nil; - - [addExcludeListButtion setMenu:popUpMenu]; -} - -- (void)_addAppInfoToExcludeList:(NSDictionary *)appInfo -{ - NSArray *excludedAppIDs = [[excludeListController arrangedObjects] - valueForKey:kCMBundleIdentifierKey]; - NSString *newID = [appInfo objectForKey:kCMBundleIdentifierKey]; - if (newID == nil) { - return; - } - - if ([excludedAppIDs containsObject:newID]) { - return; - } - - [excludeListController addObject:appInfo]; -} - -- (void)_addSelectedAppToExcludeList:(id)sender -{ - NSDictionary *appInfo = [sender representedObject]; - [self _addAppInfoToExcludeList:appInfo]; -} - -#pragma mark - Export History - - -- (void)_exportHistoryAsSingleFile -{ - NSString *filename = @"clipboard_history.txt"; - - NSSavePanel *savePanel = [NSSavePanel savePanel]; - [savePanel setCanCreateDirectories:YES]; - [savePanel setAllowedFileTypes:[NSArray arrayWithObject:@"txt"]]; - - /* Blocks causes crash in Leopard */ -// if ([savePanel respondsToSelector:@selector( beginSheetModalForWindow:completionHandler: )]) { -// /* Mac OS X 10.6 and lator */ -// [savePanel setNameFieldStringValue:filename]; -// [savePanel beginSheetModalForWindow:[self window] completionHandler:^ (NSInteger returnCode) { -// [self _exportHistoryAsSingleFile:YES sheet:savePanel returnCode:returnCode]; -// }]; -// } -// else { - /* Mac OS X 10.5 and earlier */ - [savePanel beginSheetForDirectory:nil - file:filename - modalForWindow:[self window] - modalDelegate:self - didEndSelector:@selector( savePanelDidEnd:returnCode:contextInfo: ) - contextInfo:NULL]; -// } -} - -- (void)_exportHistoryAsMultipleFiles -{ - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - [openPanel setCanChooseDirectories:YES]; - [openPanel setCanChooseFiles:NO]; - [openPanel setCanCreateDirectories:YES]; - [openPanel setPrompt:NSLocalizedString(@"Select", nil)]; - - /* Blocks causes crash in Leopard */ -// if ([openPanel respondsToSelector:@selector( beginSheetModalForWindow:completionHandler: )]) { -// /* Mac OS X 10.6 and lator */ -// [openPanel beginSheetModalForWindow:[self window] completionHandler:^ (NSInteger returnCode) { -// [self _exportHistoryAsSingleFile:NO sheet:openPanel returnCode:returnCode]; -// }]; -// } -// else { - /* Mac OS X 10.5 and earlier */ - [openPanel beginSheetForDirectory:nil - file:nil - modalForWindow:[self window] - modalDelegate:self - didEndSelector:@selector( savePanelDidEnd:returnCode:contextInfo: ) - contextInfo:NULL]; -// } -} - -- (void)_exportHistoryAsSingleFile:(BOOL)singleFile sheet:(NSSavePanel *)sheet returnCode:(NSInteger)returnCode -{ - if (returnCode != NSOKButton) { - return; - } - - NSString *path = [[sheet URL] path]; - BOOL success; - - if (singleFile) { - success = [[ClipsController sharedInstance] exportHistoryStringsAsSingleFile:path]; - } - else { - success = [[ClipsController sharedInstance] exportHistoryStringsAsMultipleFiles:path]; - } - - if (!success) { - NSLog(@"Failed to export history"); - CMRunAlertPanel(NSLocalizedString(@"Error", nil), - NSLocalizedString(@"Failed to export history", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - return; - } -} - -@end diff --git a/Source/ScriptableClip.h b/Source/ScriptableClip.h deleted file mode 100644 index 8505217..0000000 --- a/Source/ScriptableClip.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// ScriptableClip.h -// ClipMenu -// -// Created by naotaka on 09/11/13. -// Copyright 2009 Naotaka Morimoto. All rights reserved. -// - -#import -#import - -typedef enum { - CMChangeAttributesSetType, - CMChangeAttributesAddType, -} CMChangeAttributesType; - -@class Clip; - -@interface ScriptableClip : NSObject { - Clip *clip; -} -@property (nonatomic, copy) Clip *clip; - -- (id)initWithClip:(Clip *)aClip; - -- (void)setStringAttributes:(WebScriptObject *)scriptObject; -- (void)addStringAttributes:(WebScriptObject *)scriptObject; - -@end diff --git a/Source/ScriptableClip.m b/Source/ScriptableClip.m deleted file mode 100644 index f51b8c1..0000000 --- a/Source/ScriptableClip.m +++ /dev/null @@ -1,341 +0,0 @@ -// -// ScriptableClip.m -// ClipMenu -// -// Created by naotaka on 09/11/13. -// Copyright 2009 Naotaka Morimoto. All rights reserved. -// - -#import "ScriptableClip.h" -#import "Clip.h" - -#import "NSColor+String.h" - -/* AttributedString */ -#define COLOR_KEY @"color" -#define FOREGROUND_COLOR_KEY @"foreground" -#define BACKGROUND_COLOR_KEY @"background" -#define FONT_KEY @"font" -#define NAME_KEY @"name" -#define SIZE_KEY @"size" -#define UNDERLINE_STYLE_KEY @"underline" -#define STYLE_KEY @"style" -#define PATTERN_KEY @"pattern" -#define BYWORD_KEY @"byWord" - - -#pragma mark - - -id -getValueFromWebScriptObject(WebScriptObject *scriptObject, NSString *key) -{ - id result = nil; - @try { - result = [scriptObject valueForKey:key]; - } - @catch (NSException *e) { - result = nil; - } - return result; -} - -NSInteger -getUnderlineStyleConstantForName(NSString *name) -{ - NSString *lowerName = [name lowercaseString]; - static NSDictionary *styles = nil; - - if (styles == nil) { - NSArray *keys = [[NSArray alloc] initWithObjects: - @"none", @"single", @"thick", @"double", nil]; - NSArray *values = [[NSArray alloc] initWithObjects: - [NSNumber numberWithInteger:NSUnderlineStyleNone], - [NSNumber numberWithInteger:NSUnderlineStyleSingle], - [NSNumber numberWithInteger:NSUnderlineStyleThick], - [NSNumber numberWithInteger:NSUnderlineStyleDouble], - nil]; - styles = [[NSDictionary alloc] initWithObjects:values forKeys:keys]; - [keys release], keys = nil; - [values release], values = nil; - } - - NSNumber *num = [styles objectForKey:lowerName]; -// [styles release], styles = nil; - - if (num == nil) { - return NSUnderlineStyleNone; - } - - return [num integerValue]; -} - -NSInteger -getUnderlinePatternConstantForName(NSString *name) -{ - NSString *lowerName = [name lowercaseString]; - static NSDictionary *styles = nil; - - if (styles == nil) { - NSArray *keys = [[NSArray alloc] initWithObjects: - @"solid", @"dot", @"dash", @"dashdot", @"dashdotdot", nil]; - NSArray *values = [[NSArray alloc] initWithObjects: - [NSNumber numberWithInteger:NSUnderlinePatternSolid], - [NSNumber numberWithInteger:NSUnderlinePatternDot], - [NSNumber numberWithInteger:NSUnderlinePatternDash], - [NSNumber numberWithInteger:NSUnderlinePatternDashDot], - [NSNumber numberWithInteger:NSUnderlinePatternDashDotDot], - nil]; - styles = [[NSDictionary alloc] initWithObjects:values forKeys:keys]; - [keys release], keys = nil; - [values release], values = nil; - } - - NSNumber *num = [styles objectForKey:lowerName]; -// [styles release], styles = nil; - - if (num == nil) { - return NSUnderlinePatternSolid; - } - - return [num integerValue]; -} - -#pragma mark - - -@interface ScriptableClip () -- (void)_changeStringAttributes:(WebScriptObject *)scriptObject forType:(CMChangeAttributesType)type; -- (NSDictionary *)_getColorsFromWebScriptObject:(WebScriptObject *)scriptObject; -- (NSFont *)_getFontFromWebScriptObject:(WebScriptObject *)scriptObject; -- (NSNumber *)_getUnderlineStyleFromWebScriptObject:(WebScriptObject *)scriptObject; -@end - -#pragma mark - - -@implementation ScriptableClip - -@synthesize clip; - -- (id)initWithClip:(Clip *)aClip -{ - self = [super init]; - if (self == nil) { - return nil; - } - - [self setClip:aClip]; - - return self; -} - -- (void)dealloc -{ - [clip release], clip = nil; - - [super dealloc]; -} - -#pragma mark - - -- (void)setStringAttributes:(WebScriptObject *)scriptObject -{ - [self _changeStringAttributes:scriptObject forType:CMChangeAttributesSetType]; -} - -- (void)addStringAttributes:(WebScriptObject *)scriptObject -{ - [self _changeStringAttributes:scriptObject forType:CMChangeAttributesAddType]; -} - -#pragma mark - -#pragma mark WebSpripting protocol - -+ (NSString *)webScriptNameForSelector:(SEL)aSelector -{ -// NSLog(@"webScriptNameForSelector"); - - if (aSelector == @selector( setStringAttributes: )) { - return @"setStringAttributes"; - } - else if (aSelector == @selector( addStringAttributes: )) { - return @"addStringAttributes"; - } - - return nil; -} - -+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector -{ - if (aSelector == @selector( setStringAttributes: ) || - aSelector == @selector( addStringAttributes: )) { - return NO; - } - return YES; -} - -#pragma mark - -#pragma mark Private - -- (void)_changeStringAttributes:(WebScriptObject *)scriptObject forType:(CMChangeAttributesType)type -{ - Clip *aClip = self.clip; - - if (aClip.stringValue == nil) { - return; - } - - NSMutableArray *types = [NSMutableArray arrayWithArray:aClip.types]; - BOOL containsRTFD = [types containsObject:NSRTFDPboardType]; - NSMutableAttributedString *attrString = [NSMutableAttributedString alloc]; - - if (aClip.RTFData) { - if (containsRTFD) { - attrString = [attrString initWithRTFD:aClip.RTFData documentAttributes:nil]; - } - else { - attrString = [attrString initWithRTF:aClip.RTFData documentAttributes:nil]; - } - } - else { - attrString = [[NSMutableAttributedString alloc] initWithString:aClip.stringValue]; - if ([types containsObject:NSRTFPboardType]) { - [types removeObject:NSRTFPboardType]; - } - [types insertObject:NSRTFPboardType atIndex:0]; - } - - NSRange range = NSMakeRange(0, [attrString length]); - NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init]; - - /* Color */ - NSDictionary *colors = [self _getColorsFromWebScriptObject:scriptObject]; - NSColor *color; - for (NSString *key in colors) { - color = [colors objectForKey:key]; - if ([key isEqualToString:FOREGROUND_COLOR_KEY]) { - [attrs setObject:color forKey:NSForegroundColorAttributeName]; - } - else if ([key isEqualToString:BACKGROUND_COLOR_KEY]) { - [attrs setObject:color forKey:NSBackgroundColorAttributeName]; - } - } - - /* Font */ - NSFont *font = [self _getFontFromWebScriptObject:scriptObject]; - if (font) { - [attrs setObject:font forKey:NSFontAttributeName]; - } - - /* Underline Style */ - NSNumber *underlineStyle = [self _getUnderlineStyleFromWebScriptObject:scriptObject]; - if (underlineStyle) { - [attrs setObject:underlineStyle forKey:NSUnderlineStyleAttributeName]; - } - - if ([attrs count]) { - [attrString beginEditing]; - - @try { - /* Use this way - because performSelector:withObject:withObject: always raises exception */ - switch (type) { - case CMChangeAttributesSetType: - [attrString setAttributes:attrs range:range]; - break; - case CMChangeAttributesAddType: - [attrString addAttributes:attrs range:range]; - break; - default: - NSAssert(NO, @"Unknown change type"); - break; - } - [attrString fixAttributesInRange:range]; - } - @catch (NSException *ex) { - NSLog(@"exception: %@", ex); - } - - [attrString endEditing]; - - aClip.types = types; - aClip.RTFData = (containsRTFD) - ? [attrString RTFDFromRange:range documentAttributes:nil] - : [attrString RTFFromRange:range documentAttributes:nil]; - } - - [attrs release], attrs = nil; - [attrString release], attrString = nil; -} - -- (NSDictionary *)_getColorsFromWebScriptObject:(WebScriptObject *)scriptObject -{ - NSMutableDictionary *colors = [NSMutableDictionary dictionaryWithCapacity:2]; - NSString *colorName; - NSColor *color; - @try { - WebScriptObject *colorObject = [scriptObject valueForKey:COLOR_KEY]; - if (colorObject) { - colorName = getValueFromWebScriptObject(colorObject, FOREGROUND_COLOR_KEY); - if (colorName) { - color = [NSColor colorWithString:colorName]; - [colors setObject:color forKey:FOREGROUND_COLOR_KEY]; - } - - colorName = getValueFromWebScriptObject(colorObject, BACKGROUND_COLOR_KEY); - if (colorName) { - color = [NSColor colorWithString:colorName]; - [colors setObject:color forKey:BACKGROUND_COLOR_KEY]; - } - } - } - @catch (NSException *e) { - } - return colors; -} - -- (NSFont *)_getFontFromWebScriptObject:(WebScriptObject *)scriptObject -{ - NSFont *font = nil; - @try { - WebScriptObject *fontObject = [scriptObject valueForKey:FONT_KEY]; - if (fontObject) { - NSString *fontName = getValueFromWebScriptObject(fontObject, NAME_KEY); - CGFloat fontSize = [getValueFromWebScriptObject(fontObject, SIZE_KEY) floatValue]; - font = [NSFont fontWithName:fontName size:fontSize]; - } - } - @catch (NSException *e) { - } - return font; -} - -- (NSNumber *)_getUnderlineStyleFromWebScriptObject:(WebScriptObject *)scriptObject -{ - NSNumber *underlineStyle = nil; - NSString *styleName; - NSNumber *byWordNumer; - NSInteger styleConstant; - NSInteger patternConstant; - NSUInteger maskConstant = 0; - @try { - WebScriptObject *styleObject = [scriptObject valueForKey:UNDERLINE_STYLE_KEY]; - if (styleObject) { - styleName = getValueFromWebScriptObject(styleObject, STYLE_KEY); - styleConstant = getUnderlineStyleConstantForName(styleName); - - styleName = getValueFromWebScriptObject(styleObject, PATTERN_KEY); - patternConstant = getUnderlinePatternConstantForName(styleName); - - byWordNumer = getValueFromWebScriptObject(styleObject, BYWORD_KEY); - if ([byWordNumer boolValue]) { - maskConstant = NSUnderlineByWordMask; - } - - underlineStyle = [NSNumber numberWithInteger:styleConstant | patternConstant | maskConstant]; - } - } - @catch (NSException *e) { - } - return underlineStyle; -} - -@end diff --git a/Source/SnippetEditorController.h b/Source/SnippetEditorController.h deleted file mode 100644 index 305898b..0000000 --- a/Source/SnippetEditorController.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// SnippetEditorController.h -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - -#pragma mark Notifications -extern NSString *const CMSnippetEditorWillCloseNotification; - - -@class SnippetsController; -@class IndexedArrayController; -@class SeparatorCell; - -@interface SnippetEditorController : NSWindowController -{ - SnippetsController *snippetsController; - NSImage *folderImage; - NSImage *snippetImage; - - IBOutlet NSTreeController *folderTreeController; - IBOutlet NSOutlineView *folderOutlineView; - SeparatorCell *separatorCell; // the cell used to draw a separator line in the outline view - NSMutableArray *sourceList; - NSArray *draggedNodes; // used to keep track of dragged nodes - NSIndexPath *lastSelectionIndexPath; - - IBOutlet IndexedArrayController *folderArrayController; - IBOutlet IndexedArrayController *snippetArrayController; - IBOutlet NSTableView *snippetTableView; - - /* Read XML */ - NSMutableArray *foldersFromFile; - NSMutableString *currentElementContent; - NSMutableDictionary *currentFolder; - NSMutableDictionary *currentSnippet; -} -@property(nonatomic, retain) SnippetsController *snippetsController; -@property(nonatomic, retain) NSMutableArray *sourceList; -@property(nonatomic, retain) NSArray *draggedNodes; -@property(nonatomic, retain) NSIndexPath *lastSelectionIndexPath; -@property(nonatomic, retain) NSImage *folderImage; -@property(nonatomic, retain) NSImage *snippetImage; -@property(nonatomic, assign, readonly) BOOL hasFolders; - -- (IBAction)addFolder:(id)sender; -- (IBAction)removeFolder:(id)sender; -- (IBAction)toggleFolderEnabled:(id)sender; -- (IBAction)addSnippet:(id)sender; -//- (IBAction)removeSnippet:(id)sender; -- (IBAction)toggleSnippetEnabled:(id)sender; - -- (IBAction)importSnippets:(id)sender; -- (IBAction)exportSnippets:(id)sender; - -/* path through snippetsController */ -- (BOOL)saveStoreFile; - -@end diff --git a/Source/SnippetEditorController.m b/Source/SnippetEditorController.m deleted file mode 100644 index 0ca1bdd..0000000 --- a/Source/SnippetEditorController.m +++ /dev/null @@ -1,1461 +0,0 @@ -// -// SnippetEditorController.m -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "SnippetEditorController.h" -#import "SnippetsController.h" -#import "constants.h" -#import "IndexedArrayController.h" -#import "FolderNode.h" -#import "ImageAndTextCell.h" -#import "SeparatorCell.h" -#import "NSIndexPath_Extensions.h" - -#define GROUP_NAME @"GROUPS" -#define ADD_SNIPPET_IDENTIFIER @"AddSnippet" -#define DELETE_SNIPPET_IDENTIFIER @"DeleteSnippet" -#define CHECK_SNIPPET_IDENTIFIER @"CheckSnippet" - -#define DEFAULT_EXPORT_FILENAME @"snippets" - -#define kArrangedObjectsTitleKeyPath @"arrangedObjects.title" - -#pragma mark Notifications -NSString *const CMSnippetEditorWillCloseNotification = @"CMSnippetEditorWillCloseNotification"; - - -NSInteger compare(NSUInteger a, NSUInteger b) -{ - return (a < b) ? -1 : (a > b) ? 1 : 0; -} - -NSUInteger numberOfLowerIndexes(NSIndexSet *indexes, NSUInteger currentIndex, NSUInteger row) -{ - NSUInteger count = 0; - NSUInteger index = [indexes firstIndex]; - - while (index != NSNotFound) { - if (-1 < compare(currentIndex, row)) { - count++; - } - index = [indexes indexGreaterThanIndex:index]; - } - - return count; -} - - -@interface SnippetEditorController () -- (void)_prepareSourceList; -//- (void)selectParentFromSelection; -- (BOOL)isSpecialGroup:(FolderNode *)groupNode; -- (void)_expandGroups; -- (void)_cacheIconImages; -- (void)_moveUpDraggedObjects:(NSArray *)draggedObjects withIndexes:(NSIndexSet *)rowIndexes; -- (BOOL)_endEditingForWindow; - -- (id)_rootTreeNodeForSnippetFolder; -- (NSArray *)_treeNodesForSnippetFolder; -- (NSInteger)_lastIndexOfSnippetFolders; -- (FolderNode *)_makeFolderNodeForFolder:(NSManagedObject *)folder; -- (FolderNode *)_makeFolderNodeWithIndex:(NSInteger)index; -- (void)_removeFolderNodes:(NSArray *)folderNodes; -- (void)_renumberAllFolders; -- (void)_renumberFoldersFromIndex:(NSUInteger)index; -- (void)_renumberSnippetsOfFolder:(NSManagedObject *)folder fromIndex:(NSUInteger)index; -- (void)_inspectAllFolders; // for debug -- (void)_inspectAllSnippetsAtSelection; // for debug - -- (void)_parseXMLFileAtURL:(NSURL *)url; -- (void)_addImportedFolders:(NSArray *)folders; -- (void)_handleNSManagedObjectContextObjectsDidChange:(NSNotification *)aNotification; -@end - -#pragma mark - - -@implementation SnippetEditorController - -@synthesize snippetsController; -@synthesize sourceList; -@synthesize draggedNodes; -@synthesize lastSelectionIndexPath; -@synthesize folderImage; -@synthesize snippetImage; - -- (id)init -{ - self = [super initWithWindowNibName:@"SnippetEditor"]; - if (self == nil) { - return nil; - } - - [self setSnippetsController:[SnippetsController sharedInstance]]; - [self _prepareSourceList]; - [self _cacheIconImages]; - - return self; -} - -- (void)dealloc -{ -// [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [sourceList release], sourceList = nil; - [snippetsController release], snippetsController = nil; - [folderImage release], folderImage = nil; - [snippetImage release], snippetImage = nil; - [separatorCell release], separatorCell = nil; - [lastSelectionIndexPath release], lastSelectionIndexPath = nil; - - self.draggedNodes = nil; - - [super dealloc]; -} - -- (void)awakeFromNib -{ - /* Cell */ - separatorCell = [[SeparatorCell alloc] init]; - [separatorCell setEnabled:NO]; - - [self _expandGroups]; - - /* Drag and Drop */ - NSArray *draggedDataTypes = [NSArray arrayWithObject:kDraggedDataType]; - [folderOutlineView registerForDraggedTypes:draggedDataTypes]; - [folderOutlineView setDraggingSourceOperationMask:(NSDragOperationMove) - forLocal:YES]; - [snippetTableView registerForDraggedTypes:draggedDataTypes]; - [snippetTableView setDraggingSourceOperationMask:(NSDragOperationMove) - forLocal:YES]; - -// /* Notification */ -// // Avoid a problem doesn't update tableView -// [[NSNotificationCenter defaultCenter] addObserver:self -// selector:@selector( _handleNSManagedObjectContextObjectsDidChange: ) -// name:NSManagedObjectContextObjectsDidChangeNotification -// object:nil]; - - /* Snippet title was changed */ - [snippetArrayController addObserver:self - forKeyPath:kArrangedObjectsTitleKeyPath - options:NSKeyValueObservingOptionNew - context:nil]; -} - -#pragma mark - -#pragma mark Accessors - -- (NSMutableArray *)sourceList -{ - return sourceList; -} - -- (BOOL)hasFolders -{ - return [[folderArrayController arrangedObjects] count]; -} - -#pragma mark - -#pragma mark Override - -- (void)windowDidLoad -{ - [super windowDidLoad]; - [self.window setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; -} - -- (IBAction)showWindow:(id)sender -{ -// NSLog(@"showWindow"); - - [super showWindow:sender]; - [self.window center]; - [NSApp activateIgnoringOtherApps:YES]; - [self.window makeKeyAndOrderFront:self]; - - if (self.lastSelectionIndexPath) { - [folderTreeController setSelectionIndexPath:self.lastSelectionIndexPath]; - } - - /* Notification */ - // Avoid a problem doesn't update tableView - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector( _handleNSManagedObjectContextObjectsDidChange: ) - name:NSManagedObjectContextObjectsDidChangeNotification - object:snippetsController.managedObjectContext]; -} - -#pragma mark - -#pragma mark KVO - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ -// NSLog(@"observeValueForKeyPath: %@, object: %@", keyPath, object); - - if ([object isEqualTo:snippetArrayController] && - [keyPath isEqualToString:kArrangedObjectsTitleKeyPath]) { // prevent empty snippet's content -// NSLog(@"%@", [object valueForKeyPath:@"selection"]); - - id selected = [object valueForKeyPath:@"selection"]; - NSString *title = [selected valueForKeyPath:kTitle]; - if ((title == NSNoSelectionMarker) || - (title == NSNotApplicableMarker) || - (title == NSMultipleValuesMarker)) { -// NSLog(@"NO"); // temp!!! - return; - } - NSString *content = [selected valueForKeyPath:kContent]; - if ([content length] == 0 && - ![title isEqualToString:NSLocalizedString(@"untitled snippet", nil)]) { -// NSLog(@"Empty"); // temp!!! - [selected setValue:title forKey:kContent]; - } - -// NSLog(@"title: %@", [selected valueForKeyPath:kTitle]); -// NSLog(@"content: %@", [selected valueForKeyPath:kContent]); - } -} - -#pragma mark - -#pragma mark Delegate - -#pragma mark - NSControl - - -/* This method brings a glitch to the pref panel. */ -//- (void)controlTextDidEndEditing:(NSNotification *)aNotification -//{ -//// NSLog(@"controlTextDidEndEditing: %@", aNotification); -// -// if ([[aNotification object] isEqualTo:snippetTableView]) { // prevent empty snippet's content -// NSDictionary *userInfo = [aNotification userInfo]; -//// NSLog(@"controlTextDidEndEditing: %@", userInfo); -// -// NSInteger textMovement = [[userInfo objectForKey:@"NSTextMovement"] integerValue]; -// if (textMovement == NSTabTextMovement) { -// return; -// } -// -// NSString *title = [[[[userInfo objectForKey:@"NSFieldEditor"] string] copy] autorelease]; -// NSInteger index = [snippetTableView selectedRow]; -// NSManagedObject *snippet = [[snippetArrayController arrangedObjects] objectAtIndex:index]; -// -// if ([[snippet valueForKey:kContent] length] == 0) { -// [snippet setValue:title forKey:kContent]; -// } -// } -//} - -// ------------------------------------------------------------------------------- -// textShouldEndEditing: -// ------------------------------------------------------------------------------- -- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor -{ - if ([[fieldEditor string] length] == 0) - { - // don't allow empty node names - return NO; - } - else - { - return YES; - } -} - -#pragma mark - NSWindow - - -- (void)windowWillClose:(NSNotification *)aNotification -{ - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSManagedObjectContextObjectsDidChangeNotification - object:snippetsController.managedObjectContext]; - - /* Window */ - NSWindow *window = [self window]; - if (![window makeFirstResponder:window]) { - [window endEditingFor:nil]; - } - [NSApp deactivate]; - - /* Keep last selectionIndexPath - (Avoid HIToolbox: ignoring exception 'CoreData could not fulfill a fault for XXX that raised inside Carbon event dispatch) */ - self.lastSelectionIndexPath = [folderTreeController selectionIndexPath]; - [folderTreeController setSelectionIndexPath:nil]; - - /* Save snippets */ - [self saveStoreFile]; - - /* Send Notification */ - [[NSNotificationCenter defaultCenter] postNotificationName:CMSnippetEditorWillCloseNotification - object:nil]; -} - -- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window -{ -// NSLog(@"windowWillReturnUndoManager: %@", [snippetsController.managedObjectContext undoManager]); - - return [snippetsController.managedObjectContext undoManager]; -} - -#pragma mark - NSToolbarItemValidation Protocol - - -- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem -{ - NSString *itemIdentifier = [theItem itemIdentifier]; - - if ([itemIdentifier isEqualToString:ADD_SNIPPET_IDENTIFIER]) { - return (0 < [[folderTreeController selectedNodes] count]); - } - else if ([itemIdentifier isEqualToString:CHECK_SNIPPET_IDENTIFIER]) { - return (0 < [[snippetArrayController selectedObjects] count]); - } - - return YES; -} - -#pragma mark - NSOutlineViewDelegate Protocol - - -- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item; -{ - // don't allow special group nodes (Devices and Places) to be selected - FolderNode* node = [item representedObject]; - return (![self isSpecialGroup:node]); -} - -- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - NSCell* returnCell = [tableColumn dataCell]; - - if ([[tableColumn identifier] isEqualToString:kImageAndTextCellColumn]) - { - // we are being asked for the cell for the single and only column - FolderNode* node = [item representedObject]; - if ([node nodeIcon] == nil && [[node nodeTitle] length] == 0) - returnCell = separatorCell; - } - - return returnCell; -} - -// ------------------------------------------------------------------------------- -// shouldEditTableColumn:tableColumn:item -// -// Decide to allow the edit of the given outline view "item". -// ------------------------------------------------------------------------------- -- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - BOOL result = YES; - - item = [item representedObject]; - if ([self isSpecialGroup:item]) - { - result = NO; // don't allow special group nodes to be renamed - } - else - { - if ([[item urlString] isAbsolutePath]) { - result = NO; // don't allow file system objects to be renamed - } - } - - return result; -} - -- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - if ([[tableColumn identifier] isEqualToString:kImageAndTextCellColumn]) - { - // we are displaying the single and only column - if ([cell isKindOfClass:[ImageAndTextCell class]]) - { - item = [item representedObject]; - if (item) - { - if ([item isLeaf]) - { - [item setNodeIcon:folderImage]; - -// BOOL isEnabled = [item isEnabled]; -// NSLog(@"isEnabled: %d", isEnabled); -// [cell setEnabled:isEnabled]; -//// NSLog(@"cell: %d", [cell isEnabled]); - -// // does it have a URL string? -// NSString *urlStr = [item urlString]; -// if (urlStr) -// { -// if ([item isLeaf]) -// { -// [item setNodeIcon:snippetImage]; -// } -// else -// { -// [item setNodeIcon:folderImage]; -// } -// } -// else -// { -// // it's a separator, don't bother with the icon -// } - } - else - { - // check if it's a special folder (DEVICES or PLACES), we don't want it to have an icon - if ([self isSpecialGroup:item]) - { - [item setNodeIcon:nil]; - } - else - { - // it's a folder, use the folderImage as its icon - [item setNodeIcon:folderImage]; - } - } - } - - // set the cell's image - [(ImageAndTextCell*)cell setImage:[item nodeIcon]]; - - BOOL isEnabled = [item isEnabled]; -// NSLog(@"%@ isEnabled: %d, %d", [item nodeTitle], isEnabled, [cell isHighlighted]); - [cell setEnabled:isEnabled]; - } - } -} - --(BOOL)outlineView:(NSOutlineView*)outlineView isGroupItem:(id)item -{ - if ([self isSpecialGroup:[item representedObject]]) - { - return YES; - } - else - { - return NO; - } -} - -//- (void)outlineViewItemDidCollapse:(NSNotification *)notification -//{ -//// NSLog(@"collapse: %@", notification); -//// NSLog(@"%@", [folderTreeController selectionIndexPath]); -// -// [addSnippetToolbarItem setEnabled:YES]; -//} - -#pragma mark - NSOutlineViewDataSource Protocol - - -- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard -{ -// NSLog(@"items: %@", items); - - NSArray *draggedTypes = [NSArray arrayWithObject:kDraggedDataType]; - [pboard declareTypes:draggedTypes owner:self]; - - self.draggedNodes = items; - - return YES; -} - -- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index -{ -// NSLog(@"validateDrop: %@, item: %@, childIndex: %d", info, [[item representedObject] nodeTitle], index); - - NSPasteboard *pboard = [info draggingPasteboard]; - NSArray *draggedTypes = [NSArray arrayWithObject:kDraggedDataType]; - - if (![pboard availableTypeFromArray:draggedTypes]) { - return NSDragOperationNone; - } - - id draggindSource = [info draggingSource]; - - if ((draggindSource == outlineView) && - (index != NSOutlineViewDropOnItemIndex)) { - if (![item indexPath]) { - /* Not move to root path */ - return NSDragOperationNone; - } - return NSDragOperationMove; - } - else if ((draggindSource == snippetTableView) && - (index == NSOutlineViewDropOnItemIndex)) { - if (![[item representedObject] folder]) { - /* Not drag to root folder */ - return NSDragOperationNone; - } - return NSDragOperationGeneric; - } - - return NSDragOperationNone; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index -{ -// NSLog(@"acceptDrop item: %@, childIndex: %d", [[item representedObject] nodeTitle], index); - - id draggingSource = [info draggingSource]; - - if (draggingSource == outlineView) { - if (self.draggedNodes == nil || ![self.draggedNodes count]) { - return NO; - } - - NSArray *treeNodes = self.draggedNodes; - [draggedNodes release], draggedNodes = nil; - - NSIndexPath *targetIndexPath; - - if (item) { - targetIndexPath = [[item indexPath] indexPathByAddingIndex:index]; - } - else { - targetIndexPath = [NSIndexPath indexPathWithIndex:index]; - } -// NSLog(@"targetIndexPath: %@", targetIndexPath); - - NSIndexPath *draggedNodeIndexPath = [[treeNodes objectAtIndex:0] indexPath]; - - if ([draggedNodeIndexPath compare:targetIndexPath] == NSOrderedSame) { - return NO; - } - - NSUInteger draggedNodeIndex = [draggedNodeIndexPath lastIndex]; - NSUInteger lowerIndex = (index < draggedNodeIndex) ? index : draggedNodeIndex; - - [folderTreeController moveNodes:treeNodes toIndexPath:targetIndexPath]; - [self _renumberFoldersFromIndex:lowerIndex]; - -// [self _inspectAllFolders]; // temp!!! - } - else if (draggingSource == snippetTableView) { - /* drag snippets to a folder */ - NSPasteboard *pboard = [info draggingPasteboard]; - NSData *data = [pboard dataForType:kDraggedDataType]; - NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; - [snippetArrayController setSelectionIndexes:rowIndexes]; -// NSLog(@"rowIndexes: %@", rowIndexes); - - NSArray *selectedObjects = [snippetArrayController selectedObjects]; - - if (![selectedObjects count]) { - return NO; - } - - NSManagedObject *firstSnippet = [selectedObjects objectAtIndex:0]; - NSUInteger indexOfFirstSnippet = [[firstSnippet valueForKey:kIndex] unsignedIntegerValue]; - NSManagedObject *sourceFolder = [firstSnippet valueForKey:kFolder]; -// NSLog(@"indexOfFirstSnippet: %d", indexOfFirstSnippet); -// NSLog(@"sourceFolder: %@", sourceFolder); - - FolderNode *destFolderNode = [item representedObject]; - NSManagedObject *destFolder = [destFolderNode folder]; - NSInteger snippetsCount = [[destFolder valueForKeyPath:@"snippets.@count"] integerValue]; -// NSLog(@"folder: %@", folder); - - /* Move snippets to destination folder */ - for (NSManagedObject *snippet in selectedObjects) { - [snippet setValue:destFolder forKey:kFolder]; - [snippet setValue:[NSNumber numberWithInteger:snippetsCount] forKey:kIndex]; - snippetsCount++; - } - - [folderTreeController rearrangeObjects]; - - [self _renumberSnippetsOfFolder:sourceFolder fromIndex:indexOfFirstSnippet]; - -// [self _inspectAllSnippetsAtSelection]; // temp!!! - } - - return YES; -} - -#pragma mark - NSTableView - - -- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex -{ - if ([[aTableColumn identifier] isEqualToString:kImageAndTextCellColumn]) { - // we are displaying the single and only column - if ([aCell isKindOfClass:[ImageAndTextCell class]]) { - NSImage *icon = nil; - - if (aTableView == snippetTableView) { - icon = snippetImage; - } - else { - // it's a folder, use the folderImage as its icon - icon = folderImage; - } - - // set the cell's image - [(ImageAndTextCell *)aCell setImage:icon]; - } - } -} - -#pragma mark - NSTableViewDataSource protocol - - -- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard -{ - // NSLog(@"aTableView: %@", aTableView); - - NSArray *draggedTypes = [NSArray arrayWithObject:kDraggedDataType]; - [pboard declareTypes:draggedTypes owner:self]; - - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; - [pboard setData:data forType:kDraggedDataType]; - return YES; -} - -- (NSDragOperation)tableView:(NSTableView *)aTableView validateDrop:(id < NSDraggingInfo >)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation -{ - // NSLog(@"validate drop: %d", operation); - - NSPasteboard *pboard = [info draggingPasteboard]; - NSArray *draggedTypes = [NSArray arrayWithObject:kDraggedDataType]; - id draggingSource = [info draggingSource]; - - if ([pboard availableTypeFromArray:draggedTypes]) { - if (aTableView == draggingSource) { - if (operation == NSTableViewDropAbove) { - return NSDragOperationMove; - } - } - else if (draggingSource == snippetTableView - && operation == NSTableViewDropOn) { - return NSDragOperationGeneric; - // return NSDragOperationEvery; - } - } - - return NSDragOperationNone; -} - -- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id < NSDraggingInfo >)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation -{ - id draggingSource = [info draggingSource]; - - NSPasteboard *pboard = [info draggingPasteboard]; - NSData *data = [pboard dataForType:kDraggedDataType]; - NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; -// NSLog(@"rowIndexes: %@", rowIndexes); - [snippetArrayController setSelectionIndexes:rowIndexes]; - - NSArray *arrangedObjects = [snippetArrayController arrangedObjects]; - NSArray *draggedObjects = [snippetArrayController selectedObjects]; - - if (aTableView == draggingSource) { - if (row == [rowIndexes firstIndex]) { - return NO; - } - -// [snippetArrayController setAutomaticallyRearrangesObjects:NO]; - - NSUInteger first = (row < [rowIndexes firstIndex]) ? row : [rowIndexes firstIndex]; - NSUInteger last = (row > [rowIndexes lastIndex]) ? row : [rowIndexes lastIndex]; -// NSLog(@"first: %d, last: %d, row: %d", first, last, row); - - NSUInteger index = first; - NSUInteger upperThanRowCount = 0; - while (index != NSNotFound) { -// NSLog(@"index: %d", index); - id object = [arrangedObjects objectAtIndex:index]; - NSUInteger oldIndex = [[object valueForKey:kIndex] unsignedIntegerValue]; - - if (compare(oldIndex, row) == -1) { - upperThanRowCount++; - } - - index = [rowIndexes indexGreaterThanIndex:index]; - } -// NSLog(@"upperThanRowCount: %d", upperThanRowCount); - - /* numbering non dragged objects */ - NSUInteger newIndex = 0; - if (0 < first) { - newIndex = [[[arrangedObjects objectAtIndex:first] valueForKey:kIndex] unsignedIntegerValue]; - } -// NSLog(@"newIndex: %d", newIndex); - - [snippetArrayController setAutomaticallyRearrangesObjects:NO]; - - for (NSUInteger i = first; i < last; i++) { - NSUInteger lowerCount = 0; - if ([rowIndexes containsIndex:i]) { -// NSLog(@"rowIndexes contains %d", i); - continue; - } - - if (row <= i) { - lowerCount = numberOfLowerIndexes(rowIndexes, i, row); -// NSLog(@"lowerCount: %d", lowerCount); - } - - id object = [arrangedObjects objectAtIndex:i]; -// NSLog(@"object: %@", object); -// NSLog(@"newIndex: %d", newIndex); - [object setValue:[NSNumber numberWithUnsignedInteger:newIndex+lowerCount] forKey:kIndex]; - newIndex++; - } - - /* numbering dragged objects */ - NSUInteger i = row - upperThanRowCount; - for (id object in draggedObjects) { -// NSLog(@"dragged object: %d", i); - [object setValue:[NSNumber numberWithUnsignedInteger:i] forKey:kIndex]; - i++; - } - - /* after move up */ - if (row < first) { - newIndex = row + [rowIndexes count]; - for (NSUInteger i = row; i < last; i++) { - if ([rowIndexes containsIndex:i]) { -// NSLog(@"rowIndexes contains %d", i); - continue; - } - - id object = [arrangedObjects objectAtIndex:i]; - [object setValue:[NSNumber numberWithUnsignedInteger:newIndex] forKey:kIndex]; - newIndex++; - } - } - - [snippetArrayController setAutomaticallyRearrangesObjects:YES]; - } - - // [sourceArrayController renumber]; - return YES; -} - -- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView -{ - return 0; -} - -#pragma mark - NSXMLParser - - -- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict -{ - // NSLog(@"didStartElement: %@", elementName); - - if (currentElementContent) { - [currentElementContent release]; - } - currentElementContent = [[NSMutableString alloc] init]; - - if ([elementName isEqualToString:kRootElement]) { - if (foldersFromFile) { - [foldersFromFile release]; - } - foldersFromFile = [[NSMutableArray alloc] init]; - } - else if ([elementName isEqualToString:kFolderElement]) { - if (currentFolder) { - [currentFolder release]; - } - currentFolder = [[NSMutableDictionary alloc] initWithObjectsAndKeys: - kFolderElement, kType, - [NSMutableArray array], kSnippets, - nil]; - } - else if ([elementName isEqualToString:kSnippetElement]) { - if (currentSnippet) { - [currentSnippet release]; - } - currentSnippet = [[NSMutableDictionary alloc] initWithObjectsAndKeys: - kSnippetElement, kType, - nil]; - } -} - -- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string -{ - // NSLog(@"string: %@", string); - [currentElementContent appendString:string]; -} - -- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName -{ - // NSLog(@"didEndElement: %@", elementName); - - /* Collection */ - if ([elementName isEqualToString:kFolderElement]) { - [foldersFromFile addObject:currentFolder]; - [currentFolder release], currentFolder = nil; - return; - } - else if ([elementName isEqualToString:kSnippetElement]) { - [[currentFolder objectForKey:kSnippets] addObject:currentSnippet]; - [currentSnippet release], currentSnippet = nil; - return; - } - - /* Characters */ - if ([elementName isEqualToString:kTitleElement]) { - if (!currentElementContent) { - return; - } - NSMutableDictionary *currentItem = (currentSnippet) ? currentSnippet : currentFolder; - [currentItem setObject:currentElementContent forKey:elementName]; - } - else if ([elementName isEqualToString:kContentElement]) { - if (!currentElementContent) { - return; - } - [currentSnippet setObject:currentElementContent forKey:elementName]; - } - - [currentElementContent release], currentElementContent = nil; -} - -#pragma mark - -#pragma mark Actions - -- (IBAction)addFolder:(id)sender -{ - if (![self _endEditingForWindow]) { - return; - } - - NSInteger lastIndex = [self _lastIndexOfSnippetFolders]; - lastIndex++; - FolderNode *newNode = [self _makeFolderNodeWithIndex:lastIndex]; - - NSUInteger indexes[2] = {0, lastIndex}; - NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexes length:2]; - [folderTreeController insertObject:newNode atArrangedObjectIndexPath:indexPath]; - - NSInteger columnIndex = 0; - NSInteger rowIndex = lastIndex + 1; - [folderOutlineView editColumn:columnIndex - row:rowIndex - withEvent:nil - select:YES]; -} - -- (IBAction)removeFolder:(id)sender -{ - NSArray *selectedObjects = [folderTreeController selectedObjects]; - NSArray *selectionIndexPaths = [folderTreeController selectionIndexPaths]; - -// NSLog(@"selection: %@", selectionIndexPaths); - - if ([selectionIndexPaths count] == 0) { - return; - } - - NSUInteger indexToRemove = [[selectionIndexPaths objectAtIndex:0] indexAtPosition:1]; -// NSLog(@"indexToRemove: %d", indexToRemove); - - [self _removeFolderNodes:selectedObjects]; - [folderTreeController removeObjectsAtArrangedObjectIndexPaths:selectionIndexPaths]; - - [self _renumberFoldersFromIndex:indexToRemove]; -} - -- (IBAction)toggleFolderEnabled:(id)sender -{ -// NSLog(@"toggleFolderEnabled: %@", [folderTreeController selectedNodes]); - - NSArray *selectedObjects = [folderTreeController selectedObjects]; - - if (![selectedObjects count]) { - return; - } - - BOOL isEnabled = [[selectedObjects objectAtIndex:0] isEnabled]; - - for (FolderNode *folderNode in selectedObjects) { - [folderNode setIsEnabled:!isEnabled]; - } - -// [self _inspectAllFolders]; - -// NSIndexSet *indexes = [folderOutlineView selectedRowIndexes]; - - /* Deselect all to avoid a display glitch */ - [folderOutlineView deselectAll:self]; - -// [folderOutlineView selectRowIndexes:indexes byExtendingSelection:YES]; - -// NSUInteger index = [indexes firstIndex]; -// -// while (index != NSNotFound) { -// NSRect rect = [folderOutlineView rectOfRow:index]; -// [folderOutlineView drawRow:index clipRect:rect]; -// index = [indexes indexGreaterThanIndex:index]; -// } - - [folderOutlineView display]; -} - -- (IBAction)addSnippet:(id)sender -{ - [self _endEditingForWindow]; - - NSManagedObject *managedObject = [snippetArrayController newObject]; -// NSLog(@"managedObject: %@", managedObject); - [snippetArrayController addObject:managedObject]; - - NSArray *arrangedObjects = [snippetArrayController arrangedObjects]; - NSInteger rowIndex = [arrangedObjects indexOfObject:managedObject]; -// NSLog(@"starting edit of %@ in rowIndex %d", managedObject, rowIndex); - [managedObject release], managedObject = nil; - - NSInteger columnIndex = 0; // the 'title' column - [snippetTableView editColumn:columnIndex - row:rowIndex - withEvent:nil - select:YES]; -} - -//- (IBAction)removeSnippet:(id)sender -//{ -// NSManagedObjectContext *moc = [snippetsController managedObjectContext]; -// NSArray *selectedObjects = [snippetArrayController selectedObjects]; -// [snippetArrayController removeObjects:selectedObjects]; -// -// for (NSManagedObject *snippet in selectedObjects) { -// [moc deleteObject:snippet]; -// } -//} - -- (IBAction)toggleSnippetEnabled:(id)sender -{ - NSArray *selectedObjects = [snippetArrayController selectedObjects]; - - if (![selectedObjects count]) { - return; - } - -// NSLog(@"selectedObjects: %@", selectedObjects); - - BOOL isEnabled = [[[selectedObjects objectAtIndex:0] valueForKey:kEnabled] boolValue]; - NSNumber *newEnabled = [NSNumber numberWithBool:!isEnabled]; -// NSLog(@"isEnabled: %d", isEnabled); - - for (NSManagedObject *snippet in selectedObjects) { - [snippet setValue:newEnabled forKey:kEnabled]; - } -} - -- (IBAction)importSnippets:(id)sender -{ - NSArray *fileTypes = [NSArray arrayWithObject:kXMLFileType]; - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - [openPanel setAllowsMultipleSelection:NO]; - - NSInteger returnCode; - - if ([openPanel respondsToSelector:@selector( setDirectoryURL: )]) { - [openPanel setDirectoryURL:[NSURL fileURLWithPath:NSHomeDirectory()]]; - [openPanel setAllowedFileTypes:fileTypes]; - returnCode = [openPanel runModal]; - } - else { - /* Deprecated in Mac OS X 10.6 */ - returnCode = [openPanel runModalForDirectory:NSHomeDirectory() - file:nil - types:fileTypes]; - } - - if (returnCode != NSOKButton) { - return; - } - - NSArray *fileURLs = [openPanel URLs]; - - if (![fileURLs count]) { - return; - } - - NSURL *url = [fileURLs objectAtIndex:0]; - - if (!url) { - return; - } - - [self _parseXMLFileAtURL:url]; - - if (foldersFromFile) { -// NSLog(@"parsed: %@", foldersFromFile); - [self _addImportedFolders:foldersFromFile]; - [foldersFromFile release], foldersFromFile = nil; - } -} - -- (IBAction)exportSnippets:(id)sender -{ - NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:kIndex ascending:YES]; - NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor]; - [descriptor release], descriptor = nil; - - NSArray *arrangedObjects = [folderArrayController arrangedObjects]; -// NSLog(@"arrangedObjects: %@", arrangedObjects); - - arrangedObjects = [arrangedObjects sortedArrayUsingDescriptors:sortDescriptors]; - - NSXMLElement *rootElement = (NSXMLElement *)[NSXMLNode elementWithName:kRootElement]; - - for (NSManagedObject *folder in arrangedObjects) { - NSString *folderTitle = [folder valueForKey:kTitle]; - NSArray *snippets = [[[folder valueForKey:kSnippets] allObjects] sortedArrayUsingDescriptors:sortDescriptors]; - - NSXMLElement *folderElement = (NSXMLElement *)[NSXMLNode elementWithName:kFolderElement]; - - [folderElement addChild:[NSXMLNode elementWithName:kTitleElement stringValue:folderTitle]]; - - NSXMLElement *snippetsElement = (NSXMLElement *)[NSXMLNode elementWithName:kSnippetsElement]; - - for (NSManagedObject *snippet in snippets) { - NSString *snippetTitle = [snippet valueForKey:kTitle]; - NSString *content = [snippet valueForKey:kContent]; - - NSXMLElement *snippetElement = (NSXMLElement *)[NSXMLNode elementWithName:kSnippetElement]; - [snippetElement addChild:[NSXMLNode elementWithName:kTitleElement stringValue:snippetTitle]]; - - NSXMLElement *contentElement = [[NSXMLNode alloc] initWithKind:NSXMLElementKind - options:NSXMLNodePreserveWhitespace]; - [contentElement setName:kContentElement]; - [contentElement setStringValue:content]; - - [snippetElement addChild:contentElement]; - [contentElement release], contentElement = nil; - - [snippetsElement addChild:snippetElement]; - } - - [folderElement addChild:snippetsElement]; - [rootElement addChild:folderElement]; - } - - NSXMLDocument *xmlDocument = [[[NSXMLDocument alloc] initWithRootElement:rootElement] autorelease]; - [xmlDocument setVersion:@"1.0"]; - [xmlDocument setCharacterEncoding:@"UTF-8"]; - - // NSLog(@"xml: %@", xmlDocument); - - NSSavePanel *savePanel = [NSSavePanel savePanel]; - [savePanel setAccessoryView:nil]; - [savePanel setCanSelectHiddenExtension:YES]; - [savePanel setRequiredFileType:kXMLFileType]; - - NSInteger returnCode; - - if ([savePanel respondsToSelector:@selector( setDirectoryURL: )]) { - [savePanel setDirectoryURL:[NSURL fileURLWithPath:NSHomeDirectory()]]; - [savePanel setNameFieldStringValue:DEFAULT_EXPORT_FILENAME]; - returnCode = [savePanel runModal]; - } - else { - /* Deprecated in Mac OS X 10.6 */ - returnCode = [savePanel runModalForDirectory:NSHomeDirectory() file:DEFAULT_EXPORT_FILENAME]; - } - - if (returnCode == NSOKButton) { - NSData *data = [xmlDocument XMLDataWithOptions:NSXMLNodePrettyPrint]; - if (![data writeToFile:[savePanel filename] atomically:YES]) { - NSBeep(); - NSRunAlertPanel(nil, - NSLocalizedString(@"Could not write document out...", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - return; - } - } -} - -#pragma mark - -#pragma mark Public - -/* path through snippetsController */ -- (BOOL)saveStoreFile -{ - return [snippetsController saveStoreFile]; -} - -#pragma mark - -#pragma mark Private - -- (void)_prepareSourceList -{ - NSMutableArray *children = [[NSMutableArray alloc] init]; - FolderNode *node; - - for (NSManagedObject *folder in [snippetsController folders]) { - node = [[FolderNode alloc] initLeaf]; // doesn't contain children - [node setNodeTitle:[folder valueForKey:kTitle]]; - [node setFolder:folder]; - [children addObject:node]; - [node release], node = nil; - } - - FolderNode *rootNode = [[FolderNode alloc] init]; - [rootNode setNodeTitle:GROUP_NAME]; - [rootNode setChildren:children]; - [children release], children = nil; - - [self willChangeValueForKey:@"sourceList"]; - self.sourceList = [NSMutableArray arrayWithObject:rootNode]; - [self didChangeValueForKey:@"sourceList"]; - - [rootNode release], rootNode = nil; -} - -//// ------------------------------------------------------------------------------- -//// selectParentFromSelection: -//// -//// Take the currently selected node and select its parent. -//// ------------------------------------------------------------------------------- -//- (void)selectParentFromSelection -//{ -// if ([[folderTreeController selectedNodes] count] > 0) -// { -// NSTreeNode* firstSelectedNode = [[folderTreeController selectedNodes] objectAtIndex:0]; -// NSTreeNode* parentNode = [firstSelectedNode parentNode]; -// if (parentNode) -// { -// // select the parent -// NSIndexPath* parentIndex = [parentNode indexPath]; -// [folderTreeController setSelectionIndexPath:parentIndex]; -// } -// else -// { -// // no parent exists (we are at the top of tree), so make no selection in our outline -// NSArray* selectionIndexPaths = [folderTreeController selectionIndexPaths]; -// [folderTreeController removeSelectionIndexPaths:selectionIndexPaths]; -// } -// } -//} - -// ------------------------------------------------------------------------------- -// isSpecialGroup: -// ------------------------------------------------------------------------------- -- (BOOL)isSpecialGroup:(FolderNode *)groupNode -{ - return ([groupNode nodeIcon] == nil && - [[groupNode nodeTitle] isEqualToString:GROUP_NAME]); -} - -- (void)_expandGroups -{ - id item = [folderOutlineView itemAtRow:0]; - if ([folderOutlineView isExpandable:item] && ![folderOutlineView isItemExpanded:item]) { - [folderOutlineView expandItem:item]; - - NSUInteger indexes[2] = {0, 0}; - NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexes length:2]; - [folderTreeController setSelectionIndexPath:indexPath]; - } -} - -- (void)_cacheIconImages -{ - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSImage *image; - - if (image = [ws iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)]) { - [self setFolderImage:image]; - [folderImage setSize:NSMakeSize(kIconSizeInTableView,kIconSizeInTableView)]; - } - - if (image = [ws iconForFileType:NSFileTypeForHFSTypeCode(kClippingTextTypeIcon)]) { - [self setSnippetImage:image]; - [snippetImage setSize:NSMakeSize(kIconSizeInTableView,kIconSizeInTableView)]; - } -} - -- (void)_moveUpDraggedObjects:(NSArray *)draggedObjects withIndexes:(NSIndexSet *)rowIndexes -{ - NSUInteger index = [rowIndexes firstIndex]; - for (NSManagedObject *object in draggedObjects) { -// NSLog(@"index: %d", index); - - [object setValue:[NSNumber numberWithUnsignedInteger:index] forKey:kIndex]; - - if ([rowIndexes indexGreaterThanIndex:index] != NSNotFound) { - index = [rowIndexes indexGreaterThanIndex:index]; - } - } -} - -- (BOOL)_endEditingForWindow -{ - BOOL editingEnded = [self.window makeFirstResponder:self.window]; - if (!editingEnded) { - NSRunAlertPanel(nil, - NSLocalizedString(@"Unable to end editing", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - return NO; - } - - return YES; -} - -#pragma mark - Folder - - -- (id)_rootTreeNodeForSnippetFolder -{ - NSArray *rootNodes = [[folderTreeController arrangedObjects] childNodes]; - if (!rootNodes || ![rootNodes count]) { - return nil; - } - - return [rootNodes objectAtIndex:0]; -} - -- (NSArray *)_treeNodesForSnippetFolder -{ - id rootNode = [self _rootTreeNodeForSnippetFolder]; - if (rootNode == nil) { - return nil; - } - - return [rootNode childNodes]; -} - -- (NSInteger)_lastIndexOfSnippetFolders -{ - NSArray *snippetFolders = [self _treeNodesForSnippetFolder]; - - if ((snippetFolders == nil) - || ([snippetFolders count] == 0)) { - return -1; - } - - return [[[[[snippetFolders lastObject] representedObject] folder] valueForKey:kIndex] integerValue]; -} - -- (FolderNode *)_makeFolderNodeForFolder:(NSManagedObject *)folder -{ - FolderNode *node = [[FolderNode alloc] initLeaf]; - [node setNodeTitle:[folder valueForKey:kTitle]]; - [node setFolder:folder]; - - return [node autorelease]; -} - -- (FolderNode *)_makeFolderNodeWithIndex:(NSInteger)index -{ - NSManagedObjectContext *moc = [snippetsController managedObjectContext]; - NSManagedObjectModel *mom = [snippetsController managedObjectModel]; - NSEntityDescription *entity = [[mom entitiesByName] objectForKey:kFolderEntity]; - NSManagedObject *folder = [[NSManagedObject alloc] initWithEntity:entity - insertIntoManagedObjectContext:moc]; - [folder setValue:[NSNumber numberWithInteger:index] forKey:kIndex]; - - FolderNode *node = [[FolderNode alloc] initLeaf]; - [node setNodeTitle:[folder valueForKey:kTitle]]; - [node setFolder:folder]; - [folder release], folder = nil; - - return [node autorelease]; -} - -- (void)_removeFolderNodes:(NSArray *)folderNodes -{ - NSManagedObjectContext *moc = [snippetsController managedObjectContext]; - NSManagedObject *folder; - - for (FolderNode *folderNode in folderNodes) { - folder = [folderNode folder]; -// NSLog(@"folder: %@", folder); - [moc deleteObject:folder]; - } -} - -- (void)_renumberAllFolders -{ - NSUInteger i = 0; - for (NSTreeNode *firstTreeNode in [self _treeNodesForSnippetFolder]) { - FolderNode *folderNode = [firstTreeNode representedObject]; -// NSLog(@"item: %d", [folderNode index]); - [folderNode setIndex:i]; - i++; - -// NSLog(@"item: %d", [folderNode index]); - } -} - -- (void)_renumberFoldersFromIndex:(NSUInteger)index -{ - NSArray *treeNodes = [self _treeNodesForSnippetFolder]; - NSUInteger folderSize = [treeNodes count]; - NSTreeNode *firstTreeNode; - FolderNode *folderNode; - - for (NSUInteger i = index; i < folderSize; i++) { - firstTreeNode = [treeNodes objectAtIndex:i]; - folderNode = [firstTreeNode representedObject]; -// NSLog(@"item: %d", [folderNode index]); - [folderNode setIndex:i]; - -// NSLog(@"item: %d", [folderNode index]); - } -} - -- (void)_renumberSnippetsOfFolder:(NSManagedObject *)folder fromIndex:(NSUInteger)index -{ - NSMutableSet *snippets = [[[folder mutableSetValueForKey:kSnippets] mutableCopy] autorelease]; - if (![snippets count]) { - return; - } - - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K > %@", - kIndex, [NSNumber numberWithUnsignedInteger:index]]; - [snippets filterUsingPredicate:predicate]; - -// NSLog(@"snippets: %@", snippets); - - if (![snippets count]) { - return; - } - - NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:kIndex ascending:YES]; - NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor]; - [sortDescriptor release], sortDescriptor = nil; - - NSArray *filteredSnippets; - - if ([snippets respondsToSelector:@selector( sortedArrayUsingDescriptors: )]) { - /* Mac OS X 10.6 or highter */ - filteredSnippets = [snippets sortedArrayUsingDescriptors:descriptors]; - } - else { - filteredSnippets = [[snippets allObjects] sortedArrayUsingDescriptors:descriptors]; - } - -// NSLog(@"filteredSnippets: %@", filteredSnippets); - - NSUInteger newIndex = index; - - for (NSManagedObject *snippet in filteredSnippets) { - [snippet setValue:[NSNumber numberWithUnsignedInteger:newIndex] forKey:kIndex]; - newIndex++; - } -} - -/* for debug */ -- (void)_inspectAllFolders -{ - for (NSTreeNode *treeNode in [self _treeNodesForSnippetFolder]) { - FolderNode *folderNode = [treeNode representedObject]; - NSManagedObject *folder = [folderNode folder]; - NSLog(@"%d: [%@] %@\n folder: %@", - [folderNode index], - ([folderNode isEnabled]) ? @"ON " : @"OFF", - [folderNode nodeTitle], - folder); - } -} - -- (void)_inspectAllSnippetsAtSelection -{ - NSArray *selectedObjects = [snippetArrayController selectedObjects]; - - if (![selectedObjects count]) { - NSLog(@"No selected objects"); - return; - } - - for (NSManagedObject *snippet in selectedObjects) { - NSLog(@"%d: [%@] %@", - [[snippet valueForKey:kIndex] unsignedIntegerValue], - ([snippet valueForKey:kEnabled]) ? @"ON " : @"OFF", - [snippet valueForKey:kTitle]); - } -} - -#pragma mark - Import - - -- (void)_parseXMLFileAtURL:(NSURL *)url -{ - NSXMLParser *xmlParser = [[[NSXMLParser alloc] initWithContentsOfURL:url] autorelease]; - [xmlParser setDelegate:self]; - NSInteger returnCode = [xmlParser parse]; - - if (!returnCode) { - NSRunAlertPanel(nil, - NSLocalizedString(@"Failed to parse XML file", nil), - NSLocalizedString(@"OK", nil), - nil, - nil); - return; - } -} - -- (void)_addImportedFolders:(NSArray *)folders -{ - if (![self _endEditingForWindow]) { - return; - } - - NSInteger folderIndex = [self _lastIndexOfSnippetFolders]; - NSIndexPath *indexPath; - FolderNode *folderNode; - - for (NSDictionary *folder in folders) { - folderIndex++; - - NSManagedObject *newFolder = [folderArrayController newObject]; - [newFolder setValue:[folder objectForKey:kTitle] forKey:kTitle]; - [newFolder setValue:[NSNumber numberWithInteger:folderIndex] forKey:kIndex]; - - NSUInteger i = 0; - for (NSDictionary *snippet in [folder objectForKey:kSnippets]) { -// NSLog(@"snippet: %@", snippet); - - NSManagedObject *newSnippet = [snippetArrayController newObject]; - [newSnippet setValue:[NSNumber numberWithUnsignedInteger:i] forKey:kIndex]; - [newSnippet setValue:[snippet objectForKey:kTitle] forKey:kTitle]; - [newSnippet setValue:[snippet objectForKey:kContent] forKey:kContent]; - [newSnippet setValue:newFolder forKey:kFolder]; // to-one relationship - [[newFolder valueForKey:kSnippets] addObject:newSnippet]; // inverse relationship - [newSnippet release], newSnippet = nil; - i++; - } - - [folderArrayController addObject:newFolder]; - - folderNode = [self _makeFolderNodeForFolder:newFolder]; - [newFolder release], newFolder = nil; - - NSUInteger indexes[2] = {0, folderIndex}; - indexPath = [[NSIndexPath alloc] initWithIndexes:indexes length:2]; - [folderTreeController insertObject:folderNode atArrangedObjectIndexPath:indexPath]; - [indexPath release], indexPath = nil; - } -} - -- (void)_handleNSManagedObjectContextObjectsDidChange:(NSNotification *)aNotification -{ -// NSLog(@"note: %@", [aNotification userInfo]); - - NSUndoManager *um = [snippetsController.managedObjectContext undoManager]; - -// NSLog(@"isUndoing: %d, isRedoing: %d", [um isUndoing], [um isRedoing]); - - if (![um isUndoing] && ![um isRedoing]) { - return; - } - - NSIndexPath *selectionIndexPath = [folderTreeController selectionIndexPath]; - - [self _prepareSourceList]; - [self _expandGroups]; - -// [folderTreeController rearrangeObjects]; - -// [folderTreeController setSelectionIndexPath:nil]; - [folderTreeController setSelectionIndexPath:selectionIndexPath]; -} - -@end diff --git a/Source/SnippetsController.h b/Source/SnippetsController.h deleted file mode 100644 index 8c85d5e..0000000 --- a/Source/SnippetsController.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// SnippetsController.h -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import - - -@interface SnippetsController : NSObject -{ - NSPersistentStoreCoordinator *persistentStoreCoordinator; - NSManagedObjectModel *managedObjectModel; - NSManagedObjectContext *managedObjectContext; -} - -+ (SnippetsController *)sharedInstance; - -+ (NSArray *)sortDescriptors; - -- (NSPersistentStoreCoordinator *)persistentStoreCoordinator; -- (NSManagedObjectModel *)managedObjectModel; -- (NSManagedObjectContext *)managedObjectContext; - - -- (BOOL)saveStoreFile; -- (BOOL)removeSnippet:(NSManagedObject *)snippet; -- (NSArray *)folders; -//- (NSArray *)snippets; -//- (NSArray *)snippetsInFolder:(NSManagedObject *)aFolder; - -@end diff --git a/Source/SnippetsController.m b/Source/SnippetsController.m deleted file mode 100644 index 0cda92d..0000000 --- a/Source/SnippetsController.m +++ /dev/null @@ -1,235 +0,0 @@ -// -// SnippetsController.m -// ClipMenu -// -// Created by naotaka on 08/10/30. -// Copyright 2008 Naotaka Morimoto. All rights reserved. -// - -#import "SnippetsController.h" -#import "constants.h" -#import "CMUtilities.h" - - -#pragma mark Static variables -static SnippetsController *sharedInstance = nil; - - -@interface SnippetsController () -- (id)_init; -@end - - -@implementation SnippetsController - -#pragma mark Initialize - -+ (void)initialize -{ - if (sharedInstance == nil) { - sharedInstance = [[self alloc] _init]; - } -} - -+ (SnippetsController *)sharedInstance -{ - return [[sharedInstance retain] autorelease]; -} - -+ (NSArray *)sortDescriptors -{ - NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:kIndex ascending:YES] autorelease]; - return [NSArray arrayWithObject:descriptor]; -} - -- (id)_init -{ - self = [super init]; - return self; -} - -- (id)init -{ - NSAssert(self != sharedInstance, @"Should never send init to the singleton instance"); - - [self release]; - [sharedInstance retain]; - return sharedInstance; -} - -- (void)dealloc -{ - [managedObjectContext release], managedObjectContext = nil; - [persistentStoreCoordinator release], persistentStoreCoordinator = nil; - [managedObjectModel release], managedObjectModel = nil; - [super dealloc]; -} - -- (NSPersistentStoreCoordinator *)persistentStoreCoordinator -{ - if (persistentStoreCoordinator) { - return persistentStoreCoordinator; - } - - NSString *path = [CMUtilities applicationSupportFolder]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:path isDirectory:NULL]) { - [fileManager createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:NULL]; - } - - NSString *storePath = [path stringByAppendingPathComponent:kStoreName]; - NSURL *storeURL = [NSURL fileURLWithPath:storePath]; - NSError *error = nil; - - persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; - if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType - configuration:nil - URL:storeURL - options:nil - error:&error]) { - [NSApp presentError:error]; - } - - return persistentStoreCoordinator; -} - -- (NSManagedObjectModel *)managedObjectModel -{ - if (managedObjectModel) { - return managedObjectModel; - } - - managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]; - return managedObjectModel; -} - -- (NSManagedObjectContext *)managedObjectContext -{ - if (managedObjectContext) { - return managedObjectContext; - } - - NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; - if (coordinator) { - managedObjectContext = [[NSManagedObjectContext alloc] init]; - [managedObjectContext setPersistentStoreCoordinator:coordinator]; - } - - return managedObjectContext; -} - -#pragma mark - - -- (BOOL)saveStoreFile -{ -// NSLog(@"saveStoreFile"); - - NSError *error = nil; - BOOL reply = YES; - - if (managedObjectContext) { - if ([managedObjectContext commitEditing]) { - if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { - BOOL errorResult = [NSApp presentError:error]; - if (errorResult == YES) { - reply = NO; - } - else { - NSInteger alertReturn = NSRunAlertPanel(nil, - NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", nil), - NSLocalizedString(@"Quit anyway", nil), - NSLocalizedString(@"Cancel", nil), - nil); - if (alertReturn == NSAlertAlternateReturn) { - reply = NO; - } - } - } - } - else { - reply = NO; - } - } - - return reply; -} - -- (BOOL)removeSnippet:(NSManagedObject *)snippet -{ - NSError *error = nil; -// NSLog(@"its a snippet: %@", snippet); - - [managedObjectContext deleteObject:snippet]; - - if ([managedObjectContext commitEditing]) { - if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { - [NSApp presentError:error]; - return NO; - } - } - -// // temp!!! -// for (NSManagedObject *folder in [self folders]) { -// NSLog(@"folder: %@", folder); -// } - - return YES; -} - -- (NSArray *)folders -{ - NSEntityDescription *entity = [NSEntityDescription entityForName:kFolderEntity - inManagedObjectContext:self.managedObjectContext]; - NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; - [request setEntity:entity]; - -// NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:kIndex ascending:YES]; -// [request setSortDescriptors:[NSArray arrayWithObject:descriptor]]; -// [descriptor release], descriptor = nil; - - [request setSortDescriptors:[[self class] sortDescriptors]]; - - NSError *error = nil; - NSArray *fetchResluts = [self.managedObjectContext executeFetchRequest:request - error:&error]; - if (fetchResluts && [fetchResluts count] > 0) { - return fetchResluts; - } - - return nil; -} - -//- (NSArray *)snippets -//{ -// NSSet *registeredObjects = [[self managedObjectContext] registeredObjects]; -// if (registeredObjects && [registeredObjects count] > 0) { -// return [registeredObjects allObjects]; -// } -// -// return nil; -//} - -//- (NSArray *)snippetsInFolder:(NSManagedObject *)aFolder -//{ -// NSEntityDescription *entity = [NSEntityDescription entityForName:kSnippetEntity -// inManagedObjectContext:[self managedObjectContext]]; -// NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; -// [request setEntity:entity]; -// -// NSPredicate *predicate = [NSPredicate predicateWithFormat:@"title == %@", @"Google"]; -// [request setPredicate:predicate]; -// -// NSError *error = nil; -// NSArray *fetchResluts = [[self managedObjectContext] executeFetchRequest:request -// error:&error]; -// if (fetchResluts && [fetchResluts count] > 0) { -// return fetchResluts; -// } -// -// return nil; -//} - -@end diff --git a/Source/constants.h b/Source/constants.h deleted file mode 100644 index 7f5cc05..0000000 --- a/Source/constants.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * constants.h - * ClipMenu - * - * Created by naotaka on 08/10/18. - * Copyright 2008 Naotaka Morimoto. All rights reserved. - * - */ - -// Appication -#define kApplicationName @"ClipMenu" - -/* Hot Keys */ -//#define kHotKeyForClipMenu @"HotKeyForClipMenu" - -//typedef enum { -// CMHotKeyForClipMenu = 0, -// CMHotKeyForHistory, -// CMHotKeyForSnippets -//} CMHotKey; - -#define kClipMenuIdentifier @"ClipMenu" -#define kHistoryMenuIdentifier @"HistoryMenu" -#define kSnippetsMenuIdentifier @"SnippetsMenu" -#define kActionMenuIdentifier @"ActionMenu" - -#define kSelector @"selector" -#define kBehavior @"behavior" - -#define kEmptyString @"" -#define kSingleSpace @" " -#define kNewLine @"\n" -#define kCarriageReturnAndNewLine @"\r\n" -#define kCarriageReturn @"\r" -#define kTab @"\t" - -#define kPopUpActionMenu @"popUpActionMenu" - -#define kOldKey @"old" -#define kNewKey @"new" - -/* Paths */ -#define kScriptDirectory @"script" -#define kLibraryScriptDirectory @"lib" -#define kActionDirectory @"action" - -/* Filenames */ -#define kClipsSaveDataName @"clips.data" -#define kActionSaveDataName @"actionMenu.data" -#define kJavaScriptExtension @"js" - -#define kStoreName @"Snippets.xml" - -/* Preferences window */ -#define kIconSizeInTableView 16 -#define kImageAndTextCellColumn @"ImageAndTextCellColumn" -#define kDraggedDataType @"DraggedDataType" - -/* Exclude Apps */ -#define kCMBundleIdentifierKey @"bundleIdentifier" -#define kCMNameKey @"name" - -/* Model */ -#define kFolderEntity @"Folder" -#define kSnippetEntity @"Snippet" - -#define kEnabled @"enabled" -#define kIndex @"index" -#define kTitle @"title" -#define kFolder @"folder" -#define kSnippets @"snippets" -#define kContent @"content" -#define kDefaultSnippetName @"untitled snippet" - -/* Folder Node */ -#define GROUP_NAME @"GROUPS" - -/* XML */ -#define kXMLFileType @"xml" - -#define kType @"type" - -#define kRootElement @"folders" -#define kFolderElement @"folder" -#define kSnippetElement @"snippet" -#define kTitleElement @"title" -#define kSnippetsElement @"snippets" -#define kContentElement @"content" diff --git a/Source/main.m b/Source/main.m deleted file mode 100644 index 1126196..0000000 --- a/Source/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// ClipMenu -// -// Created by Naotaka Morimoto on 07/12/01. -// Copyright Naotaka Morimoto 2007. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **) argv); -} diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift new file mode 100644 index 0000000..71e6116 --- /dev/null +++ b/Sources/App/AppDelegate.swift @@ -0,0 +1,54 @@ +import AppKit + +/// Lifecycle hooks that must live in an NSApplicationDelegate rather than the +/// SwiftUI App struct (e.g. applicationWillTerminate, Sparkle delegate). +final class AppDelegate: NSObject, NSApplicationDelegate { + private let runtime = AppRuntime.shared + + @MainActor + func applicationDidFinishLaunching(_ notification: Notification) { + // Ensure persisted settings are hydrated and normalized before services read them. + runtime.settings.reload() + + // Register global hotkeys immediately. This should not depend on + // SwiftData container readiness. + runtime.hotkeyService.register() + + do { + try runtime.loginItemService.setEnabled(runtime.settings.launchAtLogin) + } catch { + // Keep startup resilient when login item registration fails. + } + + startDataServicesWhenReady(retryCount: 10) + } + + @MainActor + private func startDataServicesWhenReady(retryCount: Int) { + guard let modelContext = runtime.modelContainer?.mainContext else { + guard retryCount > 0 else { return } + Task { @MainActor in + try? await Task.sleep(nanoseconds: 100_000_000) + startDataServicesWhenReady(retryCount: retryCount - 1) + } + return + } + + if LegacyMigration.isNeeded { + LegacyMigration.run(in: modelContext) + } + + Task { + runtime.clipsService.start(context: modelContext) + await runtime.snippetService.start(context: modelContext) + await runtime.actionService.start(context: modelContext) + } + } + + func applicationWillTerminate(_ notification: Notification) { + runtime.hotkeyService.unregister() + Task { + runtime.clipsService.stop() + } + } +} diff --git a/Sources/App/AppRuntime.swift b/Sources/App/AppRuntime.swift new file mode 100644 index 0000000..a0d77e4 --- /dev/null +++ b/Sources/App/AppRuntime.swift @@ -0,0 +1,96 @@ +import AppKit +import SwiftData +import SwiftUI + +final class AppRuntime { + static let shared = AppRuntime() + + let settings: ClipMenuSettings + let clipsService: ClipsService + let snippetService = SnippetService() + let actionService = ActionService() + let loginItemService = LoginItemService() + let hotkeyService = HotkeyService() + private let preferencesWindowController = PreferencesWindowController() + + var modelContainer: ModelContainer? + + private init() { + let settings = ClipMenuSettings() + self.settings = settings + clipsService = MainActor.assumeIsolated { + ClipsService(settings: settings) + } + } + + @MainActor + func showPreferences(tab: PreferencesTab = .general) { + preferencesWindowController.show( + settings: settings, + loginItemService: loginItemService, + modelContainer: modelContainer, + initialTab: tab + ) + } +} + +@MainActor +private final class PreferencesWindowController: NSWindowController, NSWindowDelegate { + func show( + settings: ClipMenuSettings, + loginItemService: LoginItemService, + modelContainer: ModelContainer?, + initialTab: PreferencesTab + ) { + let window = window ?? makeWindow() + let rootView = makePreferencesView( + settings: settings, + loginItemService: loginItemService, + modelContainer: modelContainer, + initialTab: initialTab + ) + window.contentViewController = NSHostingController(rootView: rootView) + + NSRunningApplication.current.activate(options: [.activateAllWindows]) + window.center() + window.makeKeyAndOrderFront(nil) + window.orderFrontRegardless() + } + + func windowWillClose(_ notification: Notification) { + window?.contentViewController = nil + } + + private func makeWindow() -> NSWindow { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 820, height: 620), + styleMask: [.titled, .closable, .miniaturizable, .resizable], + backing: .buffered, + defer: false + ) + window.title = "Preferences" + window.contentMinSize = NSSize(width: 680, height: 500) + window.setFrameAutosaveName("Preferences") + window.isReleasedWhenClosed = false + window.delegate = self + self.window = window + return window + } + + private func makePreferencesView( + settings: ClipMenuSettings, + loginItemService: LoginItemService, + modelContainer: ModelContainer?, + initialTab: PreferencesTab + ) -> AnyView { + let rootView = PreferencesView(initialTab: initialTab) + .environment(settings) + .environment(\.loginItemService, loginItemService) + + if let modelContainer { + return AnyView(rootView.modelContainer(modelContainer)) + } + + return AnyView(rootView) + } +} diff --git a/Sources/App/ClipMenuApp.swift b/Sources/App/ClipMenuApp.swift new file mode 100644 index 0000000..0ea1865 --- /dev/null +++ b/Sources/App/ClipMenuApp.swift @@ -0,0 +1,50 @@ +import SwiftUI +import SwiftData + +@main +struct ClipMenuApp: App { + @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate + + private let modelContainer: ModelContainer + private let runtime = AppRuntime.shared + + init() { + let schema = Schema([ + ClipEntry.self, + SnippetFolder.self, + Snippet.self, + ActionNode.self, + ]) + + let configuration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) + modelContainer = try! ModelContainer(for: schema, configurations: [configuration]) + runtime.modelContainer = modelContainer + } + + var body: some Scene { + MenuBarExtra { + ClipMenuView() + .modelContainer(modelContainer) + .environment(runtime.settings) + .environment(\.clipsService, runtime.clipsService) + .environment(\.snippetService, runtime.snippetService) + .environment(\.actionService, runtime.actionService) + } label: { + Image(systemName: "clipboard.fill") + .symbolRenderingMode(.monochrome) + .font(.system(size: 13, weight: .semibold)) + .accessibilityLabel("ClipMenu") + } + .menuBarExtraStyle(.menu) + .modelContainer(modelContainer) + + Settings { + PreferencesView() + .modelContainer(modelContainer) + .environment(runtime.settings) + .environment(\.loginItemService, runtime.loginItemService) + } + .modelContainer(modelContainer) + } +} + diff --git a/Sources/App/EnvironmentKeys.swift b/Sources/App/EnvironmentKeys.swift new file mode 100644 index 0000000..b5756f3 --- /dev/null +++ b/Sources/App/EnvironmentKeys.swift @@ -0,0 +1,53 @@ +import SwiftUI + +// MARK: - ClipsService + +private struct ClipsServiceKey: EnvironmentKey { + static let defaultValue: ClipsService = AppRuntime.shared.clipsService +} + +extension EnvironmentValues { + var clipsService: ClipsService { + get { self[ClipsServiceKey.self] } + set { self[ClipsServiceKey.self] = newValue } + } +} + +// MARK: - SnippetService + +private struct SnippetServiceKey: EnvironmentKey { + static let defaultValue: SnippetService = SnippetService() +} + +extension EnvironmentValues { + var snippetService: SnippetService { + get { self[SnippetServiceKey.self] } + set { self[SnippetServiceKey.self] = newValue } + } +} + +// MARK: - ActionService + +private struct ActionServiceKey: EnvironmentKey { + static let defaultValue: ActionService = ActionService() +} + +extension EnvironmentValues { + var actionService: ActionService { + get { self[ActionServiceKey.self] } + set { self[ActionServiceKey.self] = newValue } + } +} + +// MARK: - LoginItemService + +private struct LoginItemServiceKey: EnvironmentKey { + static let defaultValue: LoginItemService = LoginItemService() +} + +extension EnvironmentValues { + var loginItemService: LoginItemService { + get { self[LoginItemServiceKey.self] } + set { self[LoginItemServiceKey.self] = newValue } + } +} diff --git a/Sources/Infrastructure/AppExclusionService.swift b/Sources/Infrastructure/AppExclusionService.swift new file mode 100644 index 0000000..26fda0e --- /dev/null +++ b/Sources/Infrastructure/AppExclusionService.swift @@ -0,0 +1,36 @@ +import AppKit + +/// Provides the bundle identifier of the currently frontmost application so +/// that ClipsService can skip recording clipboard changes triggered by ClipMenu +/// itself. +/// +/// Mirrors `legacy/Source/AppController.m -frontmostApplicationBundleIdentifier`. +final class AppExclusionService { + + private var excludedIDs = Set() + + func frontmostBundleIdentifier() -> String? { + NSWorkspace.shared.frontmostApplication?.bundleIdentifier + } + + func update(from settings: ClipMenuSettings) { + excludedIDs = Set(settings.excludeApps.compactMap { $0["bundleIdentifier"] }) + } + + /// Returns `true` when clipboard changes should be ignored because + /// the frontmost app is in the exclusion list stored in user preferences. + func shouldExclude() -> Bool { + guard let bundleID = frontmostBundleIdentifier() else { return false } + return excludedIDs.contains(bundleID) + } + + func runningUserApps() -> [(name: String, bundleID: String)] { + NSWorkspace.shared.runningApplications + .filter { $0.activationPolicy == .regular } + .compactMap { app in + guard let name = app.localizedName, let id = app.bundleIdentifier else { return nil } + return (name: name, bundleID: id) + } + .sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending } + } +} diff --git a/Sources/Infrastructure/ClipboardMonitor.swift b/Sources/Infrastructure/ClipboardMonitor.swift new file mode 100644 index 0000000..d48eec6 --- /dev/null +++ b/Sources/Infrastructure/ClipboardMonitor.swift @@ -0,0 +1,36 @@ +import AppKit +import Combine + +/// Publishes `NSPasteboard` change events as a Combine stream. +/// +/// Uses a timer-based polling approach (matching legacy behaviour) rather than +/// KVO, because NSPasteboard does not expose a reliable change notification API. +/// Check `legacy/Source/ClipsController.m` for the polling interval and the +/// change-count comparison logic before changing this implementation. +final class ClipboardMonitor { + let pasteboardChanged = PassthroughSubject() + + private var cancellables = Set() + private var lastChangeCount: Int = 0 + private let pasteboard = NSPasteboard.general + + func start(interval: TimeInterval = 0.75) { + stop() + lastChangeCount = pasteboard.changeCount + + Timer.publish(every: interval, on: .main, in: .common) + .autoconnect() + .sink { [weak self] _ in + guard let self else { return } + let current = self.pasteboard.changeCount + guard current != self.lastChangeCount else { return } + self.lastChangeCount = current + self.pasteboardChanged.send(self.pasteboard) + } + .store(in: &cancellables) + } + + func stop() { + cancellables.removeAll() + } +} diff --git a/Sources/Infrastructure/HotkeyService.swift b/Sources/Infrastructure/HotkeyService.swift new file mode 100644 index 0000000..fa7d133 --- /dev/null +++ b/Sources/Infrastructure/HotkeyService.swift @@ -0,0 +1,565 @@ +import AppKit +import KeyboardShortcuts +import Foundation +import os +import SwiftData + +// MARK: - Shortcut Names + +extension KeyboardShortcuts.Name { + /// Opens the main clipboard history + snippets menu (legacy: "ClipMenu", Cmd+Shift+V). + static let openClipMenu = Self("openClipMenu", + default: .init(.v, modifiers: [.command, .shift])) + /// Opens the history-only view (legacy: "HistoryMenu", Cmd+Ctrl+V). + static let openHistory = Self("openHistory", + default: .init(.v, modifiers: [.command, .control])) + /// Opens the snippets view (legacy: "SnippetsMenu", Cmd+Shift+B). + static let openSnippets = Self("openSnippets", + default: .init(.b, modifiers: [.command, .shift])) + /// Opens the actions menu for the most recent clip (Cmd+Shift+A). + static let openActions = Self("openActions", + default: .init(.a, modifiers: [.command, .shift])) +} + +// MARK: - HotkeyService + +/// Registers and unregisters global keyboard shortcuts using the +/// `KeyboardShortcuts` package. +/// +/// Default key combos mirror `legacy/Source/AppController.m +/// +_defaultHotKeyCombos` (keyCode 9 = V, 11 = B; modifiers 768 = ⌘⇧, +/// 4352 = ⌘⌃). +final class HotkeyService { + fileprivate static let log = Logger(subsystem: "com.naotaka.ClipMenu", category: "Hotkeys") + private let popupMenu = HotkeyPopupMenuPresenter() + + func register() { + Self.log.info("Registering global shortcuts") + ensureDefaultShortcutsIfMissing() + + // Trigger on key-up to avoid interacting with the menu while modifier + // keys are still held down. + KeyboardShortcuts.onKeyUp(for: .openClipMenu) { [weak self] in self?.presentFromHotkey(name: "openClipMenu", kind: .main) } + KeyboardShortcuts.onKeyUp(for: .openHistory) { [weak self] in self?.presentFromHotkey(name: "openHistory", kind: .history) } + KeyboardShortcuts.onKeyUp(for: .openSnippets) { [weak self] in self?.presentFromHotkey(name: "openSnippets", kind: .snippets) } + KeyboardShortcuts.onKeyUp(for: .openActions) { [weak self] in self?.presentFromHotkey(name: "openActions", kind: .actions) } + } + + func unregister() { + Self.log.info("Unregistering global shortcuts") + KeyboardShortcuts.removeAllHandlers() + } + + // MARK: - Private + + private func ensureDefaultShortcutsIfMissing() { + let names: [KeyboardShortcuts.Name] = [.openClipMenu, .openHistory, .openSnippets, .openActions] + + for name in names { + // KeyboardShortcuts can persist disabled shortcuts as `nil`. + // Restore the built-in default when no active shortcut exists. + if KeyboardShortcuts.getShortcut(for: name) == nil, + let fallback = name.defaultShortcut { + Self.log.notice("Restoring missing shortcut for \(name.rawValue, privacy: .public)") + KeyboardShortcuts.setShortcut(fallback, for: name) + } + } + } + + private func presentFromHotkey(name: String, kind: HotkeyMenuKind) { + Self.log.info("Hotkey triggered: \(name, privacy: .public)") + DispatchQueue.main.async { + // Single hotkey UX path: always show the native popup menu. + self.popupMenu.show(using: AppRuntime.shared, kind: kind) + } + } +} + +private enum HotkeyMenuKind { + case main + case history + case snippets + case actions +} + +private final class HotkeyPopupMenuPresenter: NSObject, NSMenuDelegate { + private let actionTarget = HotkeyPopupActionTarget() + private var targetAppForPaste: NSRunningApplication? + private lazy var anchorWindow: NSWindow = { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 1, height: 1), + styleMask: [.borderless], + backing: .buffered, + defer: false + ) + window.isReleasedWhenClosed = false + window.hasShadow = false + window.backgroundColor = .clear + window.alphaValue = 0.001 + window.ignoresMouseEvents = true + window.level = .statusBar + return window + }() + + @MainActor + func show(using runtime: AppRuntime, kind: HotkeyMenuKind) { + guard let context = runtime.modelContainer?.mainContext else { + HotkeyService.log.error("Fallback popup requested but modelContext is nil") + return + } + + let menu = buildMenu(runtime: runtime, context: context, kind: kind) + actionTarget.runtime = runtime + targetAppForPaste = currentTargetApplication() + actionTarget.targetAppForPaste = targetAppForPaste + menu.delegate = self + + let mouse = NSEvent.mouseLocation + anchorWindow.setFrameOrigin(mouse) + anchorWindow.orderFront(nil) + + if let contentView = anchorWindow.contentView { + menu.popUp(positioning: nil, at: NSPoint(x: 0, y: 0), in: contentView) + } else { + menu.popUp(positioning: nil, at: mouse, in: nil) + } + + anchorWindow.orderOut(nil) + HotkeyService.log.notice("Presented fallback NSMenu popup") + } + + func menuDidClose(_ menu: NSMenu) { + anchorWindow.orderOut(nil) + } + + private func currentTargetApplication() -> NSRunningApplication? { + guard let frontmost = NSWorkspace.shared.frontmostApplication else { return nil } + if frontmost.processIdentifier == NSRunningApplication.current.processIdentifier { + return nil + } + return frontmost + } + + private func buildMenu(runtime: AppRuntime, context: ModelContext, kind: HotkeyMenuKind) -> NSMenu { + let menu = NSMenu(title: "ClipMenu") + let settings = runtime.settings + + let fetchedClips = (try? context.fetch(FetchDescriptor( + sortBy: [SortDescriptor(\ClipEntry.lastUsedAt, order: .reverse)] + ))) ?? [] + let clips = Array(fetchedClips.prefix(max(settings.maxHistorySize, 0))) + + let folders = (try? context.fetch(FetchDescriptor( + sortBy: [SortDescriptor(\SnippetFolder.sortIndex, order: .forward)] + ))) ?? [] + + let showSnippetsInMain = kind == .main + let showHistory = kind != .snippets && kind != .actions + let showActionsInMain = kind == .main && settings.enableAction + + if showSnippetsInMain && settings.positionOfSnippets == 0 { + addSnippets(to: menu, folders: folders, settings: settings) + if showHistory { menu.addItem(.separator()) } + } + + if kind == .snippets { + addSnippets(to: menu, folders: folders, settings: settings) + } + + if kind == .actions { + addActions(to: menu, clips: clips, context: context, runtime: runtime) + } + + if showHistory { + addHistory(to: menu, clips: clips, settings: settings) + } + + if showSnippetsInMain && settings.positionOfSnippets == 1 { + if showHistory { menu.addItem(.separator()) } + addSnippets(to: menu, folders: folders, settings: settings) + } + + if showActionsInMain { + menu.addItem(.separator()) + addActionsSubmenu(to: menu, clips: clips, context: context, runtime: runtime) + } + + if showHistory && settings.showClearHistoryItem { + menu.addItem(.separator()) + let clear = NSMenuItem(title: "Clear History", action: #selector(HotkeyPopupActionTarget.clearHistory(_:)), keyEquivalent: "") + clear.target = actionTarget + clear.image = NSImage(systemSymbolName: "trash", accessibilityDescription: nil) + menu.addItem(clear) + } + + menu.addItem(.separator()) + let editSnippets = NSMenuItem(title: "Edit Snippets…", action: #selector(HotkeyPopupActionTarget.openSnippetsEditor(_:)), keyEquivalent: "") + editSnippets.target = actionTarget + editSnippets.image = NSImage(systemSymbolName: "text.badge.plus", accessibilityDescription: nil) + menu.addItem(editSnippets) + + let prefs = NSMenuItem(title: "Preferences…", action: #selector(HotkeyPopupActionTarget.openPreferences(_:)), keyEquivalent: "") + prefs.target = actionTarget + prefs.image = NSImage(systemSymbolName: "gearshape", accessibilityDescription: nil) + menu.addItem(prefs) + + let quit = NSMenuItem(title: "Quit ClipMenu", action: #selector(HotkeyPopupActionTarget.quit(_:)), keyEquivalent: "") + quit.target = actionTarget + quit.image = NSImage(systemSymbolName: "power", accessibilityDescription: nil) + menu.addItem(quit) + + return menu + } + + private func addActionsSubmenu(to menu: NSMenu, clips: [ClipEntry], context: ModelContext, runtime: AppRuntime) { + let actionsItem = NSMenuItem(title: "Actions", action: nil, keyEquivalent: "") + actionsItem.image = NSImage(systemSymbolName: "bolt", accessibilityDescription: nil) + + guard let targetClip = clips.first else { + let submenu = NSMenu(title: "Actions") + let empty = NSMenuItem(title: "No clips available", action: nil, keyEquivalent: "") + empty.isEnabled = false + submenu.addItem(empty) + actionsItem.submenu = submenu + menu.addItem(actionsItem) + return + } + + let roots = (try? context.fetch(FetchDescriptor( + predicate: #Predicate { $0.parent == nil }, + sortBy: [SortDescriptor(\ActionNode.sortIndex)] + ))) ?? [] + + let actionMenu = ActionMenuBuilder.makeMenu( + from: roots, + target: targetClip, + service: runtime.actionService, + executionContext: .transformOnly, + postAction: { [weak self] in + await self?.pasteAfterActionIfNeeded(runtime: runtime) + } + ) + if actionMenu.items.isEmpty { + let submenu = NSMenu(title: "Actions") + let empty = NSMenuItem(title: "No actions configured", action: nil, keyEquivalent: "") + empty.isEnabled = false + submenu.addItem(empty) + actionsItem.submenu = submenu + } else { + actionsItem.submenu = actionMenu + } + + menu.addItem(actionsItem) + } + + private func addActions(to menu: NSMenu, clips: [ClipEntry], context: ModelContext, runtime: AppRuntime) { + guard let targetClip = clips.first else { + let empty = NSMenuItem(title: "No clips available", action: nil, keyEquivalent: "") + empty.isEnabled = false + menu.addItem(empty) + return + } + + let titleItem = NSMenuItem(title: "Actions for Most Recent Clip", action: nil, keyEquivalent: "") + titleItem.isEnabled = false + menu.addItem(titleItem) + menu.addItem(.separator()) + + let roots = (try? context.fetch(FetchDescriptor( + predicate: #Predicate { $0.parent == nil }, + sortBy: [SortDescriptor(\ActionNode.sortIndex)] + ))) ?? [] + + let actionsMenu = ActionMenuBuilder.makeMenu( + from: roots, + target: targetClip, + service: runtime.actionService, + executionContext: .transformOnly, + postAction: { [weak self] in + await self?.pasteAfterActionIfNeeded(runtime: runtime) + } + ) + if actionsMenu.items.isEmpty { + let empty = NSMenuItem(title: "No actions configured", action: nil, keyEquivalent: "") + empty.isEnabled = false + menu.addItem(empty) + return + } + + while let first = actionsMenu.items.first { + actionsMenu.removeItem(first) + menu.addItem(first) + } + } + + @MainActor + private func pasteAfterActionIfNeeded(runtime: AppRuntime) async { + guard runtime.settings.autoPasteAfterSelection else { return } + targetAppForPaste?.activate(options: []) + try? await Task.sleep(nanoseconds: 180_000_000) + await actionTarget.pasteFromHotkeyAction() + } + private func addSnippets(to menu: NSMenu, folders: [SnippetFolder], settings: ClipMenuSettings) { + let enabledFolders = folders.filter(\.isEnabled) + guard !enabledFolders.isEmpty else { return } + + if settings.showLabelsInMenu { + let label = NSMenuItem(title: "Snippets", action: nil, keyEquivalent: "") + label.isEnabled = false + menu.addItem(label) + } + + for folder in enabledFolders { + let snippets = folder.snippets + .filter(\.isEnabled) + .sorted { $0.sortIndex < $1.sortIndex } + + guard !snippets.isEmpty else { continue } + + let folderItem = NSMenuItem(title: folder.title, action: nil, keyEquivalent: "") + folderItem.image = NSImage(named: NSImage.folderName) + let submenu = NSMenu(title: folder.title) + for snippet in snippets { + let item = NSMenuItem(title: snippet.title, action: #selector(HotkeyPopupActionTarget.selectSnippet(_:)), keyEquivalent: "") + item.target = actionTarget + item.representedObject = snippet + submenu.addItem(item) + } + folderItem.submenu = submenu + menu.addItem(folderItem) + } + } + + private func addHistory(to menu: NSMenu, clips: [ClipEntry], settings: ClipMenuSettings) { + if settings.showLabelsInMenu { + let label = NSMenuItem(title: "History", action: nil, keyEquivalent: "") + label.isEnabled = false + menu.addItem(label) + } + + let inlineCount = max(settings.numberOfItemsInline, 0) + let perFolder = max(settings.numberOfItemsInsideFolder, 1) + + let inlineClips = inlineCount == 0 ? [] : Array(clips.prefix(inlineCount)) + let folderClips = inlineCount == 0 ? clips : Array(clips.dropFirst(inlineCount)) + + for (idx, clip) in inlineClips.enumerated() { + let itemNumber = listNumber(for: idx, settings: settings) + let item = NSMenuItem(title: clipTitle(for: clip, settings: settings, listNumber: itemNumber), + action: #selector(HotkeyPopupActionTarget.selectClip(_:)), + keyEquivalent: "") + item.target = actionTarget + item.representedObject = clip + if settings.numericKeyEquivalents { + item.keyEquivalent = String(itemNumber % 10) + item.keyEquivalentModifierMask = [] + } + if let thumbnail = thumbnailImage(for: clip, settings: settings) { + item.image = thumbnail + HotkeyService.log.debug("Attached inline popup thumbnail for clip index=\(idx, privacy: .public)") + } else if clip.imageData != nil { + HotkeyService.log.debug("Inline popup clip has imageData but no thumbnail index=\(idx, privacy: .public) bytes=\(clip.imageData?.count ?? 0, privacy: .public)") + } + menu.addItem(item) + } + + let groups = stride(from: 0, to: folderClips.count, by: perFolder).map { + Array(folderClips[$0.. Int { + if settings.numberingStartsAtZero { + return index % 10 + } + let n = index + 1 + return n > 10 ? n % 10 : n + } + + private func clipTitle(for clip: ClipEntry, settings: ClipMenuSettings, listNumber: Int) -> String { + let source = clip.stringValue + ?? clip.filenames?.first + ?? clip.urlStrings?.first + ?? "" + + let stripped = source.trimmingCharacters(in: .whitespacesAndNewlines) + let firstLine: String + if let nl = stripped.firstIndex(of: "\n") { + firstLine = String(stripped[.. maxLen { + trimmed = String(firstLine.prefix(max(maxLen - 3, 0))) + "..." + } else if firstLine.isEmpty, clip.imageData != nil { + trimmed = "(Image)" + } else { + trimmed = firstLine.isEmpty ? "(binary)" : firstLine + } + + if settings.numberedMenuItems { + return "\(listNumber). \(trimmed)" + } + return trimmed + } + + private func thumbnailImage(for clip: ClipEntry, settings: ClipMenuSettings) -> NSImage? { + guard settings.showImageInMenu, + let imageData = clip.imageData, + let image = decodedImage(from: imageData) + else { + if clip.imageData != nil { + HotkeyService.log.debug("Popup thumbnail decode failed bytes=\(clip.imageData?.count ?? 0, privacy: .public)") + } + return nil + } + + let targetSize = NSSize(width: CGFloat(settings.thumbnailWidth), + height: CGFloat(settings.thumbnailHeight)) + return scaledImage(image, to: targetSize) + } + + private func scaledImage(_ image: NSImage, to size: NSSize) -> NSImage { + guard image.size.width > 0, image.size.height > 0, + size.width > 0, size.height > 0 else { + return image + } + + let ratio = min(size.width / image.size.width, size.height / image.size.height) + let drawSize = NSSize(width: image.size.width * ratio, height: image.size.height * ratio) + let drawOrigin = NSPoint(x: (size.width - drawSize.width) / 2, + y: (size.height - drawSize.height) / 2) + + let scaled = NSImage(size: size) + scaled.lockFocus() + image.draw(in: NSRect(origin: drawOrigin, size: drawSize), + from: .zero, + operation: .sourceOver, + fraction: 1.0) + scaled.unlockFocus() + return scaled + } + + private func decodedImage(from data: Data) -> NSImage? { + if let image = NSImage(data: data), image.size.width > 0, image.size.height > 0 { + HotkeyService.log.debug("Popup decode via NSImage size=\(Int(image.size.width), privacy: .public)x\(Int(image.size.height), privacy: .public)") + return image + } + + if let rep = NSBitmapImageRep(data: data) { + let image = NSImage(size: rep.size) + image.addRepresentation(rep) + HotkeyService.log.debug("Popup decode via NSBitmapImageRep size=\(Int(rep.size.width), privacy: .public)x\(Int(rep.size.height), privacy: .public)") + return image + } + + HotkeyService.log.debug("Popup decode failed for image bytes=\(data.count, privacy: .public)") + return NSImage(data: data) + } +} + +private final class HotkeyPopupActionTarget: NSObject { + weak var runtime: AppRuntime? + weak var targetAppForPaste: NSRunningApplication? + private let pasteService = PasteService() + + @MainActor + private func reactivateTargetAppIfNeeded() { + guard let targetAppForPaste else { return } + HotkeyService.log.debug("Re-activating target app pid=\(targetAppForPaste.processIdentifier, privacy: .public)") + targetAppForPaste.activate(options: []) + } + + @objc func selectClip(_ sender: NSMenuItem) { + guard let runtime, + let clip = sender.representedObject as? ClipEntry else { return } + Task { @MainActor in + reactivateTargetAppIfNeeded() + // Allow menu interaction to settle before writing pasteboard. + try? await Task.sleep(nanoseconds: 160_000_000) + await runtime.clipsService.select(clip, pasteImmediately: false) + if runtime.settings.autoPasteAfterSelection { + // Extra delay helps ensure front app is active before Cmd+V. + try? await Task.sleep(nanoseconds: 180_000_000) + await pasteService.paste() + } + } + } + + @objc func selectSnippet(_ sender: NSMenuItem) { + guard let runtime, + let snippet = sender.representedObject as? Snippet else { return } + Task { @MainActor in + reactivateTargetAppIfNeeded() + try? await Task.sleep(nanoseconds: 160_000_000) + await runtime.clipsService.copyStringToPasteboard(snippet.content, pasteImmediately: false) + if runtime.settings.autoPasteAfterSelection { + try? await Task.sleep(nanoseconds: 180_000_000) + await pasteService.paste() + } + } + } + + @objc func clearHistory(_ sender: NSMenuItem) { + guard let runtime else { return } + Task { try? await runtime.clipsService.clearAll() } + } + + @objc func openPreferences(_ sender: NSMenuItem) { + guard let runtime else { return } + Task { @MainActor in + runtime.showPreferences() + } + } + + @objc func openSnippetsEditor(_ sender: NSMenuItem) { + guard let runtime else { return } + Task { @MainActor in + runtime.showPreferences(tab: .snippets) + } + } + + @objc func quit(_ sender: NSMenuItem) { + NSApp.terminate(nil) + } + + @MainActor + func pasteFromHotkeyAction() async { + await pasteService.paste() + } +} diff --git a/Sources/Infrastructure/LoginItemService.swift b/Sources/Infrastructure/LoginItemService.swift new file mode 100644 index 0000000..9d5d8a8 --- /dev/null +++ b/Sources/Infrastructure/LoginItemService.swift @@ -0,0 +1,30 @@ +import ServiceManagement + +/// Manages launch-at-login registration via `SMAppService`. +/// +/// Replaces the legacy Carbon `LSSharedFileList` approach in +/// `legacy/Source/NaoAdditions/LoginItems.m`. +final class LoginItemService { + + private let service = SMAppService.mainApp + + var isEnabled: Bool { + service.status == .enabled + } + + func enable() throws { + try service.register() + } + + func disable() throws { + try service.unregister() + } + + func setEnabled(_ enabled: Bool) throws { + if enabled { + try enable() + } else { + try disable() + } + } +} diff --git a/Sources/Infrastructure/PasteService.swift b/Sources/Infrastructure/PasteService.swift new file mode 100644 index 0000000..626197e --- /dev/null +++ b/Sources/Infrastructure/PasteService.swift @@ -0,0 +1,122 @@ +import CoreGraphics +import AppKit +import ApplicationServices +import Carbon.HIToolbox +import os + +/// Synthesises a Cmd+V key event to paste the current pasteboard contents +/// into the frontmost application. +/// +/// Requires Accessibility permission (`AXIsProcessTrusted()`). The legacy +/// implementation lives in `legacy/Source/AppController.m -pasteFromClipboard`. +actor PasteService { + private static let log = Logger(subsystem: "com.naotaka.ClipMenu", category: "PasteService") + private var cachedVKeyCode: CGKeyCode? + private var loggedMissingAXThisSession = false + + init() { + NotificationCenter.default.addObserver( + forName: NSTextInputContext.keyboardSelectionDidChangeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + Task { await self?.invalidateCachedKeyCode() } + } + } + + func paste() async { + guard isAccessibilityTrusted() else { + Self.log.error("Paste aborted: Accessibility permission not granted") + return + } + guard let keyCode = vKeyCode() else { + Self.log.error("Paste aborted: could not resolve V key code") + return + } + guard let source = CGEventSource(stateID: .combinedSessionState) else { + Self.log.error("Paste aborted: could not create CGEventSource") + return + } + + let keyDown = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: true) + let keyUp = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: false) + + keyDown?.flags = .maskCommand + keyUp?.flags = .maskCommand + + keyDown?.post(tap: .cghidEventTap) + keyUp?.post(tap: .cghidEventTap) + Self.log.info("Posted Cmd+V events using keyCode=\(keyCode, privacy: .public)") + } + + private func isAccessibilityTrusted() -> Bool { + if AXIsProcessTrusted() { + return true + } + + // Avoid OS permission prompts on launch/session boundaries. We only + // report missing permission and let users grant it from Settings. + if !loggedMissingAXThisSession { + loggedMissingAXThisSession = true + let bundleID = Bundle.main.bundleIdentifier ?? "" + let execPath = Bundle.main.executableURL?.path ?? "" + Self.log.error("Accessibility permission missing. bundleID=\(bundleID, privacy: .public) execPath=\(execPath, privacy: .public)") + } + + return false + } + + private func invalidateCachedKeyCode() { + cachedVKeyCode = nil + } + + private func vKeyCode() -> CGKeyCode? { + if let cachedVKeyCode { + return cachedVKeyCode + } + + guard let source = TISCopyCurrentKeyboardLayoutInputSource()?.takeRetainedValue(), + let layoutData = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) + else { + cachedVKeyCode = 9 + return cachedVKeyCode + } + + let layout = unsafeBitCast(layoutData, to: CFData.self) + guard let bytes = CFDataGetBytePtr(layout) else { + cachedVKeyCode = 9 + return cachedVKeyCode + } + + let keyboardLayout = UnsafePointer(OpaquePointer(bytes)) + + for keyCode in 0..<128 { + var deadKeyState: UInt32 = 0 + var chars = [UniChar](repeating: 0, count: 4) + var length = 0 + + let status = UCKeyTranslate( + keyboardLayout, + UInt16(keyCode), + UInt16(kUCKeyActionDisplay), + 0, + UInt32(LMGetKbdType()), + OptionBits(kUCKeyTranslateNoDeadKeysBit), + &deadKeyState, + 4, + &length, + &chars + ) + + guard status == noErr, length > 0 else { continue } + let mapped = String(utf16CodeUnits: chars, count: Int(length)) + if mapped.caseInsensitiveCompare("v") == .orderedSame { + cachedVKeyCode = CGKeyCode(keyCode) + return cachedVKeyCode + } + } + + cachedVKeyCode = 9 + return cachedVKeyCode + } +} diff --git a/Sources/Migration/LegacyMigration.swift b/Sources/Migration/LegacyMigration.swift new file mode 100644 index 0000000..029e1d3 --- /dev/null +++ b/Sources/Migration/LegacyMigration.swift @@ -0,0 +1,277 @@ +import SwiftData +import Foundation +import AppKit + +/// One-time migration of user data from the legacy Objective-C app. +/// +/// Reads the three legacy data files and inserts equivalent SwiftData records: +/// +/// | Legacy file | Swift model | +/// |--------------------------|---------------------------| +/// | `~/Library/.../clips.data` | `ClipEntry` | +/// | `~/Library/.../Snippets.xml` | `SnippetFolder`, `Snippet` | +/// | `~/Library/.../actions.plist`| `ActionNode` | +/// +/// Reference: `legacy/Source/ClipsController.m` (clips path), +/// `legacy/Source/SnippetsController.m` (snippets path), +/// `legacy/Source/ActionNodeFactory.m` (actions path). +/// +/// Migration runs at most once; completion is recorded in UserDefaults under +/// `legacyMigrationCompleted`. +struct LegacyMigration { + + static let completedKey = "legacyMigrationCompleted" + + static var isNeeded: Bool { + !UserDefaults.standard.bool(forKey: completedKey) + } + + /// Call from AppDelegate.applicationDidFinishLaunching if `isNeeded`. + static func run(in context: ModelContext) { + let supportFolder = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first? + .appendingPathComponent("ClipMenu") + + guard let supportFolder else { + UserDefaults.standard.set(true, forKey: completedKey) + return + } + + importClips(from: supportFolder.appendingPathComponent("clips.data"), into: context) + importSnippets(from: supportFolder.appendingPathComponent("Snippets.xml"), into: context) + importActions(from: supportFolder.appendingPathComponent("actions.plist"), into: context) + + UserDefaults.standard.set(true, forKey: completedKey) + } + + // MARK: - Snippets (Core Data XML → SwiftData) + + private static func importSnippets(from url: URL, into context: ModelContext) { + guard FileManager.default.fileExists(atPath: url.path) else { return } + + // Build the legacy Core Data model programmatically. + // The original Snippets.xcdatamodel is a flat (non-versioned) model that was never + // compiled into the new app bundle, so loading it from Bundle.main is not possible. + // The schema is stable (Folder/Snippet with title/index/enabled + relationship), so + // constructing it in code is the most reliable approach. + let mom = makeLegacySnippetModel() + + let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) + let options: [String: Any] = [NSReadOnlyPersistentStoreOption: true] + guard (try? psc.addPersistentStore( + ofType: NSXMLStoreType, + configurationName: nil, + at: url, + options: options)) != nil + else { return } + + let legacyCtx = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) + legacyCtx.persistentStoreCoordinator = psc + + let folderReq = NSFetchRequest(entityName: "Folder") + folderReq.sortDescriptors = [NSSortDescriptor(key: "index", ascending: true)] + guard let legacyFolders = try? legacyCtx.fetch(folderReq) else { return } + + for legacyFolder in legacyFolders { + let folder = SnippetFolder( + title: legacyFolder.value(forKey: "title") as? String ?? "", + sortIndex: legacyFolder.value(forKey: "index") as? Int ?? 0 + ) + folder.isEnabled = legacyFolder.value(forKey: "enabled") as? Bool ?? true + context.insert(folder) + + let snippetSet = (legacyFolder.value(forKey: "snippets") as? NSSet)? + .allObjects as? [NSManagedObject] ?? [] + let sorted = snippetSet.sorted { + ($0.value(forKey: "index") as? Int ?? 0) < ($1.value(forKey: "index") as? Int ?? 0) + } + for legacySnippet in sorted { + let snippet = Snippet( + title: legacySnippet.value(forKey: "title") as? String ?? "", + content: legacySnippet.value(forKey: "content") as? String ?? "", + sortIndex: legacySnippet.value(forKey: "index") as? Int ?? 0 + ) + snippet.isEnabled = legacySnippet.value(forKey: "enabled") as? Bool ?? true + snippet.folder = folder + folder.snippets.append(snippet) + context.insert(snippet) + } + } + + try? context.save() + } + + /// Constructs the legacy Snippets Core Data model programmatically. + /// + /// Avoids any dependency on a compiled `.mom`/`.momd` bundle resource. + /// Matches the schema defined in `legacy/Snippets.xcdatamodel`. + private static func makeLegacySnippetModel() -> NSManagedObjectModel { + let model = NSManagedObjectModel() + + let folderEntity = NSEntityDescription() + folderEntity.name = "Folder" + folderEntity.managedObjectClassName = "NSManagedObject" + + let snippetEntity = NSEntityDescription() + snippetEntity.name = "Snippet" + snippetEntity.managedObjectClassName = "NSManagedObject" + + func attr(_ name: String, _ type: NSAttributeType) -> NSAttributeDescription { + let a = NSAttributeDescription() + a.name = name; a.attributeType = type; a.isOptional = true + return a + } + + folderEntity.properties = [ + attr("title", .stringAttributeType), + attr("index", .integer32AttributeType), + attr("enabled", .booleanAttributeType), + ] + snippetEntity.properties = [ + attr("title", .stringAttributeType), + attr("content", .stringAttributeType), + attr("index", .integer32AttributeType), + attr("enabled", .booleanAttributeType), + ] + + // Relationship: Folder.snippets ↔ Snippet.folder + let folderSnippets = NSRelationshipDescription() + folderSnippets.name = "snippets" + folderSnippets.isOptional = true + folderSnippets.minCount = 0 + folderSnippets.maxCount = 0 // to-many + folderSnippets.destinationEntity = snippetEntity + + let snippetFolder = NSRelationshipDescription() + snippetFolder.name = "folder" + snippetFolder.isOptional = true + snippetFolder.minCount = 0 + snippetFolder.maxCount = 1 // to-one + snippetFolder.destinationEntity = folderEntity + + folderSnippets.inverseRelationship = snippetFolder + snippetFolder.inverseRelationship = folderSnippets + + folderEntity.properties += [folderSnippets] + snippetEntity.properties += [snippetFolder] + + model.entities = [folderEntity, snippetEntity] + return model + } + + private static func importClips(from url: URL, into context: ModelContext) { + guard let data = try? Data(contentsOf: url) else { return } + + do { + let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) + unarchiver.requiresSecureCoding = false + unarchiver.setClass(LegacyArchivedClip.self, forClassName: "Clip") + + guard let legacyClips = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? [LegacyArchivedClip] + else { + return + } + + for legacy in legacyClips { + let entry = ClipEntry() + entry.createdAt = legacy.createdDate ?? .now + entry.lastUsedAt = legacy.lastUsedDate ?? entry.createdAt + entry.types = legacy.types + entry.stringValue = legacy.stringValue + entry.rtfData = legacy.rtfData + entry.pdfData = legacy.pdf + entry.filenames = legacy.filenames + entry.urlStrings = legacy.url + if let image = legacy.image { + entry.imageData = image.tiffRepresentation + } + context.insert(entry) + } + + try? context.save() + } catch { + return + } + } + + private static func importActions(from url: URL, into context: ModelContext) { + guard let data = try? Data(contentsOf: url), + let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil), + let dicts = plist as? [[String: Any]] + else { + return + } + + for (index, dict) in dicts.enumerated() { + let node = makeActionNode(from: dict, sortIndex: index) + context.insert(node) + } + + try? context.save() + } + + private static func makeActionNode(from dictionary: [String: Any], sortIndex: Int) -> ActionNode { + let title = (dictionary["nodeTitle"] as? String) ?? "Untitled" + let isLeaf = (dictionary["isLeaf"] as? Bool) ?? false + let node = ActionNode(title: title, isLeaf: isLeaf, sortIndex: sortIndex) + + if let action = dictionary["action"] as? [String: Any] { + if let type = action["type"] as? String { + node.actionType = type == "js" ? "javaScript" : type + } + node.actionName = action["name"] as? String + node.scriptPath = action["path"] as? String + } + + if let children = dictionary["children"] as? [[String: Any]] { + node.children = children.enumerated().map { offset, child in + makeActionNode(from: child, sortIndex: offset) + } + } + + return node + } +} + +@objc(CMLegacyArchivedClip) +private final class LegacyArchivedClip: NSObject, NSCoding { + var types: [String] = [] + var createdDate: Date? + var lastUsedDate: Date? + var stringValue: String? + var rtfData: Data? + var pdf: Data? + var filenames: [String]? + var url: [String]? + var image: NSImage? + + required init?(coder: NSCoder) { + types = coder.decodeObject(forKey: "types") as? [String] ?? [] + createdDate = coder.decodeObject(forKey: "createdDate") as? Date + lastUsedDate = coder.decodeObject(forKey: "lastUsedDate") as? Date + stringValue = coder.decodeObject(forKey: "stringValue") as? String + + let rtfKeyCandidates = ["RTFData", "RTFD", "RTF"] + for key in rtfKeyCandidates where rtfData == nil { + rtfData = coder.decodeObject(forKey: key) as? Data + } + + pdf = coder.decodeObject(forKey: "PDF") as? Data + filenames = coder.decodeObject(forKey: "filenames") as? [String] + url = coder.decodeObject(forKey: "URL") as? [String] + image = coder.decodeObject(forKey: "image") as? NSImage + } + + func encode(with coder: NSCoder) { + coder.encode(types, forKey: "types") + coder.encode(createdDate, forKey: "createdDate") + coder.encode(lastUsedDate, forKey: "lastUsedDate") + coder.encode(stringValue, forKey: "stringValue") + coder.encode(rtfData, forKey: "RTFData") + coder.encode(pdf, forKey: "PDF") + coder.encode(filenames, forKey: "filenames") + coder.encode(url, forKey: "URL") + coder.encode(image, forKey: "image") + } +} diff --git a/Sources/Models/ActionNode.swift b/Sources/Models/ActionNode.swift new file mode 100644 index 0000000..7cffa25 --- /dev/null +++ b/Sources/Models/ActionNode.swift @@ -0,0 +1,33 @@ +import SwiftData + +/// A node in the action tree (folder or leaf action). +/// +/// Mirrors the data shape in `legacy/Source/ActionNode.{h,m}`. +/// See those files and `legacy/Source/ActionNodeFactory.m` before +/// modifying the tree structure. +@Model +final class ActionNode { + + var title: String + var isLeaf: Bool + var isEnabled: Bool + var sortIndex: Int + + /// `nil` for folder nodes; populated for leaf action nodes. + var actionType: String? + var actionName: String? + var scriptPath: String? + var scriptContent: String? + + @Relationship(deleteRule: .cascade) + var children: [ActionNode] = [] + + var parent: ActionNode? + + init(title: String, isLeaf: Bool = false, sortIndex: Int = 0) { + self.title = title + self.isLeaf = isLeaf + self.isEnabled = true + self.sortIndex = sortIndex + } +} diff --git a/Sources/Models/ClipEntry.swift b/Sources/Models/ClipEntry.swift new file mode 100644 index 0000000..458d0cb --- /dev/null +++ b/Sources/Models/ClipEntry.swift @@ -0,0 +1,63 @@ +import SwiftData +import Foundation + +/// A single clipboard entry captured from NSPasteboard. +/// +/// Equality / deduplication uses `contentHash` which replicates the algorithm +/// from `legacy/Source/Clip.m -hash`. See that file for the exact XOR +/// sequence before changing this implementation. +@Model +final class ClipEntry { + + var createdAt: Date + var lastUsedAt: Date + + /// Pasteboard type strings in the order they appeared on the pasteboard. + var types: [String] + + var stringValue: String? + /// RTF or RTFD bytes (see `isRTFD` to distinguish). + var rtfData: Data? + /// `true` when `rtfData` contains an RTFD document (file-wrapper RTF). + var isRTFD: Bool + var pdfData: Data? + var filenames: [String]? + var urlStrings: [String]? + /// TIFF bytes. + var imageData: Data? + + init() { + createdAt = .now + lastUsedAt = .now + types = [] + isRTFD = false + } + + var contentHash: Int { + // Use NSString.hash (stable across process runs) rather than Swift's + // randomised hashValue so that deduplication survives app restarts. + // This mirrors legacy/Source/Clip.m which calls -hash on NSString. + var h = (types.joined() as NSString).hash + + if let imageData { + h ^= imageData.count + } + + if let filenames { + for filename in filenames { + h ^= (filename as NSString).hash + } + } else if let urlStrings { + for urlString in urlStrings { + h ^= (urlString as NSString).hash + } + } else if let pdfData { + h ^= pdfData.count + } else if let stringValue { + h ^= (stringValue as NSString).hash + } + + h ^= (rtfData?.count ?? 0) + return h + } +} diff --git a/Sources/Models/Snippet.swift b/Sources/Models/Snippet.swift new file mode 100644 index 0000000..86906e3 --- /dev/null +++ b/Sources/Models/Snippet.swift @@ -0,0 +1,19 @@ +import SwiftData + +@Model +final class Snippet { + + var title: String + var content: String + var isEnabled: Bool + var sortIndex: Int + + var folder: SnippetFolder? + + init(title: String, content: String = "", sortIndex: Int = 0) { + self.title = title + self.content = content + self.isEnabled = true + self.sortIndex = sortIndex + } +} diff --git a/Sources/Models/SnippetFolder.swift b/Sources/Models/SnippetFolder.swift new file mode 100644 index 0000000..66a8be9 --- /dev/null +++ b/Sources/Models/SnippetFolder.swift @@ -0,0 +1,18 @@ +import SwiftData + +@Model +final class SnippetFolder { + + var title: String + var isEnabled: Bool + var sortIndex: Int + + @Relationship(deleteRule: .cascade, inverse: \Snippet.folder) + var snippets: [Snippet] = [] + + init(title: String, sortIndex: Int = 0) { + self.title = title + self.isEnabled = true + self.sortIndex = sortIndex + } +} diff --git a/Sources/Scripting/ScriptEngine.swift b/Sources/Scripting/ScriptEngine.swift new file mode 100644 index 0000000..305fba6 --- /dev/null +++ b/Sources/Scripting/ScriptEngine.swift @@ -0,0 +1,105 @@ +import JavaScriptCore +import Foundation +import AppKit + +/// Executes JavaScript action scripts inside a `JSContext`. +/// +/// Replicates the execution environment of `legacy/Source/JavaScriptSupport.m`: +/// - `clipText` global string +/// - `clip` global ScriptableClip bridge object +/// - `ClipMenu.require(relativePath)` library loader +final class ScriptEngine { + + private let context: JSContext + + init() { + context = JSContext()! + context.name = "ClipMenu Script Engine" + setup() + } + + /// Runs `script` source with `clip` injected as a global. + /// Returns the string result, or `nil` on error / undefined result. + func run(script: String, clip: ScriptableClip) -> String? { + let clipText = clip.text ?? "" + + context.evaluateScript("var __scriptException = '';") + context.setObject(clipText, forKeyedSubscript: "clipText" as NSString) + context.setObject(clip, forKeyedSubscript: "clip" as NSString) + + let wrapped = """ + function __wrapper(clipText, clip) { + try { \(script) } catch(e) { __scriptException = e.toString(); return; } + } + """ + context.evaluateScript(wrapped) + + let result = context.evaluateScript("__wrapper(clipText, clip)") + + if let exc = context.objectForKeyedSubscript("__scriptException")?.toString(), + !exc.isEmpty { + return nil + } + guard let result, !result.isUndefined, !result.isNull else { return nil } + return result.toString() + } + + // MARK: - Private + + private func setup() { + context.exceptionHandler = { _, exception in + print("[ScriptEngine] exception: \(exception?.toString() ?? "?")") + } + + // ClipMenu.require(relativePath) — loads a lib script and returns success. + let requireBlock: @convention(block) (String) -> Bool = { [weak self] relativePath in + guard let self, !relativePath.isEmpty else { return false } + guard let source = self.libSource(for: relativePath) else { return false } + self.context.evaluateScript(source) + return true + } + + // ClipMenu.activate() — compatibility hook for scripts that prompt. + let activateBlock: @convention(block) () -> Void = { + DispatchQueue.main.async { + NSApp.activate(ignoringOtherApps: true) + } + } + let namespace = JSValue(newObjectIn: context) + namespace?.setObject(requireBlock, forKeyedSubscript: "require" as NSString) + namespace?.setObject(activateBlock, forKeyedSubscript: "activate" as NSString) + context.setObject(namespace, forKeyedSubscript: "ClipMenu" as NSString) + } + + private func libSource(for relativePath: String) -> String? { + let pathsToTry: [String] + if relativePath.lowercased().hasSuffix(".js") { + pathsToTry = [relativePath] + } else { + pathsToTry = [relativePath, "\(relativePath).js"] + } + + // Bundle resources first, then user support folder + for path in pathsToTry { + let bundleLegacyURL = Bundle.main.resourceURL? + .appendingPathComponent("script/lib") + .appendingPathComponent(path) + let bundleModernURL = Bundle.main.resourceURL? + .appendingPathComponent("scripts/lib") + .appendingPathComponent(path) + let userURL = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first? + .appendingPathComponent("ClipMenu/script/lib") + .appendingPathComponent(path) + + for url in [bundleLegacyURL, bundleModernURL, userURL].compactMap({ $0 }) { + if let source = try? String(contentsOf: url, encoding: .utf8) { + return source + } + } + } + + return nil + } +} diff --git a/Sources/Scripting/ScriptableClip.swift b/Sources/Scripting/ScriptableClip.swift new file mode 100644 index 0000000..c5f9ee6 --- /dev/null +++ b/Sources/Scripting/ScriptableClip.swift @@ -0,0 +1,157 @@ +import JavaScriptCore +import AppKit + +/// The JavaScript-visible bridge object that exposes clipboard content to +/// action scripts. +/// +/// Replicates the JSExport protocol surface from +/// `legacy/Source/ScriptableClip.{h,m}`. +@objc protocol ScriptableClipExports: JSExport { + var text: String? { get } + func setStringAttributes(_ attrs: [String: Any]) + func addStringAttributes(_ attrs: [String: Any]) +} + +@objc final class ScriptableClip: NSObject, ScriptableClipExports { + + private let entry: ClipEntry + + init(entry: ClipEntry) { + self.entry = entry + } + + var text: String? { entry.stringValue } + + func setStringAttributes(_ attrs: [String: Any]) { + applyAttributes(attrs, mode: .set) + } + + func addStringAttributes(_ attrs: [String: Any]) { + applyAttributes(attrs, mode: .add) + } + + // MARK: - Private + + private enum AttributeMode { case set, add } + + private func applyAttributes(_ attrs: [String: Any], mode: AttributeMode) { + guard entry.stringValue != nil, let rtfData = entry.rtfData else { return } + + let attrString: NSMutableAttributedString + if entry.isRTFD { + attrString = NSMutableAttributedString(rtfd: rtfData, documentAttributes: nil) + ?? NSMutableAttributedString() + } else { + attrString = NSMutableAttributedString(rtf: rtfData, documentAttributes: nil) + ?? NSMutableAttributedString() + } + + let range = NSRange(location: 0, length: attrString.length) + var nsAttrs: [NSAttributedString.Key: Any] = [:] + + if let colorDict = attrs["color"] as? [String: Any] { + if let fg = colorDict["foreground"] as? String, + let color = NSColor(cssName: fg) { + nsAttrs[.foregroundColor] = color + } + if let bg = colorDict["background"] as? String, + let color = NSColor(cssName: bg) { + nsAttrs[.backgroundColor] = color + } + } + + if let fontDict = attrs["font"] as? [String: Any], + let name = fontDict["name"] as? String, + let size = fontDict["size"] as? CGFloat, + let font = NSFont(name: name, size: size) { + nsAttrs[.font] = font + } + + if let ulDict = attrs["underline"] as? [String: Any] { + var mask: Int = 0 + mask |= underlineStyle(from: ulDict["style"] as? String) + mask |= underlinePattern(from: ulDict["pattern"] as? String) + if (ulDict["byWord"] as? Bool) == true { mask |= NSUnderlineStyle.byWord.rawValue } + nsAttrs[.underlineStyle] = mask + } + + guard !nsAttrs.isEmpty else { return } + attrString.beginEditing() + switch mode { + case .set: attrString.setAttributes(nsAttrs, range: range) + case .add: attrString.addAttributes(nsAttrs, range: range) + } + attrString.fixAttributes(in: range) + attrString.endEditing() + + if entry.isRTFD { + entry.rtfData = attrString.rtfd(from: range, documentAttributes: [:]) + } else { + entry.rtfData = attrString.rtf(from: range, documentAttributes: [:]) + } + } + + private func underlineStyle(from name: String?) -> Int { + switch name?.lowercased() { + case "single": return NSUnderlineStyle.single.rawValue + case "thick": return NSUnderlineStyle.thick.rawValue + case "double": return NSUnderlineStyle.double.rawValue + default: return 0 + } + } + + private func underlinePattern(from name: String?) -> Int { + switch name?.lowercased() { + case "dot": return NSUnderlineStyle.patternDot.rawValue + case "dash": return NSUnderlineStyle.patternDash.rawValue + case "dashdot": return NSUnderlineStyle.patternDashDot.rawValue + case "dashdotdot": return NSUnderlineStyle.patternDashDotDot.rawValue + default: return 0 + } + } +} + +// MARK: - NSColor CSS name extension + +private extension NSColor { + convenience init?(cssName: String) { + // Hex color support: #RGB, #RRGGBB + if cssName.hasPrefix("#") { + let hex = cssName.dropFirst() + var value: UInt64 = 0 + guard Scanner(string: String(hex)).scanHexInt64(&value) else { return nil } + let length = hex.count + if length == 3 { + let r = CGFloat((value >> 8) & 0xF) / 15.0 + let g = CGFloat((value >> 4) & 0xF) / 15.0 + let b = CGFloat(value & 0xF) / 15.0 + self.init(red: r, green: g, blue: b, alpha: 1) + } else if length == 6 { + let r = CGFloat((value >> 16) & 0xFF) / 255.0 + let g = CGFloat((value >> 8) & 0xFF) / 255.0 + let b = CGFloat(value & 0xFF) / 255.0 + self.init(red: r, green: g, blue: b, alpha: 1) + } else { + return nil + } + return + } + // Named CSS colors (subset used by legacy JavaScriptSupport) + let named: [String: (CGFloat, CGFloat, CGFloat)] = [ + "black": (0, 0, 0), "white": (1, 1, 1), + "red": (1, 0, 0), "green": (0, 0.502, 0), + "blue": (0, 0, 1), "yellow": (1, 1, 0), + "cyan": (0, 1, 1), "magenta": (1, 0, 1), + "orange": (1, 0.647, 0), "purple": (0.502, 0, 0.502), + "brown": (0.647, 0.165, 0.165), + "gray": (0.502, 0.502, 0.502), + "grey": (0.502, 0.502, 0.502), + "silver": (0.753, 0.753, 0.753), + ] + if let rgb = named[cssName.lowercased()] { + self.init(red: rgb.0, green: rgb.1, blue: rgb.2, alpha: 1) + } else { + return nil + } + } +} diff --git a/Sources/Services/ActionService.swift b/Sources/Services/ActionService.swift new file mode 100644 index 0000000..ef05a59 --- /dev/null +++ b/Sources/Services/ActionService.swift @@ -0,0 +1,252 @@ +import SwiftData +import AppKit +import Foundation + +enum ActionExecutionContext { + case pasteContext + case transformOnly + + var shouldPaste: Bool { + self == .pasteContext + } +} + +/// Manages the action tree and dispatches script execution. +/// +/// Reference: `legacy/Source/ActionController.{h,m}`, +/// `ActionNode.{h,m}`, `ActionNodeFactory.{h,m}`, +/// `BuiltInActionController.{h,m}`, `JavaScriptSupport.{h,m}`. +actor ActionService { + + private var context: ModelContext? + private let engine = ScriptEngine() + private let paste = PasteService() + + func start(context: ModelContext) { + self.context = context + seedDefaultActionsIfNeeded() + } + + /// Root-level action nodes sorted by persisted order. + func rootActions() async -> [ActionNode] { + guard let context else { return [] } + let descriptor = FetchDescriptor( + predicate: #Predicate { $0.parent == nil }, + sortBy: [SortDescriptor(\ActionNode.sortIndex)] + ) + return (try? context.fetch(descriptor)) ?? [] + } + + func rootActionCount() async -> Int { + await rootActions().count + } + + func availableActions(for entry: ClipEntry) async -> [ActionNode] { + guard let context else { return [] } + do { + return try context.fetch(FetchDescriptor( + sortBy: [SortDescriptor(\ActionNode.sortIndex)] + )) + } catch { + return [] + } + } + + /// Dispatches an action node against a clip entry. + /// The action result is inserted as a new top clipboard item and copied to + /// pasteboard. Paste synthesis happens only in paste context. + func perform(action node: ActionNode, on entry: ClipEntry, executionContext: ActionExecutionContext = .pasteContext) async { + guard node.isEnabled else { return } + + switch node.actionType { + + case "javaScript": + guard let script = scriptSource(for: node) else { return } + let scriptableClip = ScriptableClip(entry: entry) + guard let resultText = engine.run(script: script, clip: scriptableClip) else { return } + await replaceClipWithString(resultText, for: entry, shouldPaste: executionContext.shouldPaste) + + case "builtin": + await performBuiltin(name: node.actionName ?? "", on: entry, executionContext: executionContext) + + default: + break + } + } + + // MARK: - Built-in actions + // Keep in sync with legacy/Source/BuiltInActionController.m + + private func performBuiltin(name: String, on entry: ClipEntry, executionContext: ActionExecutionContext) async { + switch name { + case "removeAction": + guard let context else { return } + await MainActor.run { + context.delete(entry) + try? context.save() + } + + case "pasteAsPlainText": + guard let text = entry.stringValue else { return } + await replaceClipWithString(text, for: entry, shouldPaste: executionContext.shouldPaste) + + case "pasteAsFilePath": + guard let files = entry.filenames, !files.isEmpty else { return } + let text = files.joined(separator: "\n") + await replaceClipWithString(text, for: entry, shouldPaste: executionContext.shouldPaste) + + case "pasteAsHFSFilePath": + guard let files = entry.filenames, !files.isEmpty else { return } + let hfsPaths = files.compactMap { posixPath -> String? in + let url = URL(fileURLWithPath: posixPath) as CFURL + return CFURLCopyFileSystemPath(url, CFURLPathStyle(rawValue: 1)!) as String? + } + let text = hfsPaths.joined(separator: "\n") + await replaceClipWithString(text, for: entry, shouldPaste: executionContext.shouldPaste) + + default: + break + } + } + + private func replaceClipWithString(_ string: String, for entry: ClipEntry, shouldPaste: Bool) async { + guard let context else { return } + + await MainActor.run { + let transformed = ClipEntry() + transformed.types = [NSPasteboard.PasteboardType.string.rawValue] + transformed.stringValue = string + transformed.createdAt = .now + transformed.lastUsedAt = .now + + context.insert(transformed) + + try? context.save() + + let pboard = NSPasteboard.general + pboard.clearContents() + pboard.setString(string, forType: .string) + } + + if shouldPaste { + await paste.paste() + } + } + + // MARK: - Helpers + + private func scriptSource(for node: ActionNode) -> String? { + if let inline = node.scriptContent, !inline.isEmpty { return inline } + if let path = node.scriptPath { return try? String(contentsOfFile: path, encoding: .utf8) } + return nil + } + + private func seedDefaultActionsIfNeeded() { + guard let context else { return } + + let existingCount = (try? context.fetchCount(FetchDescriptor())) ?? 0 + guard existingCount == 0 else { return } + + var roots: [ActionNode] = [] + + roots.append(makeBuiltin(title: "Paste as Plain Text", name: "pasteAsPlainText", sortIndex: 0)) + roots.append(makeBuiltin(title: "Paste as File Path", name: "pasteAsFilePath", sortIndex: 1)) + roots.append(makeBuiltin(title: "Paste as HFS File Path", name: "pasteAsHFSFilePath", sortIndex: 2)) + roots.append(makeBuiltin(title: "Remove", name: "removeAction", sortIndex: 3)) + + var nextSortIndex = roots.count + for directory in scriptSearchRoots() { + let scriptRoots = discoverActionNodes(in: directory) + guard !scriptRoots.isEmpty else { continue } + for node in scriptRoots { + node.sortIndex = nextSortIndex + nextSortIndex += 1 + roots.append(node) + } + } + + for node in roots { + context.insert(node) + } + try? context.save() + } + + private func makeBuiltin(title: String, name: String, sortIndex: Int) -> ActionNode { + let node = ActionNode(title: title, isLeaf: true, sortIndex: sortIndex) + node.actionType = "builtin" + node.actionName = name + return node + } + + private func scriptSearchRoots() -> [URL] { + var roots: [URL] = [] + + if let bundleRoot = Bundle.main.resourceURL { + roots.append(bundleRoot.appendingPathComponent("script/action")) + roots.append(bundleRoot.appendingPathComponent("scripts/action")) + } + + if let appSupport = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first { + roots.append(appSupport.appendingPathComponent("ClipMenu/script/action")) + } + + var seen = Set() + return roots.filter { url in + let key = url.standardizedFileURL.path + guard !seen.contains(key) else { return false } + seen.insert(key) + return true + } + } + + private func discoverActionNodes(in directory: URL) -> [ActionNode] { + let fm = FileManager.default + guard let entries = try? fm.contentsOfDirectory( + at: directory, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles] + ) else { + return [] + } + + let sortedEntries = entries.sorted { + $0.lastPathComponent.localizedCaseInsensitiveCompare($1.lastPathComponent) == .orderedAscending + } + + var result: [ActionNode] = [] + var index = 0 + + for url in sortedEntries { + let isDirectory = (try? url.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory ?? false + + if isDirectory { + let children = discoverActionNodes(in: url) + guard !children.isEmpty else { continue } + let folder = ActionNode(title: url.lastPathComponent, isLeaf: false, sortIndex: index) + index += 1 + for (childIndex, child) in children.enumerated() { + child.sortIndex = childIndex + child.parent = folder + } + folder.children = children + result.append(folder) + continue + } + + guard url.pathExtension.lowercased() == "js" else { continue } + let node = ActionNode( + title: url.deletingPathExtension().lastPathComponent, + isLeaf: true, + sortIndex: index + ) + index += 1 + node.actionType = "javaScript" + node.scriptPath = url.path + result.append(node) + } + + return result + } +} diff --git a/Sources/Services/ClipsService.swift b/Sources/Services/ClipsService.swift new file mode 100644 index 0000000..3fb78f5 --- /dev/null +++ b/Sources/Services/ClipsService.swift @@ -0,0 +1,256 @@ +import SwiftData +import AppKit +import Combine +import os + +/// Manages the clipboard history: monitors NSPasteboard, deduplicates entries, +/// enforces the max-history limit, and writes ClipEntry records to SwiftData. +/// +/// Reference: `legacy/Source/ClipsController.{h,m}` and `Clip.{h,m}`. +@MainActor +final class ClipsService { + private static let log = Logger(subsystem: "com.naotaka.ClipMenu", category: "ClipsService") + + private let monitor = ClipboardMonitor() + private let exclusion = AppExclusionService() + private let paste = PasteService() + private let settings: ClipMenuSettings + + private var context: ModelContext? + private var cancellables = Set() + + init(settings: ClipMenuSettings = ClipMenuSettings()) { + self.settings = settings + } + + func start(context: ModelContext) { + self.context = context + exclusion.update(from: settings) + Task { + await enforceHistoryLimitNow() + } + monitor.start() + monitor.pasteboardChanged + .sink { [weak self] pasteboard in + Task { + await self?.handlePasteboardChange(pasteboard) + } + } + .store(in: &cancellables) + } + + func stop() { + cancellables.removeAll() + monitor.stop() + } + + /// Copies the given entry back onto the system pasteboard and triggers paste. + func select(_ entry: ClipEntry, pasteImmediately: Bool = true) async { + let pboard = NSPasteboard.general + pboard.clearContents() + + var declaredTypes = entry.types.map(NSPasteboard.PasteboardType.init(rawValue:)) + if declaredTypes.isEmpty { + declaredTypes = [.string] + } + pboard.declareTypes(declaredTypes, owner: nil) + + for type in declaredTypes { + switch type { + case .string: + if let value = entry.stringValue { + pboard.setString(value, forType: .string) + } + case .rtfd: + if let data = entry.rtfData { + pboard.setData(data, forType: .rtfd) + } + case .rtf: + if let data = entry.rtfData { + pboard.setData(data, forType: .rtf) + } + case .pdf: + if let data = entry.pdfData { + pboard.setData(data, forType: .pdf) + } + case .fileURL: + if let filenames = entry.filenames { + pboard.setPropertyList(filenames, forType: .fileURL) + } + case .URL: + if let urls = entry.urlStrings { + pboard.setPropertyList(urls, forType: .URL) + } + case .tiff, .png: + if let data = entry.imageData { + pboard.setData(data, forType: .tiff) + } + default: + break + } + } + + entry.lastUsedAt = .now + try? context?.save() + + if pasteImmediately && settings.autoPasteAfterSelection { + Self.log.debug("Auto-paste after clip selection is ON (immediate)") + await paste.paste() + } else { + Self.log.debug("Clip selected without immediate paste (pasteImmediately=\(pasteImmediately, privacy: .public), setting=\(self.settings.autoPasteAfterSelection, privacy: .public))") + } + } + + private func handlePasteboardChange(_ pboard: NSPasteboard) async { + exclusion.update(from: settings) + if exclusion.shouldExclude() { + return + } + + guard let clip = makeClip(from: pboard) else { return } + guard let context else { return } + + do { + let existing = try context.fetch(FetchDescriptor()) + if let matched = existing.first(where: { $0.contentHash == clip.contentHash }) { + matched.lastUsedAt = .now + if matched.imageData != nil || clip.imageData != nil { + Self.log.debug("Matched existing image clip hash=\(clip.contentHash, privacy: .public) imageBytes=\(clip.imageData?.count ?? 0, privacy: .public)") + } + try context.save() + return + } + + context.insert(clip) + if clip.imageData != nil { + Self.log.info("Inserted image clip hash=\(clip.contentHash, privacy: .public) imageBytes=\(clip.imageData?.count ?? 0, privacy: .public) types=\(clip.types.joined(separator: ","), privacy: .public)") + } + trimHistoryIfNeeded(context: context) + try context.save() + } catch { + Self.log.error("Failed handling pasteboard change: \(error.localizedDescription, privacy: .public)") + return + } + } + + private func enforceHistoryLimitNow() async { + guard let context else { return } + trimHistoryIfNeeded(context: context) + try? context.save() + } + + private func trimHistoryIfNeeded(context: ModelContext) { + do { + var descriptor = FetchDescriptor(sortBy: [SortDescriptor(\ClipEntry.createdAt, order: .reverse)]) + descriptor.fetchLimit = max(settings.maxHistorySize, 0) + 500 + let clips = try context.fetch(descriptor) + let maxSize = max(settings.maxHistorySize, 0) + guard clips.count > maxSize else { return } + + for clip in clips[maxSize...] { + context.delete(clip) + } + } catch { + return + } + } + + private func makeClip(from pboard: NSPasteboard) -> ClipEntry? { + guard let pbTypes = pboard.types, !pbTypes.isEmpty else { return nil } + + let filtered = filteredTypes(from: pbTypes) + guard !filtered.isEmpty else { return nil } + + let clip = ClipEntry() + clip.types = filtered.map(\.rawValue) + + for pbType in filtered { + switch pbType { + case .string: + clip.stringValue = pboard.string(forType: .string) + case .rtfd: + clip.rtfData = pboard.data(forType: .rtfd) + clip.isRTFD = true + case .rtf: + if clip.rtfData == nil { + clip.rtfData = pboard.data(forType: .rtf) + clip.isRTFD = false + } + case .pdf: + clip.pdfData = pboard.data(forType: .pdf) + case .fileURL: + clip.filenames = pboard.propertyList(forType: .fileURL) as? [String] + case .URL: + clip.urlStrings = pboard.propertyList(forType: .URL) as? [String] + case .tiff, .png: + clip.imageData = pboard.data(forType: .tiff) ?? pboard.data(forType: .png) + if clip.imageData == nil { + Self.log.debug("Image type seen but no image bytes. pbTypes=\(filtered.map(\.rawValue).joined(separator: ","), privacy: .public)") + } else { + Self.log.debug("Captured image bytes=\(clip.imageData?.count ?? 0, privacy: .public)") + } + default: + break + } + } + + return clip + } + + private func filteredTypes(from pbTypes: [NSPasteboard.PasteboardType]) -> [NSPasteboard.PasteboardType] { + var results: [NSPasteboard.PasteboardType] = [] + + for pbType in pbTypes { + guard shouldStore(pbType) else { continue } + + if pbType == .tiff || pbType == .png { + if !results.contains(.tiff) { + results.append(.tiff) + } + continue + } + + results.append(pbType) + } + + return results + } + + private func shouldStore(_ type: NSPasteboard.PasteboardType) -> Bool { + guard let typeName = legacyTypeName(for: type) else { return false } + return settings.storeTypes[typeName] ?? false + } + + private func legacyTypeName(for type: NSPasteboard.PasteboardType) -> String? { + switch type { + case .string: return "String" + case .rtf: return "RTF" + case .rtfd: return "RTFD" + case .pdf: return "PDF" + case .fileURL: return "Filenames" + case .URL: return "URL" + case .tiff, .png: return "TIFF" + default: return nil + } + } + + func clearAll() async throws { + guard let context else { return } + let all = try context.fetch(FetchDescriptor()) + for entry in all { context.delete(entry) } + try context.save() + } + + /// Writes a plain string to the pasteboard and triggers paste. + func copyStringToPasteboard(_ string: String, pasteImmediately: Bool = true) async { + let pboard = NSPasteboard.general + pboard.clearContents() + pboard.setString(string, forType: .string) + if pasteImmediately && settings.autoPasteAfterSelection { + Self.log.debug("Auto-paste after snippet selection is ON (immediate)") + await paste.paste() + } else { + Self.log.debug("Snippet copied without immediate paste (pasteImmediately=\(pasteImmediately, privacy: .public), setting=\(self.settings.autoPasteAfterSelection, privacy: .public))") + } + } +} diff --git a/Sources/Services/SnippetService.swift b/Sources/Services/SnippetService.swift new file mode 100644 index 0000000..0c7043c --- /dev/null +++ b/Sources/Services/SnippetService.swift @@ -0,0 +1,84 @@ +import SwiftData +import AppKit +import Foundation + +/// CRUD operations over SnippetFolder / Snippet records. +/// +/// Reference: `legacy/Source/SnippetsController.{h,m}`. +actor SnippetService { + + private var context: ModelContext? + + func start(context: ModelContext) { + self.context = context + } + + func folders() throws -> [SnippetFolder] { + guard let context else { return [] } + return try context.fetch(FetchDescriptor(sortBy: [SortDescriptor(\SnippetFolder.sortIndex)])) + } + + func createFolder(title: String) throws -> SnippetFolder { + guard let context else { return SnippetFolder(title: title, sortIndex: 0) } + let current = try folders() + let folder = SnippetFolder(title: title, sortIndex: current.count) + context.insert(folder) + try context.save() + return folder + } + + func updateFolder(_ folder: SnippetFolder, title: String? = nil, isEnabled: Bool? = nil) throws { + if let title { + folder.title = title + } + if let isEnabled { + folder.isEnabled = isEnabled + } + try context?.save() + } + + func deleteFolder(_ folder: SnippetFolder) throws { + context?.delete(folder) + try context?.save() + } + + func createSnippet(in folder: SnippetFolder, title: String, content: String = "") throws -> Snippet { + let sortIndex = folder.snippets.map(\.sortIndex).max().map { $0 + 1 } ?? 0 + let snippet = Snippet(title: title, content: content, sortIndex: sortIndex) + snippet.folder = folder + context?.insert(snippet) + try context?.save() + return snippet + } + + func updateSnippet(_ snippet: Snippet, title: String? = nil, content: String? = nil, isEnabled: Bool? = nil) throws { + if let title { + snippet.title = title + } + if let content { + snippet.content = content + } + if let isEnabled { + snippet.isEnabled = isEnabled + } + try context?.save() + } + + func deleteSnippet(_ snippet: Snippet) throws { + context?.delete(snippet) + try context?.save() + } + + func moveSnippet(_ snippet: Snippet, to folder: SnippetFolder, at index: Int) throws { + snippet.folder = folder + snippet.sortIndex = max(index, 0) + try context?.save() + } + + func paste(snippet: Snippet) async { + let pboard = NSPasteboard.general + pboard.clearContents() + pboard.setString(snippet.content, forType: .string) + await PasteService().paste() + } +} diff --git a/Sources/Settings/ClipMenuSettings.swift b/Sources/Settings/ClipMenuSettings.swift new file mode 100644 index 0000000..6c8eeb6 --- /dev/null +++ b/Sources/Settings/ClipMenuSettings.swift @@ -0,0 +1,291 @@ +import Foundation +import Observation + +@Observable +final class ClipMenuSettings { + + private let defaults: UserDefaults + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + registerLegacyDefaultsIfNeeded() + loadFromDefaults() + sanitizeAndPersist() + } + + // MARK: - General + + var launchAtLogin: Bool = false { didSet { defaults.set(launchAtLogin, forKey: "loginItem") } } + var suppressLoginItemAlert: Bool = false { didSet { defaults.set(suppressLoginItemAlert, forKey: "suppressAlertForLoginItem") } } + var autoPasteAfterSelection: Bool = true { didSet { defaults.set(autoPasteAfterSelection, forKey: "inputPasteCommand") } } + var reorderClipsAfterPasting: Bool = true { didSet { defaults.set(reorderClipsAfterPasting, forKey: "reorderClipsAfterPasting") } } + var maxHistorySize: Int = 20 { didSet { defaults.set(maxHistorySize, forKey: "maxHistorySize") } } + var saveHistoryOnQuit: Bool = true { didSet { defaults.set(saveHistoryOnQuit, forKey: "saveHistoryOnQuit") } } + var exportHistoryAsSingleFile: Bool = true { didSet { defaults.set(exportHistoryAsSingleFile, forKey: "exportHistoryAsSingleFile") } } + var exportSeparatorTag: Int = 1 { didSet { defaults.set(exportSeparatorTag, forKey: "tagOfSeparatorForExportHistoryToFile") } } + var showStatusItem: Bool = true { didSet { defaults.set(showStatusItem, forKey: "showStatusItem") } } + var storeTypes: [String: Bool] = [ + "String": true, + "RTF": true, + "RTFD": true, + "PDF": true, + "Filenames": true, + "URL": true, + "TIFF": true, + "PICT": true, + ] { didSet { defaults.set(storeTypes, forKey: "storeTypes") } } + var excludeApps: [[String: String]] = [[ + "bundleIdentifier": "org.openoffice.script", + "name": "OpenOffice.org", + ]] { didSet { defaults.set(excludeApps, forKey: "excludeApps") } } + + // MARK: - Menu + + var maxMenuItemTitleLength: Int = 20 { didSet { defaults.set(maxMenuItemTitleLength, forKey: "maxMenuItemTitleLength") } } + var numberOfItemsInline: Int = 0 { didSet { defaults.set(numberOfItemsInline, forKey: "numberOfItemsPlaceInline") } } + var numberOfItemsInsideFolder: Int = 10 { didSet { defaults.set(numberOfItemsInsideFolder, forKey: "numberOfItemsPlaceInsideFolder") } } + var numberedMenuItems: Bool = true { didSet { defaults.set(numberedMenuItems, forKey: "menuItemsAreMarkedWithNumbers") } } + var numberingStartsAtZero: Bool = false { didSet { defaults.set(numberingStartsAtZero, forKey: "menuItemsTitleStartWithZero") } } + var numericKeyEquivalents: Bool = false { didSet { defaults.set(numericKeyEquivalents, forKey: "addNumericKeyEquivalents") } } + var showClearHistoryItem: Bool = true { didSet { defaults.set(showClearHistoryItem, forKey: "addClearHistoryMenuItem") } } + var showAlertBeforeClearHistory: Bool = true { didSet { defaults.set(showAlertBeforeClearHistory, forKey: "showAlertBeforeClearHistory") } } + var showLabelsInMenu: Bool = true { didSet { defaults.set(showLabelsInMenu, forKey: "showLabelsInMenu") } } + var showTooltipsInMenu: Bool = true { didSet { defaults.set(showTooltipsInMenu, forKey: "showToolTipOnMenuItem") } } + var maxTooltipLength: Int = 200 { didSet { defaults.set(maxTooltipLength, forKey: "maxLengthOfToolTipKey") } } + var changeFontSize: Bool = false { didSet { defaults.set(changeFontSize, forKey: "changeFontSize") } } + var fontSizeMode: Int = 0 { didSet { defaults.set(fontSizeMode, forKey: "howToChangeFontSize") } } + var selectedFontSize: Int = 14 { didSet { defaults.set(selectedFontSize, forKey: "selectedFontSize") } } + var showImageInMenu: Bool = true { didSet { defaults.set(showImageInMenu, forKey: "showImageInTheMenu") } } + var thumbnailWidth: Int = 100 { didSet { defaults.set(thumbnailWidth, forKey: "thumbnailWidth") } } + var thumbnailHeight: Int = 32 { didSet { defaults.set(thumbnailHeight, forKey: "thumbnailHeight") } } + var showIconInMenu: Bool = true { didSet { defaults.set(showIconInMenu, forKey: "showIconInTheMenu") } } + var menuIconSize: Int = 16 { didSet { defaults.set(menuIconSize, forKey: "menuIconSize") } } + var menuIconOfFileTypeTagForString: Int = 1 { didSet { defaults.set(menuIconOfFileTypeTagForString, forKey: "menuIconOfFileTypeTagForString") } } + var menuIconOfFileTypeForString: String = "TEXT" { didSet { defaults.set(menuIconOfFileTypeForString, forKey: "menuIconOfFileTypeForString") } } + var menuIconOfFileTypeTagForRTF: Int = 0 { didSet { defaults.set(menuIconOfFileTypeTagForRTF, forKey: "menuIconOfFileTypeTagForRTF") } } + var menuIconOfFileTypeForRTF: String = "rtf" { didSet { defaults.set(menuIconOfFileTypeForRTF, forKey: "menuIconOfFileTypeForRTF") } } + var menuIconOfFileTypeTagForRTFD: Int = 0 { didSet { defaults.set(menuIconOfFileTypeTagForRTFD, forKey: "menuIconOfFileTypeTagForRTFD") } } + var menuIconOfFileTypeForRTFD: String = "rtfd" { didSet { defaults.set(menuIconOfFileTypeForRTFD, forKey: "menuIconOfFileTypeForRTFD") } } + var menuIconOfFileTypeTagForPDF: Int = 0 { didSet { defaults.set(menuIconOfFileTypeTagForPDF, forKey: "menuIconOfFileTypeTagForPDF") } } + var menuIconOfFileTypeForPDF: String = "pdf" { didSet { defaults.set(menuIconOfFileTypeForPDF, forKey: "menuIconOfFileTypeForPDF") } } + var menuIconOfFileTypeTagForFilenames: Int = 1 { didSet { defaults.set(menuIconOfFileTypeTagForFilenames, forKey: "menuIconOfFileTypeTagForFilenames") } } + var menuIconOfFileTypeForFilenames: String = "clpu" { didSet { defaults.set(menuIconOfFileTypeForFilenames, forKey: "menuIconOfFileTypeForFilenames") } } + var menuIconOfFileTypeTagForURL: Int = 1 { didSet { defaults.set(menuIconOfFileTypeTagForURL, forKey: "menuIconOfFileTypeTagForURL") } } + var menuIconOfFileTypeForURL: String = "gurl" { didSet { defaults.set(menuIconOfFileTypeForURL, forKey: "menuIconOfFileTypeForURL") } } + var menuIconOfFileTypeTagForTIFF: Int = 0 { didSet { defaults.set(menuIconOfFileTypeTagForTIFF, forKey: "menuIconOfFileTypeTagForTIFF") } } + var menuIconOfFileTypeForTIFF: String = "tiff" { didSet { defaults.set(menuIconOfFileTypeForTIFF, forKey: "menuIconOfFileTypeForTIFF") } } + var menuIconOfFileTypeTagForPICT: Int = 0 { didSet { defaults.set(menuIconOfFileTypeTagForPICT, forKey: "menuIconOfFileTypeTagForPICT") } } + var menuIconOfFileTypeForPICT: String = "pict" { didSet { defaults.set(menuIconOfFileTypeForPICT, forKey: "menuIconOfFileTypeForPICT") } } + + // MARK: - Hot Keys + + var hotKeys: [String: Any] = [ + "ClipMenu": ["keyCode": 9, "modifiers": 768], + "HistoryMenu": ["keyCode": 9, "modifiers": 4352], + "SnippetsMenu": ["keyCode": 11, "modifiers": 768], + ] { didSet { defaults.set(hotKeys, forKey: "hotKeys") } } + + // MARK: - Actions + + var enableAction: Bool = true { didSet { defaults.set(enableAction, forKey: "enableAction") } } + var invokeActionImmediately: Bool = false { didSet { defaults.set(invokeActionImmediately, forKey: "invokeActionImmediately") } } + var controlClickBehavior: String = "popUpActionMenu" { didSet { defaults.set(controlClickBehavior, forKey: "controlClickBehavior") } } + var shiftClickBehavior: String = "" { didSet { defaults.set(shiftClickBehavior, forKey: "shiftClickBehavior") } } + var optionClickBehavior: String = "" { didSet { defaults.set(optionClickBehavior, forKey: "optionClickBehavior") } } + var commandClickBehavior: String = "" { didSet { defaults.set(commandClickBehavior, forKey: "commandClickBehavior") } } + + // MARK: - Snippets + + var positionOfSnippets: Int = 1 { didSet { defaults.set(positionOfSnippets, forKey: "positionOfSnippets") } } + + // MARK: - Updates + + var enableAutomaticCheck: Bool = true { didSet { defaults.set(enableAutomaticCheck, forKey: "enableAutomaticCheck") } } + var enableAutomaticCheckPreRelease: Bool = false { didSet { defaults.set(enableAutomaticCheckPreRelease, forKey: "enableAutomaticCheckPreReleaseKey") } } + var updateCheckInterval: Int = 86_400 { didSet { defaults.set(updateCheckInterval, forKey: "updateCheckInterval") } } + + /// Re-reads all persisted keys from UserDefaults. + /// Useful on startup and after external defaults changes. + func reload() { + loadFromDefaults() + sanitizeAndPersist() + } + + private func boolValue(_ key: String, default fallback: Bool) -> Bool { + (defaults.object(forKey: key) as? Bool) ?? fallback + } + + private func intValue(_ key: String, default fallback: Int) -> Int { + (defaults.object(forKey: key) as? Int) ?? fallback + } + + private func stringValue(_ key: String, default fallback: String) -> String { + (defaults.object(forKey: key) as? String) ?? fallback + } + + private func loadFromDefaults() { + launchAtLogin = boolValue("loginItem", default: false) + suppressLoginItemAlert = boolValue("suppressAlertForLoginItem", default: false) + autoPasteAfterSelection = boolValue("inputPasteCommand", default: true) + reorderClipsAfterPasting = boolValue("reorderClipsAfterPasting", default: true) + maxHistorySize = intValue("maxHistorySize", default: 20) + saveHistoryOnQuit = boolValue("saveHistoryOnQuit", default: true) + exportHistoryAsSingleFile = boolValue("exportHistoryAsSingleFile", default: true) + exportSeparatorTag = intValue("tagOfSeparatorForExportHistoryToFile", default: 1) + showStatusItem = boolValue("showStatusItem", default: true) + storeTypes = (defaults.dictionary(forKey: "storeTypes") as? [String: Bool]) ?? Self.defaultStoreTypes + excludeApps = (defaults.array(forKey: "excludeApps") as? [[String: String]]) ?? Self.defaultExcludeApps + + maxMenuItemTitleLength = intValue("maxMenuItemTitleLength", default: 20) + numberOfItemsInline = intValue("numberOfItemsPlaceInline", default: 0) + numberOfItemsInsideFolder = intValue("numberOfItemsPlaceInsideFolder", default: 10) + numberedMenuItems = boolValue("menuItemsAreMarkedWithNumbers", default: true) + numberingStartsAtZero = boolValue("menuItemsTitleStartWithZero", default: false) + numericKeyEquivalents = boolValue("addNumericKeyEquivalents", default: false) + showClearHistoryItem = boolValue("addClearHistoryMenuItem", default: true) + showAlertBeforeClearHistory = boolValue("showAlertBeforeClearHistory", default: true) + showLabelsInMenu = boolValue("showLabelsInMenu", default: true) + showTooltipsInMenu = boolValue("showToolTipOnMenuItem", default: true) + maxTooltipLength = intValue("maxLengthOfToolTipKey", default: 200) + changeFontSize = boolValue("changeFontSize", default: false) + fontSizeMode = intValue("howToChangeFontSize", default: 0) + selectedFontSize = intValue("selectedFontSize", default: 14) + showImageInMenu = boolValue("showImageInTheMenu", default: true) + thumbnailWidth = intValue("thumbnailWidth", default: 100) + thumbnailHeight = intValue("thumbnailHeight", default: 32) + showIconInMenu = boolValue("showIconInTheMenu", default: true) + menuIconSize = intValue("menuIconSize", default: 16) + menuIconOfFileTypeTagForString = intValue("menuIconOfFileTypeTagForString", default: 1) + menuIconOfFileTypeForString = stringValue("menuIconOfFileTypeForString", default: "TEXT") + menuIconOfFileTypeTagForRTF = intValue("menuIconOfFileTypeTagForRTF", default: 0) + menuIconOfFileTypeForRTF = stringValue("menuIconOfFileTypeForRTF", default: "rtf") + menuIconOfFileTypeTagForRTFD = intValue("menuIconOfFileTypeTagForRTFD", default: 0) + menuIconOfFileTypeForRTFD = stringValue("menuIconOfFileTypeForRTFD", default: "rtfd") + menuIconOfFileTypeTagForPDF = intValue("menuIconOfFileTypeTagForPDF", default: 0) + menuIconOfFileTypeForPDF = stringValue("menuIconOfFileTypeForPDF", default: "pdf") + menuIconOfFileTypeTagForFilenames = intValue("menuIconOfFileTypeTagForFilenames", default: 1) + menuIconOfFileTypeForFilenames = stringValue("menuIconOfFileTypeForFilenames", default: "clpu") + menuIconOfFileTypeTagForURL = intValue("menuIconOfFileTypeTagForURL", default: 1) + menuIconOfFileTypeForURL = stringValue("menuIconOfFileTypeForURL", default: "gurl") + menuIconOfFileTypeTagForTIFF = intValue("menuIconOfFileTypeTagForTIFF", default: 0) + menuIconOfFileTypeForTIFF = stringValue("menuIconOfFileTypeForTIFF", default: "tiff") + menuIconOfFileTypeTagForPICT = intValue("menuIconOfFileTypeTagForPICT", default: 0) + menuIconOfFileTypeForPICT = stringValue("menuIconOfFileTypeForPICT", default: "pict") + + hotKeys = defaults.dictionary(forKey: "hotKeys") ?? Self.defaultHotKeys + + enableAction = boolValue("enableAction", default: true) + invokeActionImmediately = boolValue("invokeActionImmediately", default: false) + controlClickBehavior = stringValue("controlClickBehavior", default: "popUpActionMenu") + shiftClickBehavior = stringValue("shiftClickBehavior", default: "") + optionClickBehavior = stringValue("optionClickBehavior", default: "") + commandClickBehavior = stringValue("commandClickBehavior", default: "") + + positionOfSnippets = intValue("positionOfSnippets", default: 1) + + enableAutomaticCheck = boolValue("enableAutomaticCheck", default: true) + enableAutomaticCheckPreRelease = boolValue("enableAutomaticCheckPreReleaseKey", default: false) + updateCheckInterval = intValue("updateCheckInterval", default: 86_400) + } + + private func sanitizeAndPersist() { + maxHistorySize = max(maxHistorySize, 1) + + maxMenuItemTitleLength = max(maxMenuItemTitleLength, 1) + numberOfItemsInline = max(numberOfItemsInline, 0) + numberOfItemsInsideFolder = max(numberOfItemsInsideFolder, 1) + maxTooltipLength = max(maxTooltipLength, 1) + selectedFontSize = max(selectedFontSize, 8) + thumbnailWidth = max(thumbnailWidth, 1) + thumbnailHeight = max(thumbnailHeight, 1) + menuIconSize = [16, 32, 48].contains(menuIconSize) ? menuIconSize : 16 + fontSizeMode = [0, 1].contains(fontSizeMode) ? fontSizeMode : 0 + positionOfSnippets = [0, 1, 2].contains(positionOfSnippets) ? positionOfSnippets : 1 + + if controlClickBehavior.isEmpty { controlClickBehavior = "popUpActionMenu" } + } + + private func registerLegacyDefaultsIfNeeded() { + defaults.register(defaults: [ + "hotKeys": Self.defaultHotKeys, + "loginItem": false, + "suppressAlertForLoginItem": false, + "inputPasteCommand": true, + "reorderClipsAfterPasting": true, + "maxHistorySize": 20, + "saveHistoryOnQuit": true, + "exportHistoryAsSingleFile": true, + "tagOfSeparatorForExportHistoryToFile": 1, + "showStatusItem": true, + "storeTypes": Self.defaultStoreTypes, + "excludeApps": Self.defaultExcludeApps, + "maxMenuItemTitleLength": 20, + "numberOfItemsPlaceInline": 0, + "numberOfItemsPlaceInsideFolder": 10, + "menuItemsAreMarkedWithNumbers": true, + "menuItemsTitleStartWithZero": false, + "addNumericKeyEquivalents": false, + "addClearHistoryMenuItem": true, + "showAlertBeforeClearHistory": true, + "showLabelsInMenu": true, + "showToolTipOnMenuItem": true, + "maxLengthOfToolTipKey": 200, + "changeFontSize": false, + "howToChangeFontSize": 0, + "selectedFontSize": 14, + "showImageInTheMenu": true, + "thumbnailWidth": 100, + "thumbnailHeight": 32, + "showIconInTheMenu": true, + "menuIconSize": 16, + "menuIconOfFileTypeTagForString": 1, + "menuIconOfFileTypeForString": "TEXT", + "menuIconOfFileTypeTagForRTF": 0, + "menuIconOfFileTypeForRTF": "rtf", + "menuIconOfFileTypeTagForRTFD": 0, + "menuIconOfFileTypeForRTFD": "rtfd", + "menuIconOfFileTypeTagForPDF": 0, + "menuIconOfFileTypeForPDF": "pdf", + "menuIconOfFileTypeTagForFilenames": 1, + "menuIconOfFileTypeForFilenames": "clpu", + "menuIconOfFileTypeTagForURL": 1, + "menuIconOfFileTypeForURL": "gurl", + "menuIconOfFileTypeTagForTIFF": 0, + "menuIconOfFileTypeForTIFF": "tiff", + "menuIconOfFileTypeTagForPICT": 0, + "menuIconOfFileTypeForPICT": "pict", + "enableAction": true, + "invokeActionImmediately": false, + "controlClickBehavior": "popUpActionMenu", + "shiftClickBehavior": "", + "optionClickBehavior": "", + "commandClickBehavior": "", + "positionOfSnippets": 1, + "enableAutomaticCheck": true, + "enableAutomaticCheckPreReleaseKey": false, + "updateCheckInterval": 86_400, + ]) + } + + private static let defaultStoreTypes: [String: Bool] = [ + "String": true, + "RTF": true, + "RTFD": true, + "PDF": true, + "Filenames": true, + "URL": true, + "TIFF": true, + "PICT": true, + ] + + private static let defaultExcludeApps: [[String: String]] = [[ + "bundleIdentifier": "org.openoffice.script", + "name": "OpenOffice.org", + ]] + + private static let defaultHotKeys: [String: [String: Int]] = [ + "ClipMenu": ["keyCode": 9, "modifiers": 768], + "HistoryMenu": ["keyCode": 9, "modifiers": 4352], + "SnippetsMenu": ["keyCode": 11, "modifiers": 768], + ] +} diff --git a/Sources/UI/ActionMenuBuilder.swift b/Sources/UI/ActionMenuBuilder.swift new file mode 100644 index 0000000..759410c --- /dev/null +++ b/Sources/UI/ActionMenuBuilder.swift @@ -0,0 +1,98 @@ +import AppKit + +/// Builds a native NSMenu from an ActionNode tree for modifier-click popups. +enum ActionMenuBuilder { + + static func makeMenu( + from roots: [ActionNode], + target: ClipEntry, + service: ActionService, + executionContext: ActionExecutionContext = .pasteContext, + postAction: (@MainActor () async -> Void)? = nil + ) -> NSMenu { + let menu = NSMenu() + let sortedRoots = roots + .filter(\.isEnabled) + .sorted { $0.sortIndex < $1.sortIndex } + + for node in sortedRoots { + menu.addItem( + makeItem( + for: node, + target: target, + service: service, + executionContext: executionContext, + postAction: postAction + ) + ) + } + + return menu + } + + private static func makeItem( + for node: ActionNode, + target: ClipEntry, + service: ActionService, + executionContext: ActionExecutionContext, + postAction: (@MainActor () async -> Void)? + ) -> NSMenuItem { + if node.isLeaf { + let item = NSMenuItem(title: node.title, action: #selector(ActionMenuTarget.handleMenuItemAction(_:)), keyEquivalent: "") + item.target = ActionMenuTarget.shared + item.representedObject = ActionMenuInvocation { + Task { + await service.perform(action: node, on: target, executionContext: executionContext) + if let postAction { + await postAction() + } + } + } + return item + } + + let item = NSMenuItem(title: node.title, action: nil, keyEquivalent: "") + let submenu = NSMenu(title: node.title) + let sortedChildren = node.children + .filter(\.isEnabled) + .sorted { $0.sortIndex < $1.sortIndex } + + for child in sortedChildren { + submenu.addItem( + makeItem( + for: child, + target: target, + service: service, + executionContext: executionContext, + postAction: postAction + ) + ) + } + + item.submenu = submenu + return item + } +} + +/// Bridges NSMenuItem callbacks to async ActionService calls. +final class ActionMenuTarget: NSObject { + static let shared = ActionMenuTarget() + + @objc(handleMenuItemAction:) + func handleMenuItemAction(_ sender: NSMenuItem) { + guard let invocation = sender.representedObject as? ActionMenuInvocation else { return } + invocation.invoke() + } +} + +private final class ActionMenuInvocation: NSObject { + private let handler: () -> Void + + init(handler: @escaping () -> Void) { + self.handler = handler + } + + func invoke() { + handler() + } +} diff --git a/Sources/UI/ActionSection.swift b/Sources/UI/ActionSection.swift new file mode 100644 index 0000000..77cf175 --- /dev/null +++ b/Sources/UI/ActionSection.swift @@ -0,0 +1,67 @@ +import SwiftUI + +/// Renders the action tree as a menu, respecting folder nesting. +/// +/// Mirrors `legacy/Source/MenuController.m` action menu construction and +/// `legacy/Source/ActionController.m` availability filtering. +struct ActionSection: View { + + /// Flat root-level nodes (service fetches and passes these in). + let nodes: [ActionNode] + /// The clip on which the selected action will operate. + let target: ClipEntry + + @Environment(\.actionService) private var actionService + @Environment(\.clipsService) private var clipsService + + var body: some View { + ForEach(nodes.sorted { $0.sortIndex < $1.sortIndex }) { node in + if node.isLeaf { + if node.isEnabled { + Button(node.title) { performAction(node) } + } + } else { + let children = node.children + .filter(\.isEnabled) + .sorted { $0.sortIndex < $1.sortIndex } + if !children.isEmpty { + Menu(node.title) { + ForEach(children) { child in + if child.isLeaf { + Button(child.title) { performAction(child) } + } + } + } + } + } + } + } + + private func performAction(_ node: ActionNode) { + Task { + await actionService.perform(action: node, on: target, executionContext: .pasteContext) + } + } +} + +// MARK: - Preview + +#Preview { + let leaf = ActionNode(title: "Paste as Plain Text", isLeaf: true, sortIndex: 0) + leaf.actionType = "builtin" + leaf.actionName = "pasteAsPlainText" + + let folder = ActionNode(title: "Case", isLeaf: false, sortIndex: 1) + let upper = ActionNode(title: "Uppercase", isLeaf: true, sortIndex: 0) + upper.actionType = "javaScript" + folder.children = [upper] + + let entry = ClipEntry() + entry.stringValue = "hello" + entry.types = ["NSStringPboardType"] + + return ActionSection(nodes: [leaf, folder], target: entry) + .environment(\.actionService, ActionService()) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + .padding() +} diff --git a/Sources/UI/ClipMenuApp+Scenes.swift b/Sources/UI/ClipMenuApp+Scenes.swift new file mode 100644 index 0000000..83e22d2 --- /dev/null +++ b/Sources/UI/ClipMenuApp+Scenes.swift @@ -0,0 +1,4 @@ +import SwiftUI + +// Scene declarations are in Sources/App/ClipMenuApp.swift. +// This file is intentionally empty. diff --git a/Sources/UI/ClipMenuItem.swift b/Sources/UI/ClipMenuItem.swift new file mode 100644 index 0000000..4603fe9 --- /dev/null +++ b/Sources/UI/ClipMenuItem.swift @@ -0,0 +1,356 @@ +import SwiftUI +import AppKit +import UniformTypeIdentifiers +import os + +/// A single row in the clipboard history menu. +/// +/// Rendering rules are taken from `legacy/Source/MenuController.m +/// -_makeMenuItemForClip:withCount:andListNumber:`. +struct ClipMenuItem: View { + private static let log = Logger(subsystem: "com.naotaka.ClipMenu", category: "ClipMenuItem") + + let entry: ClipEntry + /// Numbering prefix (already computed by ClipMenuView). + let listNumber: Int + + @Environment(ClipMenuSettings.self) private var settings + @Environment(\.clipsService) private var clipsService + @Environment(\.actionService) private var actionService + + var body: some View { + Button(action: select) { + itemLabel + } + .help(tooltip) + .modifier(NumericShortcut(number: listNumber % 10, + enabled: settings.numericKeyEquivalents)) + } + + // MARK: - Label + + @ViewBuilder + private var itemLabel: some View { + let thumb = settings.showImageInMenu ? thumbnail : nil + + HStack(spacing: 4) { + // Type icon + if thumb == nil, settings.showIconInMenu, let icon = typeIcon { + Image(nsImage: icon) + .resizable() + .frame(width: CGFloat(settings.menuIconSize), + height: CGFloat(settings.menuIconSize)) + } + + // Image thumbnail + if let thumb { + Image(nsImage: thumb) + } + + // Title text + Text(titleText) + .font(itemFont) + + // Type label badge + if settings.showLabelsInMenu, let label = primaryTypeName { + Text("[\(label)]") + .foregroundStyle(.secondary) + .font(itemFont) + } + } + } + + // MARK: - Title + + private var titleText: String { + var t = trimmedTitle + if settings.numberedMenuItems { + t = "\(listNumber). \(t)" + } + return t + } + + /// Replicates `trimTitle()` from `legacy/Source/MenuController.m`. + private var trimmedTitle: String { + let source = entry.stringValue + ?? entry.filenames?.first + ?? entry.urlStrings?.first + ?? "" + let stripped = source.trimmingCharacters(in: .whitespacesAndNewlines) + let firstLine: String + if let nl = stripped.firstIndex(of: "\n") { + firstLine = String(stripped[.. maxLen { + return String(firstLine.prefix(max(maxLen - 3, 0))) + "..." + } + if !firstLine.isEmpty { + return firstLine + } + if entry.imageData != nil { + return "(Image)" + } + return "(binary)" + } + + // MARK: - Visual properties + + private var thumbnail: NSImage? { + guard let data = entry.imageData else { + if titleText.contains("(Image)") { + Self.log.debug("No imageData available for clip labeled as image") + } + return nil + } + guard let img = decodedImage(from: data) else { + Self.log.debug("Failed to decode thumbnail image data bytes=\(data.count, privacy: .public)") + return nil + } + Self.log.debug("Decoded thumbnail image size=\(Int(img.size.width), privacy: .public)x\(Int(img.size.height), privacy: .public) bytes=\(data.count, privacy: .public)") + return scaledImage(img, + to: NSSize(width: CGFloat(settings.thumbnailWidth), + height: CGFloat(settings.thumbnailHeight))) + } + + private var typeIcon: NSImage? { + // Use NSWorkspace to resolve a file-type icon for the primary pasteboard type. + let ext = iconFileExtension(for: entry.types.first ?? "") + guard !ext.isEmpty else { return nil } + let contentType = UTType(filenameExtension: ext) ?? .data + let icon = NSWorkspace.shared.icon(for: contentType) + return scaledImage(icon, to: NSSize(width: CGFloat(settings.menuIconSize), + height: CGFloat(settings.menuIconSize))) + } + + /// Maps a pasteboard type string to the file-extension hint used when + /// asking NSWorkspace for an icon. Mirrors the per-type prefs in settings. + private func iconFileExtension(for type: String) -> String { + switch type { + case "NSStringPboardType", "public.utf8-plain-text": + return settings.menuIconOfFileTypeTagForString == 0 + ? settings.menuIconOfFileTypeForString + : hfsToExt(settings.menuIconOfFileTypeForString) + case "NeXT Rich Text Format v1.0 pasteboard type", "public.rtf": + return settings.menuIconOfFileTypeForRTF + case "NeXT RTFD pasteboard type": + return settings.menuIconOfFileTypeForRTFD + case "Apple PDF pasteboard type", "com.adobe.pdf": + return settings.menuIconOfFileTypeForPDF + case "NSFilenamesPboardType", "public.file-url": + return settings.menuIconOfFileTypeForFilenames + case "Apple URL pasteboard type", "public.url": + return settings.menuIconOfFileTypeForURL + case "NeXT TIFF v4.0 pasteboard type", "public.tiff": + return settings.menuIconOfFileTypeForTIFF + default: + return "" + } + } + + private func hfsToExt(_ hfs: String) -> String { hfs.lowercased() } + + private var primaryTypeName: String? { + let map: [String: String] = [ + "NSStringPboardType": "String", + "public.utf8-plain-text": "String", + "NeXT Rich Text Format v1.0 pasteboard type": "RTF", + "NeXT RTFD pasteboard type": "RTFD", + "Apple PDF pasteboard type": "PDF", + "NSFilenamesPboardType": "Filenames", + "Apple URL pasteboard type": "URL", + "NeXT TIFF v4.0 pasteboard type": "TIFF", + "Apple PICT pasteboard type": "PICT", + ] + return entry.types.compactMap { map[$0] }.first + } + + private var tooltip: String { + guard settings.showTooltipsInMenu else { return "" } + let text = entry.stringValue + ?? entry.filenames?.joined(separator: "\n") + ?? "" + return String(text.prefix(settings.maxTooltipLength)) + } + + private var itemFont: Font { + guard settings.changeFontSize else { return .body } + let size: CGFloat = settings.fontSizeMode == 0 + ? CGFloat(settings.menuIconSize) + : CGFloat(settings.selectedFontSize) + return .system(size: size) + } + + // MARK: - Action + + private func select() { + let flags = NSEvent.modifierFlags.intersection([.control, .shift, .option, .command]) + + guard settings.enableAction else { + Task { await clipsService.select(entry) } + return + } + + if let behavior = behaviorForFlags(flags), !behavior.isEmpty { + if behavior == "popUpActionMenu" { + showActionMenu() + return + } + + if let configuredNode = configuredActionNode(from: behavior) { + Task { await actionService.perform(action: configuredNode, on: entry, executionContext: .pasteContext) } + return + } + } + + Task { await clipsService.select(entry) } + } + + private func behaviorForFlags(_ flags: NSEvent.ModifierFlags) -> String? { + switch flags { + case .control: + return settings.controlClickBehavior + case .shift: + return settings.shiftClickBehavior + case .option: + return settings.optionClickBehavior + case .command: + return settings.commandClickBehavior + default: + return nil + } + } + + private func showActionMenu() { + Task { + let roots = await actionService.rootActions() + let enabledRoots = roots.filter(\.isEnabled) + + if settings.invokeActionImmediately, + enabledRoots.count == 1, + let only = enabledRoots.first, + only.isLeaf { + await actionService.perform(action: only, on: entry, executionContext: .pasteContext) + return + } + + await MainActor.run { + let menu = ActionMenuBuilder.makeMenu(from: enabledRoots, target: entry, service: actionService) + let event = NSApp.currentEvent + if let view = event?.window?.contentView { + let pointInWindow = event?.locationInWindow ?? .zero + let pointInView = view.convert(pointInWindow, from: nil) + menu.popUp(positioning: nil, at: pointInView, in: view) + } else { + menu.popUp(positioning: nil, at: NSEvent.mouseLocation, in: nil) + } + } + } + } + + private func configuredActionNode(from rawBehavior: String) -> ActionNode? { + guard let data = rawBehavior.data(using: .utf8), + let object = try? JSONSerialization.jsonObject(with: data), + let dict = object as? [String: Any] else { + return nil + } + + let type = (dict["type"] as? String) ?? "" + let node = ActionNode(title: (dict["name"] as? String) ?? "Configured Action", isLeaf: true) + + if type == "javaScript" || type == "js" { + node.actionType = "javaScript" + node.scriptPath = dict["path"] as? String + node.scriptContent = dict["content"] as? String + return node + } + + if type == "builtin" { + node.actionType = "builtin" + node.actionName = dict["name"] as? String + return node + } + + return nil + } + + // MARK: - Helpers + + private func scaledImage(_ image: NSImage, to size: NSSize) -> NSImage { + guard image.size.width > 0, image.size.height > 0, + size.width > 0, size.height > 0 else { + return image + } + + let ratio = min(size.width / image.size.width, size.height / image.size.height) + let drawSize = NSSize(width: image.size.width * ratio, height: image.size.height * ratio) + let drawOrigin = NSPoint(x: (size.width - drawSize.width) / 2, + y: (size.height - drawSize.height) / 2) + + let scaled = NSImage(size: size) + scaled.lockFocus() + image.draw(in: NSRect(origin: drawOrigin, size: drawSize), + from: .zero, + operation: .sourceOver, + fraction: 1.0) + scaled.unlockFocus() + return scaled + } + + private func decodedImage(from data: Data) -> NSImage? { + if let image = NSImage(data: data), image.size.width > 0, image.size.height > 0 { + return image + } + + if let rep = NSBitmapImageRep(data: data) { + let image = NSImage(size: rep.size) + image.addRepresentation(rep) + return image + } + + return NSImage(data: data) + } +} + +private struct NumericShortcut: ViewModifier { + let number: Int + let enabled: Bool + + func body(content: Content) -> some View { + if enabled, let char = Character(String(number)).asciiDigit { + content.keyboardShortcut(KeyEquivalent(char), modifiers: []) + } else { + content + } + } +} + +private extension Character { + var asciiDigit: Character? { + guard self >= "0", self <= "9" else { return nil } + return self + } +} + +// MARK: - Preview + +#Preview("String clip") { + let entry = ClipEntry() + entry.stringValue = "Hello, world! This is a sample clipboard entry." + entry.types = ["NSStringPboardType"] + return ClipMenuItem(entry: entry, listNumber: 1) + .environment(ClipMenuSettings()) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + .padding() +} + +#Preview("Binary clip") { + let entry = ClipEntry() + entry.types = ["NeXT TIFF v4.0 pasteboard type"] + return ClipMenuItem(entry: entry, listNumber: 2) + .environment(ClipMenuSettings()) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + .padding() +} diff --git a/Sources/UI/ClipMenuView.swift b/Sources/UI/ClipMenuView.swift new file mode 100644 index 0000000..6a89016 --- /dev/null +++ b/Sources/UI/ClipMenuView.swift @@ -0,0 +1,165 @@ +import SwiftUI +import SwiftData + +/// Root content of the status-bar MenuBarExtra. +/// +/// Mirrors the menu hierarchy from `legacy/Source/MenuController.m -buildClipMenu`. +struct ClipMenuView: View { + private let runtime = AppRuntime.shared + + @Query(sort: \ClipEntry.lastUsedAt, order: .reverse) private var clips: [ClipEntry] + @Query(sort: \SnippetFolder.sortIndex) private var folders: [SnippetFolder] + @Query( + filter: #Predicate { $0.parent == nil }, + sort: \ActionNode.sortIndex + ) private var rootActions: [ActionNode] + + @Environment(ClipMenuSettings.self) private var settings + @Environment(\.clipsService) private var clipsService + @Environment(\.snippetService) private var snippetService + + var body: some View { + // Snippets above clips + if settings.positionOfSnippets == 0 { + SnippetSection(folders: folders.filter(\.isEnabled)) + Divider() + } + + // Clip history rows + clipsSection + + // Snippets below clips (default) + if settings.positionOfSnippets == 1 { + Divider() + SnippetSection(folders: folders.filter(\.isEnabled)) + } + + if settings.enableAction { + Divider() + Menu { + if let targetClip = clips.first { + let enabledRoots = rootActions.filter(\.isEnabled) + if enabledRoots.isEmpty { + Text("No actions configured") + } else { + ActionSection(nodes: enabledRoots, target: targetClip) + } + } else { + Text("No clips available") + } + } label: { + Label("Actions", systemImage: "bolt") + } + } + + // Clear History + if settings.showClearHistoryItem { + Divider() + Button(action: clearHistory) { + Label("Clear History", systemImage: "trash") + } + } + + Divider() + + Button { + runtime.showPreferences(tab: .snippets) + } label: { + Label("Edit Snippets…", systemImage: "text.badge.plus") + } + Button { + runtime.showPreferences() + } label: { + Label("Preferences…", systemImage: "gearshape") + } + Button { + NSApp.terminate(nil) + } label: { + Label("Quit ClipMenu", systemImage: "power") + } + } + + // MARK: - Clips section + + // Computed outside @ViewBuilder so SwiftUI's dependency tracking reliably + // sees the @Query `clips` property on every render. + + private var inlineClips: [ClipEntry] { + let n = settings.numberOfItemsInline + let capped = Array(clips.prefix(max(settings.maxHistorySize, 0))) + // Legacy: n == 0 → all items go into folder submenus (mirrors ObjC behaviour). + return n == 0 ? [] : Array(capped.prefix(n)) + } + + /// Groups of clips that appear inside folder submenus. + private var folderGroups: [[ClipEntry]] { + let n = settings.numberOfItemsInline + let groupSize = max(settings.numberOfItemsInsideFolder, 1) + let capped = Array(clips.prefix(max(settings.maxHistorySize, 0))) + let remaining = n == 0 ? capped : Array(capped.dropFirst(n)) + guard !remaining.isEmpty else { return [] } + return stride(from: 0, to: remaining.count, by: groupSize).map { + Array(remaining[$0.. Int { + if settings.numberingStartsAtZero { + return index % 10 + } else { + let n = index + 1 + return n > 10 ? n % 10 : n + } + } + + private func clearHistory() { + if settings.showAlertBeforeClearHistory { + let alert = NSAlert() + alert.messageText = "Clear History" + alert.informativeText = "Are you sure you want to clear all clipboard history?" + alert.addButton(withTitle: "Clear") + alert.addButton(withTitle: "Cancel") + guard alert.runModal() == .alertFirstButtonReturn else { return } + } + Task { try? await clipsService.clearAll() } + } +} + +// MARK: - Preview + +#Preview { + ClipMenuView() + .environment(ClipMenuSettings()) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + .environment(\.snippetService, SnippetService()) + .modelContainer(for: [ClipEntry.self, SnippetFolder.self, Snippet.self, ActionNode.self], + inMemory: true) +} diff --git a/Sources/UI/Preferences/ActionsPrefsView.swift b/Sources/UI/Preferences/ActionsPrefsView.swift new file mode 100644 index 0000000..d7521e6 --- /dev/null +++ b/Sources/UI/Preferences/ActionsPrefsView.swift @@ -0,0 +1,733 @@ +import SwiftUI +import SwiftData +import Foundation + +/// Actions tab in the Preferences window. +/// +/// Covers: enable toggle, modifier-click behaviours, invoke-immediately. +/// Reference: `legacy/Source/PrefsWindowController.{h,m}` Actions tab. +struct ActionsPrefsView: View { + + @Environment(ClipMenuSettings.self) private var settings + @Environment(\.modelContext) private var modelContext + + @Query(filter: #Predicate { $0.parent == nil }, + sort: \ActionNode.sortIndex) + private var rootNodes: [ActionNode] + + @State private var selectedNodeID: PersistentIdentifier? + @State private var selectedCatalogID: String? + @State private var rightTab: RightTab = .builtin + + private struct ClickBehaviorOption: Identifiable { + let id: String + let title: String + let value: String + } + + private enum RightTab: String, CaseIterable { + case builtin = "Built-in" + case javaScript = "JavaScript" + case users = "User's" + } + + private struct AvailableActionItem: Identifiable, Hashable { + var id: String + var name: String + var actionType: String + var actionName: String? + var scriptPath: String? + } + + private struct CatalogNode: Identifiable, Hashable { + var id: String + var name: String + var isLeaf: Bool + var item: AvailableActionItem? + var children: [CatalogNode] + + var visibleChildren: [CatalogNode]? { + children.isEmpty ? nil : children + } + } + + var body: some View { + @Bindable var s = settings + VStack(spacing: 12) { + Form { + Section("Action System") { + Toggle("Enable actions", isOn: $s.enableAction) + Toggle("Invoke action immediately when only one is available", + isOn: $s.invokeActionImmediately) + .disabled(!settings.enableAction) + } + + Section("Modified-Click Behaviour") { + clickBehaviorPicker("Control+click", binding: $s.controlClickBehavior) + clickBehaviorPicker("Shift+click", binding: $s.shiftClickBehavior) + clickBehaviorPicker("Option+click", binding: $s.optionClickBehavior) + clickBehaviorPicker("Command+click", binding: $s.commandClickBehavior) + } + .disabled(!settings.enableAction) + } + + Divider() + + Text("Action Menu") + .font(.headline) + .frame(maxWidth: .infinity, alignment: .leading) + + GeometryReader { proxy in + let spacing: CGFloat = 12 + let controlsWidth: CGFloat = 120 + let columnWidth = max(260, (proxy.size.width - controlsWidth - (spacing * 2)) / 2) + + HStack(alignment: .top, spacing: spacing) { + actionTreePane + .frame(width: columnWidth) + + actionControlsPane + .frame(width: controlsWidth) + + actionCatalogPane + .frame(width: columnWidth) + } + } + .frame(minHeight: 320) + + HStack(spacing: 8) { + Text("Name:") + .font(.caption) + .foregroundStyle(.secondary) + TextField("Action name", text: Binding( + get: { selectedNode?.title ?? "" }, + set: { newValue in + guard let selectedNode else { return } + selectedNode.title = newValue + persist() + } + )) + .disabled(selectedNode == nil) + } + } + .formStyle(.grouped) + .padding() + .onAppear { + if selectedNodeID == nil { + selectedNodeID = rootNodes.first?.persistentModelID + } + } + .onChange(of: rootNodes.count) { _, _ in + if selectedNode == nil { + selectedNodeID = rootNodes.first?.persistentModelID + } + } + } + + // MARK: - Helpers + + /// Picker that maps between the stored behavior string and a display label. + /// Legacy values: "" (no-op), "popUpActionMenu" (show action menu). + @ViewBuilder + private func clickBehaviorPicker(_ label: String, binding: Binding) -> some View { + let options = clickBehaviorOptions + Picker(label, selection: binding) { + ForEach(options) { option in + Text(option.title).tag(option.value) + } + if !options.contains(where: { $0.value == binding.wrappedValue }) { + Text("Custom action").tag(binding.wrappedValue) + } + } + .pickerStyle(.menu) + } + + private var actionTreePane: some View { + VStack(alignment: .leading, spacing: 8) { + Text("Current actions") + .font(.subheadline) + .fontWeight(.medium) + + List(selection: $selectedNodeID) { + OutlineGroup(sortedRoots, children: \.sortedChildrenForUI) { node in + HStack(spacing: 8) { + Toggle("", isOn: Binding( + get: { node.isEnabled }, + set: { newValue in + node.isEnabled = newValue + persist() + } + )) + .labelsHidden() + .toggleStyle(.checkbox) + + Image(systemName: node.isLeaf ? "bolt.fill" : "folder.fill") + .foregroundStyle(node.isLeaf ? .orange : .accentColor) + + Text(node.title) + .lineLimit(1) + + Spacer(minLength: 0) + } + .tag(node.persistentModelID) + .draggable(nodeToken(node)) + .dropDestination(for: String.self) { items, _ in + guard let sourceToken = items.first else { return false } + return handleDrop(sourceToken: sourceToken, onto: node) + } + } + } + .listStyle(.sidebar) + .dropDestination(for: String.self) { items, _ in + guard let sourceToken = items.first, + let source = nodeForToken(sourceToken) + else { return false } + + return moveNode(source, destinationParent: nil, destinationIndex: sortedRoots.count) + } + } + } + + private var actionControlsPane: some View { + VStack(spacing: 8) { + Button { + addSelectedCatalogAction() + } label: { + Label("Add", systemImage: "plus") + } + .disabled(selectedCatalogItem == nil) + + Button { + addFolder() + } label: { + Label("Folder", systemImage: "folder.badge.plus") + } + + Button(role: .destructive) { + removeSelectedNode() + } label: { + Label("Delete", systemImage: "trash") + } + .disabled(selectedNode == nil) + + Divider() + + Button { + moveSelectedNode(delta: -1) + } label: { + Label("Up", systemImage: "arrow.up") + } + .disabled(!canMoveSelectedNode(delta: -1)) + + Button { + moveSelectedNode(delta: 1) + } label: { + Label("Down", systemImage: "arrow.down") + } + .disabled(!canMoveSelectedNode(delta: 1)) + } + .controlSize(.small) + .buttonStyle(.bordered) + .padding(.top, 28) + } + + private var actionCatalogPane: some View { + VStack(alignment: .leading, spacing: 8) { + Picker("", selection: $rightTab) { + ForEach(RightTab.allCases, id: \.self) { tab in + Text(tab.rawValue).tag(tab) + } + } + .pickerStyle(.segmented) + + List(selection: $selectedCatalogID) { + OutlineGroup(catalogNodes, children: \.visibleChildren) { node in + HStack(spacing: 8) { + Image(systemName: node.isLeaf ? "bolt.fill" : "folder.fill") + .foregroundStyle(node.isLeaf ? .orange : .accentColor) + Text(node.name) + } + .tag(node.id) + } + } + .listStyle(.sidebar) + } + } + + private var sortedRoots: [ActionNode] { + rootNodes.sorted { $0.sortIndex < $1.sortIndex } + } + + private var selectedNode: ActionNode? { + guard let selectedNodeID else { return nil } + return allNodes.first { $0.persistentModelID == selectedNodeID } + } + + private var allNodes: [ActionNode] { + flatten(nodes: sortedRoots) + } + + private var selectedCatalogItem: AvailableActionItem? { + guard let selectedCatalogID else { return nil } + return catalogLeafItemsByID[selectedCatalogID] + } + + private var catalogLeafItemsByID: [String: AvailableActionItem] { + var result: [String: AvailableActionItem] = [:] + + func collect(_ nodes: [CatalogNode]) { + for node in nodes { + if let item = node.item { + result[item.id] = item + } + if !node.children.isEmpty { + collect(node.children) + } + } + } + + collect(catalogNodes) + return result + } + + private var clickBehaviorOptions: [ClickBehaviorOption] { + var options: [ClickBehaviorOption] = [ + ClickBehaviorOption(id: "none", title: "No action", value: ""), + ClickBehaviorOption(id: "popup", title: "Show action menu", value: "popUpActionMenu"), + ] + + let leaves = allNodes + .filter { $0.isLeaf && $0.isEnabled } + .sorted { + $0.title.localizedCaseInsensitiveCompare($1.title) == .orderedAscending + } + + options.append(contentsOf: leaves.compactMap { node in + guard let behavior = serializedBehavior(for: node) else { return nil } + return ClickBehaviorOption( + id: nodeToken(node), + title: "Run \(node.title)", + value: behavior + ) + }) + + return options + } + + private var catalogNodes: [CatalogNode] { + switch rightTab { + case .builtin: + return [ + CatalogNode( + id: "builtin:pasteAsPlainText", + name: "Paste as Plain Text", + isLeaf: true, + item: AvailableActionItem(id: "builtin:pasteAsPlainText", name: "Paste as Plain Text", actionType: "builtin", actionName: "pasteAsPlainText"), + children: [] + ), + CatalogNode( + id: "builtin:pasteAsFilePath", + name: "Paste as File Path", + isLeaf: true, + item: AvailableActionItem(id: "builtin:pasteAsFilePath", name: "Paste as File Path", actionType: "builtin", actionName: "pasteAsFilePath"), + children: [] + ), + CatalogNode( + id: "builtin:pasteAsHFSFilePath", + name: "Paste as HFS File Path", + isLeaf: true, + item: AvailableActionItem(id: "builtin:pasteAsHFSFilePath", name: "Paste as HFS File Path", actionType: "builtin", actionName: "pasteAsHFSFilePath"), + children: [] + ), + CatalogNode( + id: "builtin:removeAction", + name: "Remove", + isLeaf: true, + item: AvailableActionItem(id: "builtin:removeAction", name: "Remove", actionType: "builtin", actionName: "removeAction"), + children: [] + ), + ] + case .javaScript: + let bundleURL = Bundle.main.resourceURL?.appendingPathComponent("scripts/action") + return scriptCatalogNodes(in: bundleURL) + case .users: + let userURL = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first? + .appendingPathComponent("ClipMenu/script/action") + return scriptCatalogNodes(in: userURL) + } + } + + private func scriptCatalogNodes(in root: URL?) -> [CatalogNode] { + guard let root else { return [] } + + struct ScriptRecord { + let relativePath: String + let fullPath: String + } + + let fm = FileManager.default + guard let enumerator = fm.enumerator( + at: root, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles] + ) else { + return [] + } + + var records: [ScriptRecord] = [] + for case let url as URL in enumerator { + guard url.pathExtension.lowercased() == "js" else { continue } + let relative = url.path.replacingOccurrences(of: root.path + "/", with: "") + records.append(ScriptRecord(relativePath: relative, fullPath: url.path)) + } + + final class MutableNode { + let id: String + let name: String + var isLeaf: Bool + var item: AvailableActionItem? + var children: [String: MutableNode] = [:] + + init(id: String, name: String, isLeaf: Bool, item: AvailableActionItem? = nil) { + self.id = id + self.name = name + self.isLeaf = isLeaf + self.item = item + } + } + + let rootNode = MutableNode(id: "root", name: "root", isLeaf: false) + + for record in records { + let parts = record.relativePath.split(separator: "/").map(String.init) + guard !parts.isEmpty else { continue } + + var cursor = rootNode + for (idx, part) in parts.enumerated() { + let isLast = idx == parts.count - 1 + if isLast { + let name = part.replacingOccurrences(of: ".js", with: "") + let item = AvailableActionItem( + id: "script:\(record.fullPath)", + name: name, + actionType: "javaScript", + actionName: nil, + scriptPath: record.fullPath + ) + cursor.children[name] = MutableNode( + id: item.id, + name: name, + isLeaf: true, + item: item + ) + } else { + if cursor.children[part] == nil { + cursor.children[part] = MutableNode( + id: "folder:\(parts.prefix(idx + 1).joined(separator: "/"))", + name: part, + isLeaf: false + ) + } + if let next = cursor.children[part] { + cursor = next + } + } + } + } + + func freeze(_ node: MutableNode) -> CatalogNode { + let sortedChildren = node.children.values + .sorted { lhs, rhs in + if lhs.isLeaf != rhs.isLeaf { + return lhs.isLeaf && !rhs.isLeaf ? false : true + } + return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending + } + .map(freeze) + + return CatalogNode( + id: node.id, + name: node.name, + isLeaf: node.isLeaf, + item: node.item, + children: sortedChildren + ) + } + + return rootNode.children.values + .sorted { lhs, rhs in + if lhs.isLeaf != rhs.isLeaf { + return lhs.isLeaf && !rhs.isLeaf ? false : true + } + return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending + } + .map(freeze) + } + + private func addSelectedCatalogAction() { + guard let item = selectedCatalogItem else { return } + let newNode = ActionNode(title: item.name, isLeaf: true, sortIndex: 0) + newNode.actionType = item.actionType + newNode.actionName = item.actionName + newNode.scriptPath = item.scriptPath + insert(node: newNode, into: selectedFolderTarget) + selectedNodeID = newNode.persistentModelID + } + + private func addFolder() { + let newFolder = ActionNode(title: "New Folder", isLeaf: false, sortIndex: 0) + insert(node: newFolder, into: selectedFolderTarget) + selectedNodeID = newFolder.persistentModelID + } + + private var selectedFolderTarget: ActionNode? { + guard let selectedNode else { return nil } + return selectedNode.isLeaf ? selectedNode.parent : selectedNode + } + + private func insert(node: ActionNode, into folder: ActionNode?) { + if let folder { + node.parent = folder + node.sortIndex = nextSortIndex(in: folder) + folder.children.append(node) + } else { + node.parent = nil + node.sortIndex = nextRootSortIndex() + } + + modelContext.insert(node) + persist() + } + + private func removeSelectedNode() { + guard let selectedNode else { return } + let parent = selectedNode.parent + let selectedID = selectedNode.persistentModelID + + modelContext.delete(selectedNode) + normalizeSiblings(in: parent) + persist() + + if selectedNodeID == selectedID { + if let parent { + selectedNodeID = parent.persistentModelID + } else { + selectedNodeID = rootNodes.first?.persistentModelID + } + } + } + + private func canMoveSelectedNode(delta: Int) -> Bool { + guard let selectedNode else { return false } + let siblings = siblingsOfSelectedNode(selectedNode) + guard let index = siblings.firstIndex(where: { $0.persistentModelID == selectedNode.persistentModelID }) else { + return false + } + let newIndex = index + delta + return newIndex >= 0 && newIndex < siblings.count + } + + private func moveSelectedNode(delta: Int) { + guard let selectedNode else { return } + let siblings = siblingsOfSelectedNode(selectedNode) + guard let index = siblings.firstIndex(where: { $0.persistentModelID == selectedNode.persistentModelID }) else { + return + } + let newIndex = index + delta + guard newIndex >= 0 && newIndex < siblings.count else { return } + + let other = siblings[newIndex] + let currentSort = selectedNode.sortIndex + selectedNode.sortIndex = other.sortIndex + other.sortIndex = currentSort + normalizeSiblings(in: selectedNode.parent) + persist() + } + + private func siblingsOfSelectedNode(_ node: ActionNode) -> [ActionNode] { + if let parent = node.parent { + return parent.children.sorted { $0.sortIndex < $1.sortIndex } + } + return sortedRoots + } + + private func nextRootSortIndex() -> Int { + (sortedRoots.last?.sortIndex ?? -1) + 1 + } + + private func nextSortIndex(in folder: ActionNode) -> Int { + let sorted = folder.children.sorted { $0.sortIndex < $1.sortIndex } + return (sorted.last?.sortIndex ?? -1) + 1 + } + + private func normalizeSiblings(in parent: ActionNode?) { + if let parent { + let siblings = parent.children.sorted { $0.sortIndex < $1.sortIndex } + for (idx, node) in siblings.enumerated() { + node.sortIndex = idx + } + return + } + + let roots = sortedRoots + for (idx, node) in roots.enumerated() { + node.sortIndex = idx + } + } + + private func flatten(nodes: [ActionNode]) -> [ActionNode] { + var result: [ActionNode] = [] + for node in nodes.sorted(by: { $0.sortIndex < $1.sortIndex }) { + result.append(node) + result.append(contentsOf: flatten(nodes: node.children)) + } + return result + } + + private func persist() { + try? modelContext.save() + } + + // MARK: - Drag and Drop + + private func nodeToken(_ node: ActionNode) -> String { + String(describing: node.persistentModelID) + } + + private func nodeForToken(_ token: String) -> ActionNode? { + allNodes.first { nodeToken($0) == token } + } + + private func handleDrop(sourceToken: String, onto target: ActionNode) -> Bool { + guard let source = nodeForToken(sourceToken), source !== target else { return false } + + if target.isLeaf { + let parent = target.parent + let siblings = parent == nil + ? sortedRoots + : parent!.children.sorted { $0.sortIndex < $1.sortIndex } + guard let targetIndex = siblings.firstIndex(where: { $0.persistentModelID == target.persistentModelID }) else { + return false + } + return moveNode(source, destinationParent: parent, destinationIndex: targetIndex + 1) + } + + let children = target.children.sorted { $0.sortIndex < $1.sortIndex } + return moveNode(source, destinationParent: target, destinationIndex: children.count) + } + + private func moveNode(_ source: ActionNode, destinationParent: ActionNode?, destinationIndex: Int) -> Bool { + if let destinationParent { + if source === destinationParent || isDescendant(destinationParent, of: source) { + return false + } + } + + let sourceParent = source.parent + if sourceParent === destinationParent { + if sourceParent == nil { + var roots = sortedRoots.filter { $0.persistentModelID != source.persistentModelID } + let insertionIndex = max(0, min(destinationIndex, roots.count)) + roots.insert(source, at: insertionIndex) + renumber(nodes: roots) + persist() + return true + } + + guard let sourceParent else { return false } + var siblings = sourceParent.children + .filter { $0.persistentModelID != source.persistentModelID } + .sorted { $0.sortIndex < $1.sortIndex } + let insertionIndex = max(0, min(destinationIndex, siblings.count)) + siblings.insert(source, at: insertionIndex) + sourceParent.children = siblings + renumber(nodes: siblings) + persist() + return true + } + + if let sourceParent { + sourceParent.children.removeAll { $0.persistentModelID == source.persistentModelID } + renumber(nodes: sourceParent.children.sorted { $0.sortIndex < $1.sortIndex }) + } + + if let destinationParent { + var children = destinationParent.children + .filter { $0.persistentModelID != source.persistentModelID } + .sorted { $0.sortIndex < $1.sortIndex } + let insertionIndex = max(0, min(destinationIndex, children.count)) + source.parent = destinationParent + children.insert(source, at: insertionIndex) + destinationParent.children = children + renumber(nodes: children) + } else { + source.parent = nil + var roots = sortedRoots.filter { $0.persistentModelID != source.persistentModelID } + let insertionIndex = max(0, min(destinationIndex, roots.count)) + roots.insert(source, at: insertionIndex) + renumber(nodes: roots) + } + + selectedNodeID = source.persistentModelID + persist() + return true + } + + private func renumber(nodes: [ActionNode]) { + for (index, node) in nodes.enumerated() { + node.sortIndex = index + } + } + + private func isDescendant(_ candidate: ActionNode, of ancestor: ActionNode) -> Bool { + var current = candidate.parent + while let node = current { + if node === ancestor { return true } + current = node.parent + } + return false + } + + // MARK: - Modifier behavior serialization + + private func serializedBehavior(for node: ActionNode) -> String? { + guard node.isLeaf else { return nil } + + var dict: [String: Any] = ["type": node.actionType ?? ""] + if let name = node.actionName, !name.isEmpty { + dict["name"] = name + } + if let path = node.scriptPath, !path.isEmpty { + dict["path"] = path + } + if let content = node.scriptContent, !content.isEmpty { + dict["content"] = content + } + + guard let data = try? JSONSerialization.data(withJSONObject: dict, options: []), + let json = String(data: data, encoding: .utf8) + else { + return nil + } + + return json + } +} + +private extension ActionNode { + var sortedChildrenForUI: [ActionNode]? { + let sorted = children.sorted { $0.sortIndex < $1.sortIndex } + return sorted.isEmpty ? nil : sorted + } +} + +// MARK: - Preview + +#Preview { + ActionsPrefsView() + .environment(ClipMenuSettings()) + .modelContainer(for: [ActionNode.self], inMemory: true) + .frame(width: 820, height: 620) +} diff --git a/Sources/UI/Preferences/GeneralPrefsView.swift b/Sources/UI/Preferences/GeneralPrefsView.swift new file mode 100644 index 0000000..1dcb81c --- /dev/null +++ b/Sources/UI/Preferences/GeneralPrefsView.swift @@ -0,0 +1,126 @@ +import SwiftUI +import AppKit + +/// General tab in the Preferences window. +/// +/// Covers: login item, paste command, reorder, history size, +/// save-on-quit, status item, store types, app exclusions. +/// Reference: `legacy/Source/PrefsWindowController.{h,m}` General tab. +struct GeneralPrefsView: View { + + @Environment(ClipMenuSettings.self) private var settings + @Environment(\.loginItemService) private var loginItem + + var body: some View { + @Bindable var s = settings + Form { + // MARK: Startup + Section("Startup") { + Toggle("Launch ClipMenu at login", isOn: Binding( + get: { settings.launchAtLogin }, + set: { val in + settings.launchAtLogin = val + try? loginItem.setEnabled(val) + } + )) + } + + // MARK: Clipboard Behaviour + Section("Clipboard") { + Toggle("Paste automatically after selection", isOn: $s.autoPasteAfterSelection) + Toggle("Move used clip to top of history", isOn: $s.reorderClipsAfterPasting) + LabeledContent("Maximum history size") { + TextField("", value: $s.maxHistorySize, format: .number) + .frame(width: 60) + } + Toggle("Save history when quitting", isOn: $s.saveHistoryOnQuit) + } + + // MARK: Store Types + Section("Store Types") { + StoreTypesGrid(settings: settings) + } + + // MARK: Excluded Apps + Section("Excluded Applications") { + ExcludeAppsEditor(settings: settings) + } + } + .formStyle(.grouped) + .padding() + } +} + +// MARK: - Store Types sub-view + +private struct StoreTypesGrid: View { + + let settings: ClipMenuSettings + private let types = ["String", "RTF", "RTFD", "PDF", "Filenames", "URL", "TIFF", "PICT"] + + var body: some View { + LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], alignment: .leading) { + ForEach(types, id: \.self) { typeName in + Toggle(typeName, isOn: Binding( + get: { settings.storeTypes[typeName] ?? true }, + set: { val in + var dict = settings.storeTypes + dict[typeName] = val + settings.storeTypes = dict + } + )) + .toggleStyle(.checkbox) + } + } + } +} + +// MARK: - Excluded apps sub-view + +private struct ExcludeAppsEditor: View { + + let settings: ClipMenuSettings + @State private var selection: String? = nil + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + List(selection: $selection) { + ForEach(settings.excludeApps, id: \.self) { app in + Text(app["name"] ?? app["bundleIdentifier"] ?? "") + .tag(app["bundleIdentifier"]) + } + } + .frame(minHeight: 80) + + HStack { + Button("Add") { addFrontmostApp() } + Button("Remove") { removeSelected() } + .disabled(selection == nil) + } + } + } + + private func addFrontmostApp() { + guard let app = NSWorkspace.shared.frontmostApplication, + let id = app.bundleIdentifier, + let name = app.localizedName, + !settings.excludeApps.contains(where: { $0["bundleIdentifier"] == id }) + else { return } + settings.excludeApps.append(["bundleIdentifier": id, "name": name]) + } + + private func removeSelected() { + guard let sel = selection else { return } + settings.excludeApps.removeAll { $0["bundleIdentifier"] == sel } + selection = nil + } +} + +// MARK: - Preview + +#Preview { + GeneralPrefsView() + .environment(ClipMenuSettings()) + .environment(\.loginItemService, LoginItemService()) + .frame(width: 520) +} diff --git a/Sources/UI/Preferences/MenuPrefsView.swift b/Sources/UI/Preferences/MenuPrefsView.swift new file mode 100644 index 0000000..a7ed877 --- /dev/null +++ b/Sources/UI/Preferences/MenuPrefsView.swift @@ -0,0 +1,119 @@ +import SwiftUI + +/// Menu tab in the Preferences window. +/// +/// Covers: title length, inline/folder counts, numbering, labels, +/// clear-history item, tooltips, font size, thumbnails, icons. +/// Reference: `legacy/Source/PrefsWindowController.{h,m}` Menu tab. +struct MenuPrefsView: View { + + @Environment(ClipMenuSettings.self) private var settings + + var body: some View { + @Bindable var s = settings + Form { + // MARK: Title display + Section("Title Display") { + LabeledContent("Max title length") { + TextField("", value: $s.maxMenuItemTitleLength, format: .number) + .frame(width: 60) + } + Toggle("Prefix items with numbers", isOn: $s.numberedMenuItems) + Toggle("Start numbering at zero", isOn: $s.numberingStartsAtZero) + .disabled(!settings.numberedMenuItems) + Toggle("Add numeric key equivalents (1–0)", isOn: $s.numericKeyEquivalents) + Toggle("Show type label in title", isOn: $s.showLabelsInMenu) + } + + // MARK: Layout + Section("Layout") { + LabeledContent("Items shown inline") { + TextField("", value: $s.numberOfItemsInline, format: .number) + .frame(width: 60) + } + LabeledContent("Items per subfolder") { + TextField("", value: $s.numberOfItemsInsideFolder, format: .number) + .frame(width: 60) + } + Picker("Snippet position", selection: $s.positionOfSnippets) { + Text("Above clips").tag(0) + Text("Below clips").tag(1) + Text("Hidden").tag(2) + } + } + + // MARK: Misc items + Section("Menu Items") { + Toggle("Show \"Clear History\" item", isOn: $s.showClearHistoryItem) + Toggle("Confirm before clearing", isOn: $s.showAlertBeforeClearHistory) + .disabled(!settings.showClearHistoryItem) + } + + // MARK: Tooltips + Section("Tooltips") { + Toggle("Show tooltip on hover", isOn: $s.showTooltipsInMenu) + LabeledContent("Max tooltip length") { + TextField("", value: $s.maxTooltipLength, format: .number) + .frame(width: 80) + } + .disabled(!settings.showTooltipsInMenu) + } + + // MARK: Font + Section("Font Size") { + Toggle("Override menu font size", isOn: $s.changeFontSize) + if settings.changeFontSize { + Picker("Mode", selection: $s.fontSizeMode) { + Text("Match icon size").tag(0) + Text("Manual").tag(1) + } + .pickerStyle(.radioGroup) + if settings.fontSizeMode == 1 { + LabeledContent("Font size (pt)") { + TextField("", value: $s.selectedFontSize, format: .number) + .frame(width: 60) + } + } + } + } + + // MARK: Images + Section("Images") { + Toggle("Show image thumbnails", isOn: $s.showImageInMenu) + if settings.showImageInMenu { + LabeledContent("Thumbnail width (px)") { + TextField("", value: $s.thumbnailWidth, format: .number) + .frame(width: 60) + } + LabeledContent("Thumbnail height (px)") { + TextField("", value: $s.thumbnailHeight, format: .number) + .frame(width: 60) + } + } + } + + // MARK: Icons + Section("Type Icons") { + Toggle("Show type icon", isOn: $s.showIconInMenu) + if settings.showIconInMenu { + Picker("Icon size", selection: $s.menuIconSize) { + Text("16 px").tag(16) + Text("32 px").tag(32) + Text("48 px").tag(48) + } + .pickerStyle(.segmented) + } + } + } + .formStyle(.grouped) + .padding() + } +} + +// MARK: - Preview + +#Preview { + MenuPrefsView() + .environment(ClipMenuSettings()) + .frame(width: 520) +} diff --git a/Sources/UI/Preferences/ShortcutsPrefsView.swift b/Sources/UI/Preferences/ShortcutsPrefsView.swift new file mode 100644 index 0000000..b083daf --- /dev/null +++ b/Sources/UI/Preferences/ShortcutsPrefsView.swift @@ -0,0 +1,34 @@ +import SwiftUI +import KeyboardShortcuts + +/// Shortcuts tab in the Preferences window. +/// +/// Displays `KeyboardShortcuts.Recorder` controls for each global shortcut +/// defined in `HotkeyService`. Defaults match legacy PTHotKey defaults from +/// `legacy/Source/AppController.m +_defaultHotKeyCombos`. +struct ShortcutsPrefsView: View { + var body: some View { + Form { + Section { + KeyboardShortcuts.Recorder("Clipboard menu", name: .openClipMenu) + KeyboardShortcuts.Recorder("History menu", name: .openHistory) + KeyboardShortcuts.Recorder("Snippets menu", name: .openSnippets) + KeyboardShortcuts.Recorder("Actions menu", name: .openActions) + } footer: { + Text("These shortcuts open the ClipMenu status-bar menu. Defaults: ⌘⇧V, ⌘⌃V, ⌘⇧B, ⌘⇧A.") + .foregroundStyle(.secondary) + .font(.footnote) + } + } + .formStyle(.grouped) + .padding() + } +} + +// MARK: - Preview + +#Preview { + ShortcutsPrefsView() + .frame(width: 520) +} + diff --git a/Sources/UI/Preferences/SnippetsPrefsView.swift b/Sources/UI/Preferences/SnippetsPrefsView.swift new file mode 100644 index 0000000..a3a7981 --- /dev/null +++ b/Sources/UI/Preferences/SnippetsPrefsView.swift @@ -0,0 +1,348 @@ +import SwiftUI +import SwiftData + +/// Snippets tab in the Preferences window. +/// +/// Provides basic folder/snippet editing so users can manage items shown +/// in the Snippets menu. +struct SnippetsPrefsView: View { + @Environment(\.modelContext) private var modelContext + @Environment(ClipMenuSettings.self) private var settings + + @Query(sort: \SnippetFolder.sortIndex) private var folders: [SnippetFolder] + + @State private var selectedFolderID: PersistentIdentifier? + @State private var selectedSnippetID: PersistentIdentifier? + @State private var editingFolderID: PersistentIdentifier? + @State private var editingFolderTitle: String = "" + @State private var editingSnippetID: PersistentIdentifier? + @State private var editingSnippetTitle: String = "" + + @FocusState private var isFolderNameFocused: Bool + @FocusState private var isSnippetNameFocused: Bool + + private var selectedFolder: SnippetFolder? { + folders.first { $0.persistentModelID == selectedFolderID } + } + + private var selectedSnippets: [Snippet] { + guard let selectedFolder else { return [] } + return selectedFolder.snippets.sorted { $0.sortIndex < $1.sortIndex } + } + + private var selectedSnippet: Snippet? { + selectedSnippets.first { $0.persistentModelID == selectedSnippetID } + } + + var body: some View { + @Bindable var s = settings + + VStack(alignment: .leading, spacing: 12) { + ViewThatFits(in: .horizontal) { + HStack { + Text("The position to show snippets in ClipMenu:") + Spacer() + Picker("Snippet position", selection: $s.positionOfSnippets) { + Text("Above the clipboard history").tag(0) + Text("Below the clipboard history").tag(1) + Text("Hidden").tag(2) + } + .labelsHidden() + .frame(width: 260) + } + + VStack(alignment: .leading, spacing: 6) { + Text("The position to show snippets in ClipMenu:") + Picker("Snippet position", selection: $s.positionOfSnippets) { + Text("Above the clipboard history").tag(0) + Text("Below the clipboard history").tag(1) + Text("Hidden").tag(2) + } + .labelsHidden() + .frame(maxWidth: .infinity, alignment: .leading) + } + } + + HStack(alignment: .top, spacing: 12) { + foldersPane + .frame(minWidth: 180, idealWidth: 240, maxWidth: .infinity) + snippetsPane + .frame(minWidth: 180, idealWidth: 240, maxWidth: .infinity) + contentPane + .frame(minWidth: 220, idealWidth: 360, maxWidth: .infinity) + } + .frame(maxHeight: .infinity) + } + .padding() + .onAppear { ensureSelection() } + .onChange(of: folders.count) { _, _ in ensureSelection() } + .onChange(of: selectedFolderID) { _, _ in + guard let selectedFolder else { + selectedSnippetID = nil + return + } + if !selectedFolder.snippets.contains(where: { $0.persistentModelID == selectedSnippetID }) { + selectedSnippetID = selectedFolder.snippets.sorted { $0.sortIndex < $1.sortIndex }.first?.persistentModelID + } + editingSnippetID = nil + } + } + + private var foldersPane: some View { + VStack(alignment: .leading, spacing: 8) { + Text("Folders") + .font(.headline) + + VStack(spacing: 8) { + List { + ForEach(folders) { folder in + HStack { + Toggle("", isOn: Binding( + get: { folder.isEnabled }, + set: { newValue in + folder.isEnabled = newValue + persist() + } + )) + .toggleStyle(.checkbox) + .labelsHidden() + + Image(systemName: "folder.fill") + + if editingFolderID == folder.persistentModelID { + TextField("Folder", text: $editingFolderTitle) + .textFieldStyle(.plain) + .focused($isFolderNameFocused) + .onSubmit { commitFolderRename(folder) } + } else { + Text(folder.title) + } + + Spacer() + } + .contentShape(Rectangle()) + .onTapGesture { + selectedFolderID = folder.persistentModelID + } + .onTapGesture(count: 2) { + beginFolderRename(folder) + } + .listRowBackground(folder.persistentModelID == selectedFolderID ? Color.accentColor.opacity(0.15) : Color.clear) + } + } + .listStyle(.plain) + .scrollContentBackground(.hidden) + .frame(maxWidth: .infinity, maxHeight: .infinity) + + ControlGroup { + Button(action: addFolder) { + Image(systemName: "plus") + } + .help("Add Folder") + + Button(action: removeSelectedFolder) { + Image(systemName: "minus") + } + .help("Remove Folder") + .disabled(selectedFolder == nil) + } + .controlSize(.small) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(10) + .background(panelBackground, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) + } + } + + private var snippetsPane: some View { + VStack(alignment: .leading, spacing: 8) { + Text("Title") + .font(.headline) + + if let selectedFolder { + VStack(spacing: 8) { + List { + ForEach(selectedSnippets) { snippet in + HStack { + Toggle("", isOn: Binding( + get: { snippet.isEnabled }, + set: { newValue in + snippet.isEnabled = newValue + persist() + } + )) + .toggleStyle(.checkbox) + .labelsHidden() + + if editingSnippetID == snippet.persistentModelID { + TextField("Title", text: $editingSnippetTitle) + .textFieldStyle(.plain) + .focused($isSnippetNameFocused) + .onSubmit { commitSnippetRename(snippet) } + } else { + Text(snippet.title) + } + Spacer() + } + .contentShape(Rectangle()) + .onTapGesture { + selectedSnippetID = snippet.persistentModelID + } + .onTapGesture(count: 2) { + beginSnippetRename(snippet) + } + .listRowBackground(snippet.persistentModelID == selectedSnippetID ? Color.accentColor.opacity(0.15) : Color.clear) + } + } + .listStyle(.plain) + .scrollContentBackground(.hidden) + .frame(maxWidth: .infinity, maxHeight: .infinity) + + ControlGroup { + Button(action: { addSnippet(to: selectedFolder) }) { + Image(systemName: "plus") + } + .help("Add Snippet") + + Button(action: removeSelectedSnippet) { + Image(systemName: "minus") + } + .help("Remove Snippet") + .disabled(selectedSnippet == nil) + } + .controlSize(.small) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(10) + .background(panelBackground, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) + } else { + ContentUnavailableView("No Folder Selected", systemImage: "text.badge.plus", description: Text("Create a folder to start adding snippets.")) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(10) + .background(panelBackground, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) + } + } + } + + private var contentPane: some View { + VStack(alignment: .leading, spacing: 8) { + Text("Content") + .font(.headline) + + TextEditor(text: Binding( + get: { selectedSnippet?.content ?? "" }, + set: { newValue in + guard let selectedSnippet else { return } + selectedSnippet.content = newValue + persist() + } + )) + .frame(minHeight: 280, maxHeight: .infinity) + .scrollContentBackground(.hidden) + .padding(8) + .disabled(selectedSnippet == nil) + } + .padding(10) + .background(panelBackground, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) + } + + private var panelBackground: Color { + Color.black.opacity(0.1) + } + + private func addFolder() { + let nextIndex = (folders.map(\.sortIndex).max() ?? -1) + 1 + let folder = SnippetFolder(title: "New Folder", sortIndex: nextIndex) + modelContext.insert(folder) + persist() + selectedFolderID = folder.persistentModelID + selectedSnippetID = nil + beginFolderRename(folder) + } + + private func removeSelectedFolder() { + guard let selectedFolder else { return } + modelContext.delete(selectedFolder) + persist() + selectedFolderID = nil + selectedSnippetID = nil + ensureSelection() + } + + private func addSnippet(to folder: SnippetFolder) { + let nextIndex = (folder.snippets.map(\.sortIndex).max() ?? -1) + 1 + let snippet = Snippet(title: "New Snippet", content: "", sortIndex: nextIndex) + snippet.folder = folder + folder.snippets.append(snippet) + modelContext.insert(snippet) + persist() + selectedSnippetID = snippet.persistentModelID + beginSnippetRename(snippet) + } + + private func removeSelectedSnippet() { + guard let selectedSnippet else { return } + modelContext.delete(selectedSnippet) + persist() + selectedSnippetID = selectedSnippets.first?.persistentModelID + } + + private func ensureSelection() { + if selectedFolder == nil { + selectedFolderID = folders.first?.persistentModelID + } + + guard let selectedFolder else { + selectedSnippetID = nil + return + } + + if !selectedFolder.snippets.contains(where: { $0.persistentModelID == selectedSnippetID }) { + selectedSnippetID = selectedFolder.snippets.sorted { $0.sortIndex < $1.sortIndex }.first?.persistentModelID + } + } + + private func persist() { + try? modelContext.save() + } + + private func beginFolderRename(_ folder: SnippetFolder) { + selectedFolderID = folder.persistentModelID + editingFolderID = folder.persistentModelID + editingFolderTitle = folder.title + isFolderNameFocused = true + } + + private func commitFolderRename(_ folder: SnippetFolder) { + let trimmed = editingFolderTitle.trimmingCharacters(in: .whitespacesAndNewlines) + folder.title = trimmed.isEmpty ? folder.title : trimmed + editingFolderID = nil + persist() + } + + private func beginSnippetRename(_ snippet: Snippet) { + selectedSnippetID = snippet.persistentModelID + editingSnippetID = snippet.persistentModelID + editingSnippetTitle = snippet.title + isSnippetNameFocused = true + } + + private func commitSnippetRename(_ snippet: Snippet) { + let trimmed = editingSnippetTitle.trimmingCharacters(in: .whitespacesAndNewlines) + snippet.title = trimmed.isEmpty ? snippet.title : trimmed + editingSnippetID = nil + persist() + } +} + +// MARK: - Preview + +#Preview { + let folder = SnippetFolder(title: "Templates", sortIndex: 0) + let snippet = Snippet(title: "Greeting", content: "Hello from ClipMenu!", sortIndex: 0) + snippet.folder = folder + folder.snippets = [snippet] + + return SnippetsPrefsView() + .modelContainer(for: [SnippetFolder.self, Snippet.self], inMemory: true) +} diff --git a/Sources/UI/PreferencesView.swift b/Sources/UI/PreferencesView.swift new file mode 100644 index 0000000..44dccf9 --- /dev/null +++ b/Sources/UI/PreferencesView.swift @@ -0,0 +1,104 @@ +import SwiftUI + +enum PreferencesTab: Hashable, CaseIterable, Identifiable { + case general + case menu + case snippets + case actions + case shortcuts + + var id: Self { self } + + var title: String { + switch self { + case .general: return "General" + case .menu: return "Menu" + case .snippets: return "Snippets" + case .actions: return "Actions" + case .shortcuts: return "Shortcuts" + } + } + + var symbolName: String { + switch self { + case .general: return "gearshape" + case .menu: return "list.bullet" + case .snippets: return "text.badge.plus" + case .actions: return "bolt" + case .shortcuts: return "keyboard" + } + } +} + +/// Root of the Settings scene — tabbed preferences window. +/// +/// Mirrors the tab structure from `legacy/Source/PrefsWindowController.{h,m}` +/// (General, Menu, Actions, Shortcuts tabs). +struct PreferencesView: View { + @State private var selection: PreferencesTab + + init(initialTab: PreferencesTab = .general) { + _selection = State(initialValue: initialTab) + } + + var body: some View { + VStack(spacing: 12) { + HStack(spacing: 6) { + ForEach(PreferencesTab.allCases) { tab in + Button { + selection = tab + } label: { + HStack { + Spacer(minLength: 0) + Label(tab.title, systemImage: tab.symbolName) + .font(.system(size: 13, weight: .medium)) + Spacer(minLength: 0) + } + .frame(maxWidth: .infinity, minHeight: 32) + .contentShape(Rectangle()) + } + .frame(maxWidth: .infinity) + .buttonStyle(.plain) + .focusable(false) + .foregroundStyle(selection == tab ? .white : .primary) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(selection == tab ? Color.accentColor : Color.clear) + ) + } + } + .frame(maxWidth: .infinity) + .padding(6) + .background( + RoundedRectangle(cornerRadius: 10) + .fill(Color(nsColor: .controlBackgroundColor)) + ) + + Group { + switch selection { + case .general: + GeneralPrefsView() + case .menu: + MenuPrefsView() + case .snippets: + SnippetsPrefsView() + case .actions: + ActionsPrefsView() + case .shortcuts: + ShortcutsPrefsView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + } + .frame(minWidth: 680, minHeight: 500) + .padding(12) + } +} + +// MARK: - Preview + +#Preview { + PreferencesView() + .environment(ClipMenuSettings()) + .environment(\.loginItemService, LoginItemService()) +} diff --git a/Sources/UI/SnippetSection.swift b/Sources/UI/SnippetSection.swift new file mode 100644 index 0000000..559f3e2 --- /dev/null +++ b/Sources/UI/SnippetSection.swift @@ -0,0 +1,58 @@ +import SwiftUI +import AppKit + +/// Renders enabled snippet folders and their snippets as menu submenus. +/// +/// Mirrors `legacy/Source/MenuController.m` snippet menu construction. +struct SnippetSection: View { + + /// Pre-filtered to enabled folders only (ClipMenuView does the filtering). + let folders: [SnippetFolder] + + @Environment(\.clipsService) private var clipsService + + var body: some View { + ForEach(folders) { folder in + let enabled = folder.snippets + .filter(\.isEnabled) + .sorted { $0.sortIndex < $1.sortIndex } + if !enabled.isEmpty { + Menu { + ForEach(enabled) { snippet in + snippetButton(snippet) + } + } label: { + Label(folder.title, systemImage: "folder") + } + } + } + } + + private func snippetButton(_ snippet: Snippet) -> some View { + Button(snippet.title) { + Task { + await clipsService.copyStringToPasteboard(snippet.content) + } + } + } +} + +// MARK: - Preview + +#Preview { + let folder1 = SnippetFolder(title: "Greetings", sortIndex: 0) + let s1 = Snippet(title: "Hello", content: "Hello, world!", sortIndex: 0) + let s2 = Snippet(title: "Goodbye", content: "Goodbye!", sortIndex: 1) + s1.folder = folder1 + s2.folder = folder1 + folder1.snippets = [s1, s2] + + let folder2 = SnippetFolder(title: "Lone snippet", sortIndex: 1) + let s3 = Snippet(title: "Quick note", content: "FYI", sortIndex: 0) + s3.folder = folder2 + folder2.snippets = [s3] + + return SnippetSection(folders: [folder1, folder2]) + .environment(\.clipsService, ClipsService(settings: ClipMenuSettings())) + .padding() +} diff --git a/dist/ClipMenu.app/Contents/CodeResources b/dist/ClipMenu.app/Contents/CodeResources new file mode 100644 index 0000000..f988b0f Binary files /dev/null and b/dist/ClipMenu.app/Contents/CodeResources differ diff --git a/dist/ClipMenu.app/Contents/Info.plist b/dist/ClipMenu.app/Contents/Info.plist new file mode 100644 index 0000000..8683bff --- /dev/null +++ b/dist/ClipMenu.app/Contents/Info.plist @@ -0,0 +1,58 @@ + + + + + BuildMachineOSBuild + 25D2128 + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ClipMenu + CFBundleExecutable + ClipMenu + CFBundleIconFile + AppIcon + CFBundleIconName + AppIcon + CFBundleIdentifier + app.eetr.ClipMenu + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ClipMenu + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 25E236 + DTPlatformName + macosx + DTPlatformVersion + 26.4 + DTSDKBuild + 25E236 + DTSDKName + macosx26.4 + DTXcode + 2640 + DTXcodeBuild + 17E192 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + 14.0 + LSUIElement + + NSPrincipalClass + NSApplication + + diff --git a/dist/ClipMenu.app/Contents/MacOS/ClipMenu b/dist/ClipMenu.app/Contents/MacOS/ClipMenu new file mode 100755 index 0000000..a8fc5c0 Binary files /dev/null and b/dist/ClipMenu.app/Contents/MacOS/ClipMenu differ diff --git a/dist/ClipMenu.app/Contents/PkgInfo b/dist/ClipMenu.app/Contents/PkgInfo new file mode 100644 index 0000000..bd04210 --- /dev/null +++ b/dist/ClipMenu.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/dist/ClipMenu.app/Contents/Resources/AppIcon.icns b/dist/ClipMenu.app/Contents/Resources/AppIcon.icns new file mode 100644 index 0000000..e296447 Binary files /dev/null and b/dist/ClipMenu.app/Contents/Resources/AppIcon.icns differ diff --git a/dist/ClipMenu.app/Contents/Resources/Assets.car b/dist/ClipMenu.app/Contents/Resources/Assets.car new file mode 100644 index 0000000..2d9ed74 Binary files /dev/null and b/dist/ClipMenu.app/Contents/Resources/Assets.car differ diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Info.plist b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Info.plist new file mode 100644 index 0000000..15ab94c --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Info.plist @@ -0,0 +1,40 @@ + + + + + BuildMachineOSBuild + 25D2128 + CFBundleDevelopmentRegion + en + CFBundleIdentifier + keyboardshortcuts.KeyboardShortcuts.resources + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + KeyboardShortcuts_KeyboardShortcuts + CFBundlePackageType + BNDL + CFBundleSupportedPlatforms + + MacOSX + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 25E236 + DTPlatformName + macosx + DTPlatformVersion + 26.4 + DTSDKBuild + 25E236 + DTSDKName + macosx26.4 + DTXcode + 2640 + DTXcodeBuild + 17E192 + LSMinimumSystemVersion + 10.15 + + diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ar.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ar.lproj/Localizable.strings new file mode 100644 index 0000000..bb18602 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ar.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "سجل اختصاراً"; +"press_shortcut" = "اضغط على الاختصار"; +"keyboard_shortcut_used_by_menu_item" = "لا يمكن استخدام اختصار لوحة المفاتيح هذا لأنه مستخدم بواسطة عنصر القائمة “%@”."; +"keyboard_shortcut_used_by_system" = "لا يمكن استخدام اختصار لوحة المفاتيح هذا لأنه مستخدم مسبقاً على مستوى النظام."; +"keyboard_shortcuts_can_be_changed" = "يمكن تغيير معظم اختصارات لوحة المفاتيح على مستوى النظام في "إعدادات النظام › لوحة المفاتيح › اختصارات لوحة المفاتيح"."; +"keyboard_shortcut_disallowed" = "يجب دمج مفتاح Option مع Command أو Control."; +"force_use_shortcut" = "استخدم على أي حال"; +"ok" = "موافق"; +"space_key" = "مسافة"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/cs.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/cs.lproj/Localizable.strings new file mode 100644 index 0000000..d1daf32 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/cs.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Přidat zkratku"; +"press_shortcut" = "Zadejte klávesy"; +"keyboard_shortcut_used_by_menu_item" = "Tuto zkratku nelze použít, protože je již využívána položkou „%@“"; +"keyboard_shortcut_used_by_system" = "Tuto zkratku nelze použít, protože už ji používá systém."; +"keyboard_shortcuts_can_be_changed" = "Většinu systémových zkratek můžete změnit v „Nastavení systému › Klávesnice › Klávesové zkratky“."; +"keyboard_shortcut_disallowed" = "Modifikátor Option musí být kombinován s klávesou Command nebo Control."; +"force_use_shortcut" = "Přesto použít"; +"ok" = "OK"; +"space_key" = "Mezera"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/de.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/de.lproj/Localizable.strings new file mode 100644 index 0000000..c3eae6d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/de.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Kurzbefehl aufnehmen"; +"press_shortcut" = "Kurzbefehl wählen…"; +"keyboard_shortcut_used_by_menu_item" = "Dieses Tastaturkürzel kann nicht verwendet werden, da es bereits durch den Menüpunkt „%@” belegt ist."; +"keyboard_shortcut_used_by_system" = "Dieses Tastaturkürzel kann nicht verwendet werden, da es bereits systemweit verwendet wird."; +"keyboard_shortcuts_can_be_changed" = "Die meisten systemweiten Tastaturkürzel können unter „Systemeinstellungen › Tastatur › Tastaturkurzbefehle“ geändert werden."; +"keyboard_shortcut_disallowed" = "Die Option-Taste muss mit der Befehlstaste oder der Steuerungstaste kombiniert werden."; +"force_use_shortcut" = "Trotzdem verwenden"; +"ok" = "OK"; +"space_key" = "Leer"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/en.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..2a37582 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/en.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Record Shortcut"; +"press_shortcut" = "Press Shortcut"; +"keyboard_shortcut_used_by_menu_item" = "This keyboard shortcut cannot be used as it’s already used by the “%@” menu item."; +"keyboard_shortcut_used_by_system" = "This keyboard shortcut cannot be used as it’s already a system-wide keyboard shortcut."; +"keyboard_shortcuts_can_be_changed" = "Most system-wide keyboard shortcuts can be changed in “System Settings › Keyboard › Keyboard Shortcuts”."; +"keyboard_shortcut_disallowed" = "Option modifier must be combined with Command or Control."; +"force_use_shortcut" = "Use Anyway"; +"ok" = "OK"; +"space_key" = "Space"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/es.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/es.lproj/Localizable.strings new file mode 100644 index 0000000..0492858 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/es.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Grabar atajo"; +"press_shortcut" = "Pulsar atajo"; +"keyboard_shortcut_used_by_menu_item" = "Este atajo de teclado no se puede utilizar ya que está siendo utilizado por el elemento de menú “%@”."; +"keyboard_shortcut_used_by_system" = "Este atajo de teclado no se puede utilizar ya que está siendo utilizado por un atajo del sistema operativo."; +"keyboard_shortcuts_can_be_changed" = "La mayoría de los atajos de teclado del sistema operativo pueden ser modificados en “Configuración del sistema › Teclado › Atajos de teclado“."; +"keyboard_shortcut_disallowed" = "El modificador Option debe combinarse con Command o Control."; +"force_use_shortcut" = "Usar de todos modos"; +"ok" = "Aceptar"; +"space_key" = "Espacio"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/fr.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/fr.lproj/Localizable.strings new file mode 100644 index 0000000..2029e0a --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/fr.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Enregistrer le raccourci"; +"press_shortcut" = "Saisir un raccourci"; +"keyboard_shortcut_used_by_menu_item" = "Ce raccourci ne peut pas être utilisé, car il est déjà utilisé par le menu “%@”."; +"keyboard_shortcut_used_by_system" = "Ce raccourci ne peut pas être utilisé car il s'agit d'un raccourci déjà présent dans le système."; +"keyboard_shortcuts_can_be_changed" = "La plupart des raccourcis clavier de l'ensemble du système peuvent être modifiés en “Réglages du système… › Clavier › Raccourcis clavier…”."; +"keyboard_shortcut_disallowed" = "Le modificateur Option doit être combiné avec Command ou Control."; +"force_use_shortcut" = "Utiliser quand même"; +"ok" = "OK"; +"space_key" = "Espace"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/hu.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/hu.lproj/Localizable.strings new file mode 100644 index 0000000..e18a4b7 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/hu.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Billentyűparancs rögzítése"; +"press_shortcut" = "Nyomja meg a billentyűparancsot"; +"keyboard_shortcut_used_by_menu_item" = "Ez a billentyűparancs nem használható mert már a “%@” menü elem használja."; +"keyboard_shortcut_used_by_system" = "Ez a billentyűparancs nem használható mert már egy rendszerszintü billentyűparancs."; +"keyboard_shortcuts_can_be_changed" = "A legtöbb rendszerszintü billentyűparancsot a “Rendszerbeállítások › Billentyűzet › Billentyűparancsok” menüben meg lehet változtatni"; +"keyboard_shortcut_disallowed" = "Az Option módosítót a Command vagy Control billentyűvel együtt kell használni."; +"force_use_shortcut" = "Használat mindenképp"; +"ok" = "OK"; +"space_key" = "Szóköz"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/it.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/it.lproj/Localizable.strings new file mode 100644 index 0000000..d85e120 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/it.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Registra scorciatoia"; +"press_shortcut" = "Premi scorciatoia"; +"keyboard_shortcut_used_by_menu_item" = "Questa scorciatoia da tastiera non può essere utilizzata perché è già assegnata alla voce di menu “%@”."; +"keyboard_shortcut_used_by_system" = "Questa scorciatoia da tastiera non può essere utilizzata perché è già una scorciatoia di sistema."; +"keyboard_shortcuts_can_be_changed" = "La maggior parte delle scorciatoie di sistema può essere modificata in “Impostazioni di Sistema › Tastiera › Scorciatoie da tastiera”."; +"keyboard_shortcut_disallowed" = "Il modificatore Opzione deve essere combinato con Comando o Controllo."; +"force_use_shortcut" = "Usa comunque"; +"ok" = "OK"; +"space_key" = "Spazio"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ja.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ja.lproj/Localizable.strings new file mode 100644 index 0000000..def5a42 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ja.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "キーを記録"; +"press_shortcut" = "キーを押してください"; +"keyboard_shortcut_used_by_menu_item" = "このショートカットは既に“%@”で使われており使えません。"; +"keyboard_shortcut_used_by_system" = "このショートカットキーは既にシステムで使われており使えません。"; +"keyboard_shortcuts_can_be_changed" = "システムで設定されているショートカットキーは“システム設定 › キーボード › キーボードショートカット”で変更できます。"; +"keyboard_shortcut_disallowed" = "Optionキーは、CommandキーまたはControlキーと組み合わせる必要があります。"; +"force_use_shortcut" = "強制使用"; +"ok" = "OK"; +"space_key" = "スペース"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ko.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ko.lproj/Localizable.strings new file mode 100644 index 0000000..066b138 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ko.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "단축키 등록"; +"press_shortcut" = "단축키 입력"; +"keyboard_shortcut_used_by_menu_item" = "이 키보드 단축키는 이미 “%@” 메뉴 항목에 사용되고 있으므로 등록할 수 없습니다."; +"keyboard_shortcut_used_by_system" = "이 키보드 단축키는 이미 시스템상에서 사용되고 있으므로 등록할 수 없습니다."; +"keyboard_shortcuts_can_be_changed" = "대부분의 시스템 키보드 단축키는 “시스템 설정 › 키보드 › 키보드 단축키”에서 변경 가능합니다."; +"keyboard_shortcut_disallowed" = "Option 수정자는 Command 또는 Control과 함께 사용해야 합니다."; +"force_use_shortcut" = "그래도 사용"; +"ok" = "확인"; +"space_key" = "빈칸"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/nl.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/nl.lproj/Localizable.strings new file mode 100644 index 0000000..7d60994 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/nl.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Toetscombinatie opnemen"; +"press_shortcut" = "Voer toetscombinatie in"; +"keyboard_shortcut_used_by_menu_item" = "Deze toetscombinatie kan niet worden gebruikt omdat hij al wordt gebruikt door het menu item “%@”."; +"keyboard_shortcut_used_by_system" = "Deze toetscombinatie kan niet worden gebruikt omdat hij al door het systeem gebruikt wordt."; +"keyboard_shortcuts_can_be_changed" = "De meeste systeem toetscombinaties kunnen onder “Systeeminstellingen… > Toetsenbord > Toetscombinaties…” veranderd worden."; +"keyboard_shortcut_disallowed" = "De Option-toets moet worden gecombineerd met Command of Control."; +"force_use_shortcut" = "Toch gebruiken"; +"ok" = "OK"; +"space_key" = "spatie"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/pt-BR.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/pt-BR.lproj/Localizable.strings new file mode 100644 index 0000000..4825a62 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/pt-BR.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Gravar Atalho"; +"press_shortcut" = "Digite o Atalho"; +"keyboard_shortcut_used_by_menu_item" = "Este atalho não pode ser usado porque ele já é usado pelo item de menu “%@”."; +"keyboard_shortcut_used_by_system" = "Este atalho não pode ser usado porque ele já é usado por um atalho do sistema."; +"keyboard_shortcuts_can_be_changed" = "A maioria dos atalhos do sistema podem ser alterados em “Ajustes do Sistema › Teclado › Atalhos de Teclado”."; +"keyboard_shortcut_disallowed" = "O modificador Option deve ser combinado com Command ou Control."; +"force_use_shortcut" = "Usar mesmo assim"; +"ok" = "OK"; +"space_key" = "Espaço"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ru.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ru.lproj/Localizable.strings new file mode 100644 index 0000000..bf5ab2d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ru.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Добавить"; +"press_shortcut" = "Запись…"; +"keyboard_shortcut_used_by_menu_item" = "Это сочетание клавиш нельзя использовать, так как оно уже используется в пункте меню «%@»."; +"keyboard_shortcut_used_by_system" = "Это сочетание клавиш нельзя использовать, поскольку оно является системным."; +"keyboard_shortcuts_can_be_changed" = "Большинство системных сочетаний клавиш можно изменить в «Настройки системы › Клавиатура › Сочетания клавиш»."; +"keyboard_shortcut_disallowed" = "Клавиша Option должна использоваться в сочетании с Command или Control."; +"force_use_shortcut" = "Все равно использовать"; +"ok" = "OK"; +"space_key" = "Пробел"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/sk.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/sk.lproj/Localizable.strings new file mode 100644 index 0000000..145f9de --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/sk.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "Nahraj skratku"; +"press_shortcut" = "Stlač skratku"; +"keyboard_shortcut_used_by_menu_item" = "Túto klávesovú skratku nemožno použiť, pretože ju už používa položka menu “%@”."; +"keyboard_shortcut_used_by_system" = "Túto klávesovú skratku nemožno použiť, pretože je už použivaná pre celý systém."; +"keyboard_shortcuts_can_be_changed" = "Väčšinu systémových klávesových skratiek môžeš zmeniť v “Systémové nastavenia › Klávesnica › Klávesové skratky”."; +"keyboard_shortcut_disallowed" = "Modifikátor Option musí byť kombinovaný s klávesmi Command alebo Control."; +"force_use_shortcut" = "Použiť napriek tomu"; +"ok" = "OK"; +"space_key" = "Medzerník"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-Hans.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..90ebe6a --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "设置快捷键"; +"press_shortcut" = "按下快捷键"; +"keyboard_shortcut_used_by_menu_item" = "当前快捷键无法使用,因为它已被用作菜单项“%@”的快捷键。"; +"keyboard_shortcut_used_by_system" = "当前快捷键无法使用,因为它已被用作系统快捷键。"; +"keyboard_shortcuts_can_be_changed" = "可以在“系统设置 › 键盘 › 键盘快捷键”中更改大多数系统快捷键。"; +"keyboard_shortcut_disallowed" = "Option键必须与Command键或Control键组合使用。"; +"force_use_shortcut" = "强制使用"; +"ok" = "好"; +"space_key" = "空格"; diff --git a/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-TW.lproj/Localizable.strings b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-TW.lproj/Localizable.strings new file mode 100644 index 0000000..8caa7f4 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-TW.lproj/Localizable.strings @@ -0,0 +1,9 @@ +"record_shortcut" = "設定快速鍵"; +"press_shortcut" = "按下快速鍵"; +"keyboard_shortcut_used_by_menu_item" = "此快速鍵無法使用,因為它已被選單項目「%@」使用。"; +"keyboard_shortcut_used_by_system" = "此快速鍵無法使用,因為它已被系統使用。"; +"keyboard_shortcuts_can_be_changed" = "可以在「系統設定 › 鍵盤 › 鍵盤快速鍵」中更改大多數的系統快速鍵。"; +"keyboard_shortcut_disallowed" = "Option鍵必須與Command鍵或Control鍵組合使用。"; +"force_use_shortcut" = "強制使用"; +"ok" = "好"; +"space_key" = "空格"; diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Capitalize.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Capitalize.js new file mode 100644 index 0000000..cb9bffe --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Capitalize.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('inflection'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].capitalize(); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Title Case.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Title Case.js new file mode 100644 index 0000000..edabf5f --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/Title Case.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('inflection'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].titleize(); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/UPPERCASE.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/UPPERCASE.js new file mode 100644 index 0000000..9d92eb7 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/UPPERCASE.js @@ -0,0 +1,8 @@ +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].toUpperCase(); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/lowercase.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/lowercase.js new file mode 100644 index 0000000..5077218 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Case/lowercase.js @@ -0,0 +1,8 @@ +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].toLowerCase(); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Collapse Spaces.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Collapse Spaces.js new file mode 100644 index 0000000..b2a273a --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Collapse Spaces.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.collapseSpaces(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate MD5 hash.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate MD5 hash.js new file mode 100644 index 0000000..42ab168 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate MD5 hash.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('v8cgi/util'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return Util.md5(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate SHA-1 hash.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate SHA-1 hash.js new file mode 100644 index 0000000..9abb658 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Calculate SHA-1 hash.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('v8cgi/util'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return Util.sha1(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Decode from Base64.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Decode from Base64.js new file mode 100644 index 0000000..9ad638d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Decode from Base64.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('v8cgi/util'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return Util.base64decode(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Encode to Base64.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Encode to Base64.js new file mode 100644 index 0000000..55bd3e1 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Crypt/Encode to Base64.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('v8cgi/util'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return Util.base64encode(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Character to Decimal.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Character to Decimal.js new file mode 100644 index 0000000..d168f99 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Character to Decimal.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/char'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.char2dec(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Decimal to Character.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Decimal to Character.js new file mode 100644 index 0000000..40c4108 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Decimal to Character.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/char'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.dec2char(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Markdown to HTML.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Markdown to HTML.js new file mode 100644 index 0000000..510e806 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Convert Markdown to HTML.js @@ -0,0 +1,9 @@ +var isExist = ClipMenu.require('showdown'); +if (!isExist) { + throw new Error('Could not find the file'); +} + +var converter = new Showdown.converter(); + +return converter.makeHtml(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Decode URI component.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Decode URI component.js new file mode 100644 index 0000000..963fecb --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Decode URI component.js @@ -0,0 +1,2 @@ +return decodeURIComponent(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Encode URI component.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Encode URI component.js new file mode 100644 index 0000000..4e76ba4 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Encode URI component.js @@ -0,0 +1,2 @@ +return encodeURIComponent(clipText); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Escape HTML characters.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Escape HTML characters.js new file mode 100644 index 0000000..740bf6d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Escape HTML characters.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('v8cgi/html'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = HTML.escape(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Strip Tags.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Strip Tags.js new file mode 100644 index 0000000..0a4b095 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Strip Tags.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.stripTags(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Surround with Tags....js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Surround with Tags....js new file mode 100644 index 0000000..e30851d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Surround with Tags....js @@ -0,0 +1,17 @@ +/* The selected text is marked with start and end tags. */ + +ClipMenu.activate(); + +var input = prompt('Enter HTML/XML tag name:'); +if (!input) { + throw new Error('Invalid input'); +} + +var words = input.split(' '); +var tag = words[0]; +if (tag.length == 0) { + throw new Error('Enter valid tag name'); +} + +return '<' + input + '>' + clipText + ''; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Unescape HTML characters.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Unescape HTML characters.js new file mode 100644 index 0000000..06e9a66 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/HTML/Unescape HTML characters.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('v8cgi/html'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = HTML.unescape(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js new file mode 100644 index 0000000..9cd20c8 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.htof(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js new file mode 100644 index 0000000..26be6ec --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.hkktofkk(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js new file mode 100644 index 0000000..35bee11 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.hgtokk(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js new file mode 100644 index 0000000..1bdf691 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.kktohg(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js new file mode 100644 index 0000000..ac1fb8d --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.ftoh(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js new file mode 100644 index 0000000..ed96705 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js @@ -0,0 +1,13 @@ +var isExist = ClipMenu.require('fhconvert'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +var lines = clipText.split('\n'); + +for (var i = 0; i < lines.length; i++) { + lines[i] = FHConvert.fkktohkk(lines[i]); +} + +return lines.join('\n'); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Reverse.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Reverse.js new file mode 100644 index 0000000..0664cb8 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Reverse.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.reverse(); + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" new file mode 100644 index 0000000..0a43023 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\230 \342\200\231.js" @@ -0,0 +1,2 @@ +return '‘' + clipText + '’'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" new file mode 100644 index 0000000..59d8a11 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\342\200\234 \342\200\235.js" @@ -0,0 +1,2 @@ +return '“' + clipText + '”'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" new file mode 100644 index 0000000..3facd49 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\210 \343\200\211.js" @@ -0,0 +1,2 @@ +return '〈' + clipText + '〉'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" new file mode 100644 index 0000000..fa6e894 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\212 \343\200\213.js" @@ -0,0 +1,2 @@ +return '《' + clipText + '》'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" new file mode 100644 index 0000000..894e3fd --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\214 \343\200\215.js" @@ -0,0 +1,2 @@ +return '「' + clipText + '」'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" new file mode 100644 index 0000000..38511f0 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\216 \343\200\217.js" @@ -0,0 +1,2 @@ +return '『' + clipText + '』'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" new file mode 100644 index 0000000..bf663cf --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\220 \343\200\221.js" @@ -0,0 +1,2 @@ +return '【' + clipText + '】'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" new file mode 100644 index 0000000..df6a14c --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\343\200\224 \343\200\225.js" @@ -0,0 +1,2 @@ +return '〔' + clipText + '〕'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" new file mode 100644 index 0000000..b09a3ea --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\210 \357\274\211.js" @@ -0,0 +1,2 @@ +return '(' + clipText + ')'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" new file mode 100644 index 0000000..96e3599 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\234 \357\274\236.js" @@ -0,0 +1,2 @@ +return '<' + clipText + '>'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" new file mode 100644 index 0000000..d78dcb0 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\274\273 \357\274\275.js" @@ -0,0 +1,2 @@ +return '[' + clipText + ']'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" new file mode 100644 index 0000000..905e3e0 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with (Japanese)/\357\275\233 \357\275\235.js" @@ -0,0 +1,2 @@ +return '{' + clipText + '}'; + diff --git "a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/\" \".js" "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/\" \".js" new file mode 100644 index 0000000..35085b4 --- /dev/null +++ "b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/\" \".js" @@ -0,0 +1,2 @@ +return '"' + clipText + '"'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/' '.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/' '.js new file mode 100644 index 0000000..cc1682e --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/' '.js @@ -0,0 +1,2 @@ +return "'" + clipText + "'"; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/( ).js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/( ).js new file mode 100644 index 0000000..4e56c4a --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/( ).js @@ -0,0 +1,2 @@ +return '(' + clipText + ')'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/< >.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/< >.js new file mode 100644 index 0000000..fbdd652 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/< >.js @@ -0,0 +1,2 @@ +return '<' + clipText + '>'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/[ ].js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/[ ].js new file mode 100644 index 0000000..2c76733 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/[ ].js @@ -0,0 +1,2 @@ +return '[' + clipText + ']'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/` `.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/` `.js new file mode 100644 index 0000000..5ce8154 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/` `.js @@ -0,0 +1,2 @@ +return '`' + clipText + '`'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/{ }.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/{ }.js new file mode 100644 index 0000000..1d5c4d4 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Surround with/{ }.js @@ -0,0 +1,2 @@ +return '{' + clipText + '}'; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/LTrim.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/LTrim.js new file mode 100644 index 0000000..08420a4 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/LTrim.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.ltrim(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/RTrim.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/RTrim.js new file mode 100644 index 0000000..f6d6e62 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/RTrim.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.rtrim(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/Trim.js b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/Trim.js new file mode 100644 index 0000000..17b53de --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/action/Trim/Trim.js @@ -0,0 +1,7 @@ +var isExist = ClipMenu.require('JS-methods/string'); +if (!isExist) { + throw new Error('Could not find the library'); +} + +return clipText.trim(); + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/char.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/char.js new file mode 100644 index 0000000..95abbf6 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/char.js @@ -0,0 +1 @@ +(function(){var unicode={'dec2hex':function(ts){return(ts+0).toString(16).toUpperCase()},'dec2hex2':function(ts){var hexequiv=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");return hexequiv[(ts>>4)&0xF]+hexequiv[ts&0xF]},'dec2hex4':function(ts){var hexequiv=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");return hexequiv[(ts>>12)&0xF]+hexequiv[(ts>>8)&0xF]+hexequiv[(ts>>4)&0xF]+hexequiv[ts&0xF]},'convertCP2Char':function(ts){var outputString='';ts=ts.replace(/^\s+/,'');if(ts.length==0)return"";ts=ts.replace(/\s+/g,' ');var listArray=ts.split(' ');for(var i=0;i>10))+String.fromCharCode(0xDC00|(n&0x3FF))}else outputString+='!erreur '+unicode.dec2hex(n)+'!'}return(outputString)},'convertCP2DecNCR':function(ts){var outputString="";ts=ts.replace(/^\s+/,'');if(ts.length==0)return"";ts=ts.replace(/\s+/g,' ');var listArray=ts.split(' ');for(var i=0;i0xFFFF)outputString+='!erreur '+unicode.dec2hex(b)+'!';if(haut!=0){if(0xDC00<=b&&b<=0xDFFF){outputString+=unicode.dec2hex(0x10000+((haut-0xD800)<<10)+(b-0xDC00))+' ';haut=0;continue}else{outputString+='!erreur '+unicode.dec2hex(haut)+'!';haut=0}}if(0xD800<=b&&b<=0xDBFF)haut=b;else outputString+=unicode.dec2hex(b)+' '}return(outputString.replace(/ $/,''))},'convertDecNCR2CP':function(ts){var outputString='';ts=ts.replace(/\s/g,'');var listArray=ts.split(';');for(var i=0;i0)outputString+=' ';var n=parseInt(listArray[i].substring(2,listArray[i].length),10);outputString+=unicode.dec2hex(n)}return(outputString)}};if(!String.prototype.char2dec)String.prototype.char2dec=function(){return unicode.convertCP2DecNCR(unicode.convertChar2CP(this))};if(!String.prototype.dec2char)String.prototype.dec2char=function(){return unicode.convertCP2Char(unicode.convertDecNCR2CP(this))}})(); \ No newline at end of file diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/string.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/string.js new file mode 100644 index 0000000..26aa5e0 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/JS-methods/string.js @@ -0,0 +1 @@ +(function(){function append(name,method){if(!String.prototype[name])String.prototype[name]=method}append("trim",function(){return this.replace(/(^\s+|\s+$)/g,"")});append("ltrim",function(){return this.replace(/^\s*/g,"")});append("rtrim",function(){return this.replace(/\s*$/g,"")});append("collapseSpaces",function(){return this.trim().replace(/\s{2,}/g," ").replace(/{(Keyword):\s*(.*?)\s*}/gi,"{$1:$2}")});append("format",function(substrings){var subRegExp=/(?:%(\d+))/mg,currPos=0,r=[];do{var match=subRegExp.exec(this);if(match&&match[1]){if(match.index>currPos)r.push(this.substring(currPos,match.index));r.push(substrings[parseInt(match[1])]);currPos=subRegExp.lastIndex}}while(match);if(currPos0)s=this.substring(0,start);if(start+length0)s+=(separator&&count!=0)?t+separator:t;return s});append("pad",function(length,ch,direction){length=length||30;direction=direction||0;ch=ch||' ';var t=this;while(t.lengthlength?this.slice(0,length-suffix.length)+suffix:this});append("stripTags",function(){return this.replace(/<\/?[^>]+>/gi,'')})})(); \ No newline at end of file diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/fhconvert.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/fhconvert.js new file mode 100644 index 0000000..df9c254 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/fhconvert.js @@ -0,0 +1,286 @@ +/* + fhconvert.js ver1.1.4 + Fullwidth to Halfwidth, Hiragana to Katakana and vice versa, Unicode charactor converter + + copyright (c) 2008 distraid Inc. + This script is freely distributable under the terms of an MIT-style license. + + $Id: fhconvert.js 10 2009-02-16 08:15:24Z ksy $ +*/ + +var FHConvert = { + ConvPattern: { + ftoh: {range:{start:0xff01,end:0xff5e}, mod:-0xfee0}, + htof: {range:{start:0x0021,end:0x007e}, mod:+0xfee0}, + hgtokk: {range:{start:0x3041,end:0x3096}, mod:+0x0060}, + kktohg: {range:{start:0x30a1,end:0x30f6}, mod:-0x0060}, + + fkktohkk: {range:{start:0x30a1,end:0x30fc}}, + hkktofkk: {range:{start:0xff61,end:0xff9f}, vsm:0xff9e, vsmRange:{start:0xff66,end:0xff9c}, svsm:0xff9f, svsmRange:{start:0xff8a,end:0xff8e}}, + + _jftojh: {convSet:{'\u2019':'\u0027','\u201d':'\u0022','\uffe5':'\u005c'}}, + _jhtojf: {convSet:{'\u0027':'\u2019','\u0022':'\u201d','\u005c':'\uffe5'}}, + + _fstohs: {convSet:{'\u3000':'\u0020'}}, + _hstofs: {convSet:{'\u0020':'\u3000'}} + }, + + _convertSet: function( value, param ) { + if ( !value || !param ) return value; + var str, idx, len = value.length, newVal = '', strArray = new Array(len); + for ( idx=0; idx= param['range']['start'] && code <= param['range']['end'] ) + strArray[idx] = String.fromCharCode( code + param['mod'] ); + else + strArray[idx] = str; + } + return strArray.join(''); + }, + + _convertReg: function( value, param ) { + if ( !value || !param ) return value; + return value.replace( param['convReg'], param['convRepl'] ); + }, + + mergeObj: function( obj1, obj2 ) { + var obj = {}; + for ( var prop in obj1 ) + obj[prop] = obj1[prop]; + for ( prop in obj2 ) + obj[prop] = obj2[prop]; + return obj; + }, + + _initConvert: function( id, param ) { + var opt = {id:id}, convSet = null, code; + if ( !param ) param = {}; + + if ( this.ConvPattern[id] ) + { + opt['range'] = this.ConvPattern[id]['range']; + opt['mod'] = this.ConvPattern[id]['mod']; + convSet = this.ConvPattern[id]['convSet']; + } + + if ( param['jaCode'] ) + { + if ( id == 'ftoh' ) + convSet = this.mergeObj( convSet, this.ConvPattern['_jftojh']['convSet'] ); + else if ( id == 'htof' ) + convSet = this.mergeObj( convSet, this.ConvPattern['_jhtojf']['convSet'] ); + } + + if ( param['space'] ) + { + if ( id == 'ftoh' || id == 'fkktohkk' ) + convSet = this.mergeObj( convSet, this.ConvPattern['_fstohs']['convSet'] ); + else if ( id == 'htof' || id == 'hkktofkk' ) + convSet = this.mergeObj( convSet, this.ConvPattern['_hstofs']['convSet'] ); + } + + if ( typeof param['convSet'] == 'object' ) + { + convSet = this.mergeObj( convSet, param['convSet'] ); + for ( code in convSet ) + { + if ( typeof convSet[code] == 'number' ) + convSet[code] = String.fromCharCode( convSet[code] ); + } + } + opt['convSet'] = convSet; + return opt; + }, + + _toRegStr: function( code ) { + if ( code == null ) return ''; + var idx, strCode = ''; + if ( typeof code == 'string' ) + { + for ( idx = 0; idx < code.length; idx++ ) + strCode += this._toRegStr( code.charCodeAt(idx) ); + return strCode; + } + strCode = '000'+code.toString(16); + return '\\u'+strCode.substring( strCode.length-4 ); + }, + + _initConvertReg: function( id, param ) { + if ( !param ) return null; + var code, prop, val, regStr, rangeCode = '', recode = '', convObj = {}, recodeM = []; + if ( param['range'] ) + { + if ( param['mod'] ) + { + for ( code = param['range']['start']; code <= param['range']['end']; code++ ) + convObj[String.fromCharCode(code)] = String.fromCharCode( code + param['mod'] ); + } + rangeCode = this._toRegStr(param['range']['start']) + '-' + this._toRegStr(param['range']['end']); + } + + if ( param['convSet'] ) + { + for ( prop in param['convSet'] ) + { + val = param['convSet'][prop]; + regStr = this._toRegStr( prop ); + if ( prop.length > 1 ) + recodeM.push( '('+regStr+')' ); + else { + code = prop.charCodeAt(0); + if ( !param['range'] || code < param['range']['start'] || code > param['range']['end'] ) + recode += regStr; + } + convObj[prop] = val; + } + } + if ( id == 'hkktofkk' && this.ConvPattern['hkktofkk']['convSetHKK'] ) + { + for ( prop in this.ConvPattern['hkktofkk']['convSetHKK'] ) + convObj[prop] = this.ConvPattern['hkktofkk']['convSetHKK'][prop]; + recodeM.push( '(['+this._toRegStr(this.ConvPattern['hkktofkk']['vsmRange']['start'])+'-'+this._toRegStr(this.ConvPattern['hkktofkk']['vsmRange']['end'])+']'+this._toRegStr(this.ConvPattern['hkktofkk']['vsm'])+')' ); + recodeM.push( '(['+this._toRegStr(this.ConvPattern['hkktofkk']['svsmRange']['start'])+'-'+this._toRegStr(this.ConvPattern['hkktofkk']['svsmRange']['end'])+']'+this._toRegStr(this.ConvPattern['hkktofkk']['svsm'])+')' ); + } + + recode = rangeCode + recode; + if ( !recode && recodeM.length <= 0 ) return null; + + if ( recode ) + recode = '(['+recode+'])'; + if ( recodeM.length > 0 ) + { + if ( recode ) + recodeM.push( recode ); + recode = recodeM.join( '|' ); + } + + param['convSet'] = null; + param['convReg'] = new RegExp( recode, 'g' ); + code = prop = val = ragStr = rengeCode = recode = recodeM = null; + + if ( id == 'hkktofkk' ) + { + param['convRepl'] = function( m0 ) { + if ( convObj[m0] != null ) + return convObj[m0]; + return convObj[m0.charAt(0)]+convObj[m0.charAt(1)]; + }; + } else + param['convRepl'] = function( m0 ) { return convObj[m0]; }; + return param; + }, + + ftoh: function( value, param ) { + return this._convert( value, this._initConvert('ftoh',param) ); + }, + htof: function( value, param ) { + return this._convert( value, this._initConvert('htof',param) ); + }, + hgtokk: function( value, param ) { + return this._convert( value, this._initConvert('hgtokk',param) ); + }, + kktohg: function( value, param ) { + return this._convert( value, this._initConvert('kktohg',param) ); + }, + fkktohkk: function( value, param ) { + return this._convertSet( value, this._initConvert('fkktohkk',param) ); + }, + hkktofkk: function( value, param ) { + param = this._initConvert( 'hkktofkk', param ); + param = this._initConvertReg( 'hkktofkk', param ); + return this._convertReg( value, param ); + }, + + createCl: function( id, param ) { + param = this._initConvert( id, param ); + param = this._initConvertReg( id, param ); + if ( !param ) return function( value ) { return value; } + var bind = FHConvert; + var proc = function( value ) { + return this._convertReg( value, param ); + } + return function(value) { + return proc.apply( bind, [value] ); + } + } +}; + +(function(){ + var cp = FHConvert['ConvPattern']; + + var hkkMark = {0x300c:0xff62,0x300d:0xff63,0x3002:0xff61,0x3001:0xff64,0x309b:0xff9e,0x309c:0xff9f}; + var halfcode = [0xff67,0xff71,0xff68,0xff72,0xff69,0xff73,0xff6a,0xff74,0xff6b,0xff75, + 0xff76,,0xff77,,0xff78,,0xff79,,0xff7a,,0xff7b,,0xff7c,,0xff7d,,0xff7e,,0xff7f,, + 0xff80,,0xff81,,0xff6f,0xff82,,0xff83,,0xff84,,0xff85,0xff86,0xff87,0xff88,0xff89, + 0xff8a,,,0xff8b,,,0xff8c,,,0xff8d,,,0xff8e,,, + 0xff8f,0xff90,0xff91,0xff92,0xff93,0xff6c,0xff94,0xff6d,0xff95,0xff6e,0xff96, + 0xff97,0xff98,0xff99,0xff9a,0xff9b,0xff9c,0xff9c,0xff72,0xff74,0xff66,0xff9d, + ,0xff76,0xff79,,,,,0xff65,0xff70]; + var halfConv = { + 0x30ac:[0xff76,0xff9e],0x30ae:[0xff77,0xff9e],0x30b0:[0xff78,0xff9e],0x30b2:[0xff79,0xff9e],0x30b4:[0xff7a,0xff9e], + 0x30b6:[0xff7b,0xff9e],0x30b8:[0xff7c,0xff9e],0x30ba:[0xff7d,0xff9e],0x30bc:[0xff7e,0xff9e],0x30be:[0xff7f,0xff9e], + 0x30c0:[0xff80,0xff9e],0x30c2:[0xff81,0xff9e],0x30c5:[0xff82,0xff9e],0x30c7:[0xff83,0xff9e],0x30c9:[0xff84,0xff9e], + 0x30d0:[0xff8a,0xff9e],0x30d3:[0xff8b,0xff9e],0x30d6:[0xff8c,0xff9e],0x30d9:[0xff8d,0xff9e],0x30dc:[0xff8e,0xff9e], + 0x30d1:[0xff8a,0xff9f],0x30d4:[0xff8b,0xff9f],0x30d7:[0xff8c,0xff9f],0x30da:[0xff8d,0xff9f],0x30dd:[0xff8e,0xff9f], + 0x30f4:[0xff73,0xff9e],0x30f7:[0xff9c,0xff9e],0x30f8:[0xff72,0xff9e],0x30f9:[0xff74,0xff9e],0x30fa:[0xff66,0xff9e] + }; + + var idx, code, prop, fkkSet = {}; + if ( cp['fkktohkk'] ) + { + for ( idx = 0, code = cp['fkktohkk']['range']['start']; code <= cp['fkktohkk']['range']['end']; code++, idx++ ) + fkkSet[String.fromCharCode(code)] = String.fromCharCode.apply( null, (halfConv[code]!=null?halfConv[code]:[halfcode[idx]]) ); + for ( code in hkkMark ) + fkkSet[String.fromCharCode(code)] = String.fromCharCode( hkkMark[code] ); + cp['fkktohkk']['convSet'] = fkkSet; + } + + var vsm = 0xff9e; + var svsm = 0xff9f; + var fullcode = [0x3002,0x300c,0x300d,0x3001,0x30fb, + 0x30f2,0x30a1,0x30a3,0x30a5,0x30a7,0x30a9,0x30e3,0x30e5,0x30e7,0x30c3,0x30fc, + 0x30a2,0x30a4,0x30a6,0x30a8,0x30aa,0x30ab,0x30ad,0x30af,0x30b1,0x30b3,0x30b5,0x30b7,0x30b9,0x30bb,0x30bd,0x30bf,0x30c1,0x30c4,0x30c6,0x30c8, + 0x30ca,0x30cb,0x30cc,0x30cd,0x30ce,0x30cf,0x30d2,0x30d5,0x30d8,0x30db,0x30de,0x30df,0x30e0,0x30e1,0x30e2,0x30e4,0x30e6,0x30e8, + 0x30e9,0x30ea,0x30eb,0x30ec,0x30ed,0x30ef,0x30f3,0x309b,0x309c]; + + var vsmConv = { + 0xff76:{v:0x30ac},0xff77:{v:0x30ae},0xff78:{v:0x30b0},0xff79:{v:0x30b2},0xff7a:{v:0x30b4},0xff7b:{v:0x30b6},0xff7c:{v:0x30b8},0xff7d:{v:0x30ba},0xff7e:{v:0x30bc},0xff7f:{v:0x30be}, + 0xff80:{v:0x30c0},0xff81:{v:0x30c2},0xff82:{v:0x30c5},0xff83:{v:0x30c7},0xff84:{v:0x30c9}, + 0xff8a:{v:0x30d0,sv:0x30d1},0xff8b:{v:0x30d3,sv:0x30d4},0xff8c:{v:0x30d6,sv:0x30d7},0xff8d:{v:0x30d9,sv:0x30da},0xff8e:{v:0x30dc,sv:0x30dd}, + 0xff73:{v:0x30f4},0xff9c:{v:0x30f7},0xff66:{v:0x30fa} + }; + + var hkkSet = {}; + if ( cp['hkktofkk'] ) + { + for ( idx = 0, code = cp['hkktofkk']['range']['start']; code <= cp['hkktofkk']['range']['end']; code++, idx++ ) + hkkSet[String.fromCharCode(code)] = String.fromCharCode( fullcode[idx] ); + + for ( code in vsmConv ) + { + if ( vsmConv[code]['v'] ) + hkkSet[String.fromCharCode(code,vsm)] = String.fromCharCode( vsmConv[code]['v'] ); + if ( vsmConv[code]['sv'] ) + hkkSet[String.fromCharCode(code,svsm)] = String.fromCharCode( vsmConv[code]['sv'] ); + } + cp['hkktofkk']['convSetHKK'] = hkkSet; + } +})(); \ No newline at end of file diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/inflection.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/inflection.js new file mode 100644 index 0000000..8cd326b --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/inflection.js @@ -0,0 +1,511 @@ +/* +Copyright (c) 2007 Ryan Schuft (ryan.schuft@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* + This code is based in part on the work done in Ruby to support + infection as part of Ruby on Rails in the ActiveSupport's Inflector + and Inflections classes. It was initally ported to Javascript by + Ryan Schuft (ryan.schuft@gmail.com). + + The code is available at http://code.google.com/p/inflection-js/ + + The basic usage is: + 1. Include this script on your web page. + 2. Call functions on any String object in Javascript + + Currently implemented functions: + + String.pluralize(plural) == String + renders a singular English language noun into its plural form + normal results can be overridden by passing in an alternative + + String.singularize(singular) == String + renders a plural English language noun into its singular form + normal results can be overridden by passing in an alterative + + String.camelize(lowFirstLetter) == String + renders a lower case underscored word into camel case + the first letter of the result will be upper case unless you pass true + also translates "/" into "::" (underscore does the opposite) + + String.underscore() == String + renders a camel cased word into words seperated by underscores + also translates "::" back into "/" (camelize does the opposite) + + String.humanize(lowFirstLetter) == String + renders a lower case and underscored word into human readable form + defaults to making the first letter capitalized unless you pass true + + String.capitalize() == String + renders all characters to lower case and then makes the first upper + + String.dasherize() == String + renders all underbars and spaces as dashes + + String.titleize() == String + renders words into title casing (as for book titles) + + String.demodulize() == String + renders class names that are prepended by modules into just the class + + String.tableize() == String + renders camel cased singular words into their underscored plural form + + String.classify() == String + renders an underscored plural word into its camel cased singular form + + String.foreign_key(dropIdUbar) == String + renders a class name (camel cased singular noun) into a foreign key + defaults to seperating the class from the id with an underbar unless + you pass true + + String.ordinalize() == String + renders all numbers found in the string into their sequence like "22nd" +*/ + +/* + This function adds plurilization support to every String object + Signature: + String.pluralize(plural) == String + Arguments: + plural - String (optional) - overrides normal output with said String + Returns: + String - singular English language nouns are returned in plural form + Examples: + "person".pluralize() == "people" + "octopus".pluralize() == "octopi" + "Hat".pluralize() == "Hats" + "person".pluralize("guys") == "guys" +*/ +if(!String.prototype.pluralize)String.prototype.pluralize=function(plural) +{ + var str=this; + if(plural)str=plural; + else + { + var uncountable=false; + for(var x=0;!uncountable&&x + T K B +*/ + +var Showdown={}; +Showdown.converter=function(){ +var _1; +var _2; +var _3; +var _4=0; +this.makeHtml=function(_5){ +_1=new Array(); +_2=new Array(); +_3=new Array(); +_5=_5.replace(/~/g,"~T"); +_5=_5.replace(/\$/g,"~D"); +_5=_5.replace(/\r\n/g,"\n"); +_5=_5.replace(/\r/g,"\n"); +_5="\n\n"+_5+"\n\n"; +_5=_6(_5); +_5=_5.replace(/^[ \t]+$/mg,""); +_5=_7(_5); +_5=_8(_5); +_5=_9(_5); +_5=_a(_5); +_5=_5.replace(/~D/g,"$$"); +_5=_5.replace(/~T/g,"~"); +return _5; +}; +var _8=function(_b){ +var _b=_b.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(_c,m1,m2,m3,m4){ +m1=m1.toLowerCase(); +_1[m1]=_11(m2); +if(m3){ +return m3+m4; +}else{ +if(m4){ +_2[m1]=m4.replace(/"/g,"""); +} +} +return ""; +}); +return _b; +}; +var _7=function(_12){ +_12=_12.replace(/\n/g,"\n\n"); +var _13="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"; +var _14="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"; +_12=_12.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,_15); +_12=_12.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,_15); +_12=_12.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,_15); +_12=_12.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g,_15); +_12=_12.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,_15); +_12=_12.replace(/\n\n/g,"\n"); +return _12; +}; +var _15=function(_16,m1){ +var _18=m1; +_18=_18.replace(/\n\n/g,"\n"); +_18=_18.replace(/^\n/,""); +_18=_18.replace(/\n+$/g,""); +_18="\n\n~K"+(_3.push(_18)-1)+"K\n\n"; +return _18; +}; +var _9=function(_19){ +_19=_1a(_19); +var key=_1c("
"); +_19=_19.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key); +_19=_19.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key); +_19=_19.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key); +_19=_1d(_19); +_19=_1e(_19); +_19=_1f(_19); +_19=_7(_19); +_19=_20(_19); +return _19; +}; +var _21=function(_22){ +_22=_23(_22); +_22=_24(_22); +_22=_25(_22); +_22=_26(_22); +_22=_27(_22); +_22=_28(_22); +_22=_11(_22); +_22=_29(_22); +_22=_22.replace(/ +\n/g,"
\n"); +return _22; +}; +var _24=function(_2a){ +var _2b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; +_2a=_2a.replace(_2b,function(_2c){ +var tag=_2c.replace(/(.)<\/?code>(?=.)/g,"$1`"); +tag=_2e(tag,"\\`*_"); +return tag; +}); +return _2a; +}; +var _27=function(_2f){ +_2f=_2f.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,_30); +_2f=_2f.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,_30); +_2f=_2f.replace(/(\[([^\[\]]+)\])()()()()()/g,_30); +return _2f; +}; +var _30=function(_31,m1,m2,m3,m4,m5,m6,m7){ +if(m7==undefined){ +m7=""; +} +var _39=m1; +var _3a=m2; +var _3b=m3.toLowerCase(); +var url=m4; +var _3d=m7; +if(url==""){ +if(_3b==""){ +_3b=_3a.toLowerCase().replace(/ ?\n/g," "); +} +url="#"+_3b; +if(_1[_3b]!=undefined){ +url=_1[_3b]; +if(_2[_3b]!=undefined){ +_3d=_2[_3b]; +} +}else{ +if(_39.search(/\(\s*\)$/m)>-1){ +url=""; +}else{ +return _39; +} +} +} +url=_2e(url,"*_"); +var _3e=""; +return _3e; +}; +var _26=function(_3f){ +_3f=_3f.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,_40); +_3f=_3f.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,_40); +return _3f; +}; +var _40=function(_41,m1,m2,m3,m4,m5,m6,m7){ +var _49=m1; +var _4a=m2; +var _4b=m3.toLowerCase(); +var url=m4; +var _4d=m7; +if(!_4d){ +_4d=""; +} +if(url==""){ +if(_4b==""){ +_4b=_4a.toLowerCase().replace(/ ?\n/g," "); +} +url="#"+_4b; +if(_1[_4b]!=undefined){ +url=_1[_4b]; +if(_2[_4b]!=undefined){ +_4d=_2[_4b]; +} +}else{ +return _49; +} +} +_4a=_4a.replace(/"/g,"""); +url=_2e(url,"*_"); +var _4e="\""+_4a+"\"";"+_21(m1)+""); +}); +_4f=_4f.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(_52,m1){ +return _1c("

"+_21(m1)+"

"); +}); +_4f=_4f.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(_54,m1,m2){ +var _57=m1.length; +return _1c(""+_21(m2)+""); +}); +return _4f; +}; +var _58; +var _1d=function(_59){ +_59+="~0"; +var _5a=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; +if(_4){ +_59=_59.replace(_5a,function(_5b,m1,m2){ +var _5e=m1; +var _5f=(m2.search(/[*+-]/g)>-1)?"ul":"ol"; +_5e=_5e.replace(/\n{2,}/g,"\n\n\n"); +var _60=_58(_5e); +_60=_60.replace(/\s+$/,""); +_60="<"+_5f+">"+_60+"\n"; +return _60; +}); +}else{ +_5a=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; +_59=_59.replace(_5a,function(_61,m1,m2,m3){ +var _65=m1; +var _66=m2; +var _67=(m3.search(/[*+-]/g)>-1)?"ul":"ol"; +var _66=_66.replace(/\n{2,}/g,"\n\n\n"); +var _68=_58(_66); +_68=_65+"<"+_67+">\n"+_68+"\n"; +return _68; +}); +} +_59=_59.replace(/~0/,""); +return _59; +}; +_58=function(_69){ +_4++; +_69=_69.replace(/\n{2,}$/,"\n"); +_69+="~0"; +_69=_69.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(_6a,m1,m2,m3,m4){ +var _6f=m4; +var _70=m1; +var _71=m2; +if(_70||(_6f.search(/\n{2,}/)>-1)){ +_6f=_9(_72(_6f)); +}else{ +_6f=_1d(_72(_6f)); +_6f=_6f.replace(/\n$/,""); +_6f=_21(_6f); +} +return "
  • "+_6f+"
  • \n"; +}); +_69=_69.replace(/~0/g,""); +_4--; +return _69; +}; +var _1e=function(_73){ +_73+="~0"; +_73=_73.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(_74,m1,m2){ +var _77=m1; +var _78=m2; +_77=_79(_72(_77)); +_77=_6(_77); +_77=_77.replace(/^\n+/g,""); +_77=_77.replace(/\n+$/g,""); +_77="
    "+_77+"\n
    "; +return _1c(_77)+_78; +}); +_73=_73.replace(/~0/,""); +return _73; +}; +var _1c=function(_7a){ +_7a=_7a.replace(/(^\n+|\n+$)/g,""); +return "\n\n~K"+(_3.push(_7a)-1)+"K\n\n"; +}; +var _23=function(_7b){ +_7b=_7b.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(_7c,m1,m2,m3,m4){ +var c=m3; +c=c.replace(/^([ \t]*)/g,""); +c=c.replace(/[ \t]*$/g,""); +c=_79(c); +return m1+""+c+""; +}); +return _7b; +}; +var _79=function(_82){ +_82=_82.replace(/&/g,"&"); +_82=_82.replace(//g,">"); +_82=_2e(_82,"*_{}[]\\",false); +return _82; +}; +var _29=function(_83){ +_83=_83.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"$2"); +_83=_83.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"$2"); +return _83; +}; +var _1f=function(_84){ +_84=_84.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(_85,m1){ +var bq=m1; +bq=bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); +bq=bq.replace(/~0/g,""); +bq=bq.replace(/^[ \t]+$/gm,""); +bq=_9(bq); +bq=bq.replace(/(^|\n)/g,"$1 "); +bq=bq.replace(/(\s*
    [^\r]+?<\/pre>)/gm,function(_88,m1){
    +var pre=m1;
    +pre=pre.replace(/^  /mg,"~0");
    +pre=pre.replace(/~0/g,"");
    +return pre;
    +});
    +return _1c("
    \n"+bq+"\n
    "); +}); +return _84; +}; +var _20=function(_8b){ +_8b=_8b.replace(/^\n+/g,""); +_8b=_8b.replace(/\n+$/g,""); +var _8c=_8b.split(/\n{2,}/g); +var _8d=new Array(); +var end=_8c.length; +for(var i=0;i=0){ +_8d.push(str); +}else{ +if(str.search(/\S/)>=0){ +str=_21(str); +str=str.replace(/^([ \t]*)/g,"

    "); +str+="

    "; +_8d.push(str); +} +} +} +end=_8d.length; +for(var i=0;i=0){ +var _91=_3[RegExp.$1]; +_91=_91.replace(/\$/g,"$$$$"); +_8d[i]=_8d[i].replace(/~K\d+K/,_91); +} +} +return _8d.join("\n\n"); +}; +var _11=function(_92){ +_92=_92.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"); +_92=_92.replace(/<(?![a-z\/?\$!])/gi,"<"); +return _92; +}; +var _25=function(_93){ +_93=_93.replace(/\\(\\)/g,_94); +_93=_93.replace(/\\([`*_{}\[\]()>#+-.!])/g,_94); +return _93; +}; +var _28=function(_95){ +_95=_95.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"
    $1"); +_95=_95.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(_96,m1){ +return _98(_a(m1)); +}); +return _95; +}; +var _98=function(_99){ +function char2hex(ch){ +var _9b="0123456789ABCDEF"; +var dec=ch.charCodeAt(0); +return (_9b.charAt(dec>>4)+_9b.charAt(dec&15)); +} +var _9d=[function(ch){ +return "&#"+ch.charCodeAt(0)+";"; +},function(ch){ +return "&#x"+char2hex(ch)+";"; +},function(ch){ +return ch; +}]; +_99="mailto:"+_99; +_99=_99.replace(/./g,function(ch){ +if(ch=="@"){ +ch=_9d[Math.floor(Math.random()*2)](ch); +}else{ +if(ch!=":"){ +var r=Math.random(); +ch=(r>0.9?_9d[2](ch):r>0.45?_9d[1](ch):_9d[0](ch)); +} +} +return ch; +}); +_99=""+_99+""; +_99=_99.replace(/">.+:/g,"\">"); +return _99; +}; +var _a=function(_a3){ +_a3=_a3.replace(/~E(\d+)E/g,function(_a4,m1){ +var _a6=parseInt(m1); +return String.fromCharCode(_a6); +}); +return _a3; +}; +var _72=function(_a7){ +_a7=_a7.replace(/^(\t|[ ]{1,4})/gm,"~0"); +_a7=_a7.replace(/~0/g,""); +return _a7; +}; +var _6=function(_a8){ +_a8=_a8.replace(/\t(?=\t)/g," "); +_a8=_a8.replace(/\t/g,"~A~B"); +_a8=_a8.replace(/~B(.+?)~A/g,function(_a9,m1,m2){ +var _ac=m1; +var _ad=4-_ac.length%4; +for(var i=0;i<_ad;i++){ +_ac+=" "; +} +return _ac; +}); +_a8=_a8.replace(/~A/g," "); +_a8=_a8.replace(/~B/g,""); +return _a8; +}; +var _2e=function(_af,_b0,_b1){ +var _b2="(["+_b0.replace(/([\[\]\\])/g,"\\$1")+"])"; +if(_b1){ +_b2="\\\\"+_b2; +} +var _b3=new RegExp(_b2,"g"); +_af=_af.replace(_b3,_94); +return _af; +}; +var _94=function(_b4,m1){ +var _b6=m1.charCodeAt(0); +return "~E"+_b6+"E"; +}; +}; + diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/html.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/html.js new file mode 100644 index 0000000..9ed4d64 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/html.js @@ -0,0 +1,21 @@ +var HTML = { + escape: function(str) { + if (str === null || !str.toString) { return ""; } + return str.toString() + .replace(/&/g,"&") + .replace(//g,">") + .replace(/"/g,""") + .replace(/'/g,"'"); + }, + unescape: function(str) { + if (str === null || !str.toString) { return ""; } + return str.toString() + .replace(/'/g,"'") + .replace(/"/g,"\"") + .replace(/>/g,">") + .replace(/</g,"<") + .replace(/&/g,"&"); + } +} +exports.HTML = HTML; diff --git a/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/util.js b/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/util.js new file mode 100644 index 0000000..86e9001 --- /dev/null +++ b/dist/ClipMenu.app/Contents/Resources/scripts/lib/v8cgi/util.js @@ -0,0 +1,521 @@ +/* + MD5 and SHA routines, along with their supplemental sub-routines are + Copyright (C) Paul Johnston 1999 - 2002. + Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet, Ondrej Zara + Distributed under the BSD License +*/ + +var Util = { + md5:function(str) { + var input = Util.utf8decode(str); + var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ + var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + + /* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ + function core_md5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return [a, b, c, d]; + } + + /* + * These functions implement the four basic operations the algorithm uses. + */ + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); + } + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); + } + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + } + + /* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /* + * Bitwise rotate a 32-bit number to the left. + */ + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ + function str2binl(str) { + var bin = []; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + return bin; + } + + /* + * Convert an array of little-endian words to a hex string. + */ + function binl2hex(binarray) { + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + } + return str; + } + return binl2hex(core_md5(str2binl(input), input.length * chrsz)); + }, + sha1:function(str) { + var input = Util.utf8decode(str); + var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ + var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + + /* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ + function core_sha1(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for(var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for(var j = 0; j < 80; j++) { + if(j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + } + + /* + * Perform the appropriate triplet combination function for the current + * iteration + */ + function sha1_ft(t, b, c, d) { + if(t < 20) return (b & c) | ((~b) & d); + if(t < 40) return b ^ c ^ d; + if(t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; + } + + /* + * Determine the appropriate additive constant for the current iteration + */ + function sha1_kt(t) { + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; + } + + /* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /* + * Bitwise rotate a 32-bit number to the left. + */ + function rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /* + * Convert an 8-bit or 16-bit string to an array of big-endian words + * In 8-bit function, characters >255 have their hi-byte silently ignored. + */ + function str2binb(str) { + var bin = Array(); + var mask = (1 << chrsz) - 1; + for (var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); + return bin; + } + + /* + * Convert an array of big-endian words to a hex string. + */ + function binb2hex(binarray) { + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); + } + return str; + } + + return binb2hex(core_sha1(str2binb(input),input.length * chrsz)); + }, + base64encode:function(str) { + var input = Util.utf8decode(str); + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + do { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); + } while (i < input.length); + return output; + }, + base64decode:function(input) { + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { output = output + String.fromCharCode(chr2); } + if (enc4 != 64) { output = output + String.fromCharCode(chr3); } + } while (i < input.length); + + return Util.utf8encode(output); + }, + serialize:function(obj, pretty, depth, cache) { + var d = depth || 0; + var c = cache || []; + var separator = pretty ? "\n" : ""; + var indent = pretty ? " " : ""; + var prefix = ""; + if (pretty) { for (var i=0;i 191) && (c < 224)) { + c1 = str.charCodeAt(i+1); + result += String.fromCharCode(((c & 31) << 6) | (c1 & 63)); + i += 2; + } else { + c1 = str.charCodeAt(i+1); + c2 = str.charCodeAt(i+2); + result += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63)); + i += 3; + } + } + return result; + }, + utf8decode:function(str) { + var result = ""; + + for (var i=0;i 127) && (c < 2048)) { + result += String.fromCharCode((c >> 6) | 192); + result += String.fromCharCode((c & 63) | 128); + } + else { + result += String.fromCharCode((c >> 12) | 224); + result += String.fromCharCode(((c >> 6) & 63) | 128); + result += String.fromCharCode((c & 63) | 128); + } + } + return result; + }, + mail:function(to, subject, body, headers, auth) { + var from = Config["smtpFrom"]; + var rcpt = []; + var h = { + "To":[], + "Cc":[] + }; + if (to) { + rcpt.push(to); + h["To"].push(to); + } + if (subject) { h["Subject"] = subject; } + + for (var p in headers) { + var val = headers[p]; + if (p.match(/^to$/i)) { + rcpt.push(val); + h["To"].push(val); + } else if (p.match(/^cc$/i)) { + rcpt.push(val); + h["Cc"].push(val); + } else if (p.match(/^bcc$/i)) { + rcpt.push(val); + } else if (p.match(/^subject$/i)) { + h["Subject"] = val; + } else { + h[p] = val; + } + } + + function send(text, nowait) { + // System.stdout("S: "+text+"\n"); + sock.send(text+"\r\n"); + if (!nowait) { + var data = sock.receive(1024); + // System.stdout("R: "+data); + } + } + + var host = Socket.getHostName(); + var sock = new Socket(Socket.PF_INET, Socket.SOCK_STREAM, Socket.SOL_TCP); + sock.connect(Config["smtpHost"], Config["smtpPort"]); + + if (auth && auth.type.match(/^login$/i)) { + send("HELO "+host); + } else { + send("EHLO "+host); + send("AUTH LOGIN"); + send(Util.base64encode(auth.user)); + send(Util.base64encode(auth.password)); + } + + send("MAIL FROM:<"+from+">"); + for (var i=0;i"); + } + send("DATA"); + + for (var name in h) { + var value = h[name]; + if (!(value instanceof Array)) { value = [value]; } + for (var i=0;i + + + + files + + Resources/AppIcon.icns + + gyjZ6DLyqWByji9TlgoDHHVqJkY= + + Resources/Assets.car + + KeUXZDKsZKfsRPeBksBhVbz3SV4= + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Info.plist + + lxtKpUM41AMytAwgEnVkan5/ALE= + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ar.lproj/Localizable.strings + + hash + + d+WfRxCeEB1HZVE9WT1IFLFpCqE= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/cs.lproj/Localizable.strings + + hash + + /1GbOkXACrBY9JyjsKXqB7nD3W8= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/de.lproj/Localizable.strings + + hash + + hien3tY+2IGDbQLpBNUY+S6ZRmE= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/en.lproj/Localizable.strings + + hash + + KoBT7GA/9cP2BIxF+0pxC/nnBuE= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/es.lproj/Localizable.strings + + hash + + lwCpotF7YBzI4JRPV/9oykZPVQ8= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/fr.lproj/Localizable.strings + + hash + + +H7s+HmqaS1YQ6bRLCcK5KWj318= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/hu.lproj/Localizable.strings + + hash + + Ob+M+csCqRrWht6l86XHy6J5Z/I= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/it.lproj/Localizable.strings + + hash + + qTFM0EoPCvBHdYgkc1m8aBCcWcM= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ja.lproj/Localizable.strings + + hash + + VrDpLyE2xnmr7PnIedVfuQdV5eA= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ko.lproj/Localizable.strings + + hash + + 1FYFyDbAubETmK1FZBPP8zJOQtw= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/nl.lproj/Localizable.strings + + hash + + RZwSSaXbdAaWjKNib6QqXPAHNu8= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/pt-BR.lproj/Localizable.strings + + hash + + hPvN5GvQJxZnwK4S9fbnheNZAkY= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ru.lproj/Localizable.strings + + hash + + Ff042rG91TV7NkUN8NnxVtf+BUk= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/sk.lproj/Localizable.strings + + hash + + 0eLyBwgXs9VyKEz4vtTCDq7uR2o= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-Hans.lproj/Localizable.strings + + hash + + ZnVi39ykU18omRRctGOBi22JDz4= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-TW.lproj/Localizable.strings + + hash + + PJh+w/j/gOkJHi90KOkyO1RrQTI= + + optional + + + Resources/scripts/action/Case/Capitalize.js + + etNntYbElF9afRnUmhZxAoTI2Cg= + + Resources/scripts/action/Case/Title Case.js + + GjQYW6vmg+TOCKU6SJTg08SylUw= + + Resources/scripts/action/Case/UPPERCASE.js + + U1f0ah/VxkwQtNkxuIoWqkubBrs= + + Resources/scripts/action/Case/lowercase.js + + MWMM4WxgXRE/cwwPvA3v6bkn7EY= + + Resources/scripts/action/Collapse Spaces.js + + 1A177zVH/qpmitQaLfRexRzAfEU= + + Resources/scripts/action/Crypt/Calculate MD5 hash.js + + tkPszDk1MuAjqnTvk1sQfYlpaCk= + + Resources/scripts/action/Crypt/Calculate SHA-1 hash.js + + dyQumCpuf5A74NWFBmYy94psPKw= + + Resources/scripts/action/Crypt/Decode from Base64.js + + /k5UGcUqJAoRvEN/hlLmsAlgsu0= + + Resources/scripts/action/Crypt/Encode to Base64.js + + bpnW3J7wcpG+qe5X3no8+WEMnHI= + + Resources/scripts/action/HTML/Convert Character to Decimal.js + + kKOMucgu8Fow9zS07iJEqKjWRTU= + + Resources/scripts/action/HTML/Convert Decimal to Character.js + + QInxdlZVoX1DH3+2+GNVnF1FtQM= + + Resources/scripts/action/HTML/Convert Markdown to HTML.js + + uyV84JB7KLMzaMR+ZO7pp6rpBto= + + Resources/scripts/action/HTML/Decode URI component.js + + WtytMsZdiKM5OGq5B+FfJJFJPvM= + + Resources/scripts/action/HTML/Encode URI component.js + + TkyipmAd2rnT8GqQ0jyYm6oDCbo= + + Resources/scripts/action/HTML/Escape HTML characters.js + + +Jw0ff9vsisKCxWKESEJN+RGQI4= + + Resources/scripts/action/HTML/Strip Tags.js + + GdSo8Z/8XYVOL5Pt4Hr4acqdBEI= + + Resources/scripts/action/HTML/Surround with Tags....js + + eZPn/MC2TOy5NhPJvJi4zX6e5c8= + + Resources/scripts/action/HTML/Unescape HTML characters.js + + IiyN7GUW3ZlcvOcvBfRKfAPAdBw= + + Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js + + nviLOAp2NwRoJu+fnfTtNabqE4c= + + Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js + + aMIwl5oWCzqy96tL8MtUtEUE5Xs= + + Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js + + cfbsa1sqUTQRUAZN4qIRu0CDlsc= + + Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js + + CPZYWKj33MslRgLcojPGn2AJ6A8= + + Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js + + VxcB+FTWXEKjKNdWYiKoveDNSSQ= + + Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js + + zL5KzyLZhUFRvfGMpikZG5GIhi0= + + Resources/scripts/action/Reverse.js + + vy3XF/5xk5PnbzhRV99pEqy7GP8= + + Resources/scripts/action/Surround with (Japanese)/‘ ’.js + + XZl3gxFkfw9QhNuI5q8e53+kBXI= + + Resources/scripts/action/Surround with (Japanese)/“ ”.js + + HweamFt35DcADxED/WG1gZTuASc= + + Resources/scripts/action/Surround with (Japanese)/〈 〉.js + + qWjdNUVC3iIOiIDyRtUTtvshGp8= + + Resources/scripts/action/Surround with (Japanese)/《 》.js + + bvMRAhedaZ6YSuUOP/OBcCX1c+Q= + + Resources/scripts/action/Surround with (Japanese)/「 」.js + + STgZmdtgZ+6Cq5yb74ULfLideKs= + + Resources/scripts/action/Surround with (Japanese)/『 』.js + + Ib4qwapzSgOQ4uj4jvz5UpGO7ZQ= + + Resources/scripts/action/Surround with (Japanese)/【 】.js + + PnFTVvUTEf1jjqaR6N04BlEQqiU= + + Resources/scripts/action/Surround with (Japanese)/〔 〕.js + + C383HO4kEs5UJ3Y7t6DZesHneNE= + + Resources/scripts/action/Surround with (Japanese)/( ).js + + kdmAFR5xEHWATnuPBTJZ66zqcq4= + + Resources/scripts/action/Surround with (Japanese)/< >.js + + HknNnx+VmDrAk7t0HJnE1u3svaU= + + Resources/scripts/action/Surround with (Japanese)/[ ].js + + nF2ZBMlP1/ews5e6KvXB7RXD3rE= + + Resources/scripts/action/Surround with (Japanese)/{ }.js + + /dVi6Ae6abp1LAHsCsgvF3LO+xM= + + Resources/scripts/action/Surround with/" ".js + + W7I9WGlI1OgGcGXzMd9c4jKrwn8= + + Resources/scripts/action/Surround with/' '.js + + +GmSSvNU99wEgaxyicWPpK4Aoyk= + + Resources/scripts/action/Surround with/( ).js + + rF7IlHEpftsmGCjX7ruin7Is8/Y= + + Resources/scripts/action/Surround with/< >.js + + 2sVlrFm/fiCJ2a74efL5k2G2YZY= + + Resources/scripts/action/Surround with/[ ].js + + o3FiS4q6Wxp8D8dNIYzxmcrY+18= + + Resources/scripts/action/Surround with/` `.js + + IYifXEFp1Wt3Olh5PBXWK2NP2UA= + + Resources/scripts/action/Surround with/{ }.js + + mB8QXQxYSb+14/AqmMmlIIsw45k= + + Resources/scripts/action/Trim/LTrim.js + + 2Vl4SKPe57YbN/J/BfPAwYy3KWo= + + Resources/scripts/action/Trim/RTrim.js + + +JGwtHPCBabW4PFXStongXFg1Pw= + + Resources/scripts/action/Trim/Trim.js + + l+mnYnIFwuLxpjU1MTn2iYcmcNQ= + + Resources/scripts/lib/JS-methods/char.js + + eUXnZR+0d4Qs+DTs1lobRcLlm/0= + + Resources/scripts/lib/JS-methods/string.js + + ueVg+sSka3o3z2xzeWj3/62xtq8= + + Resources/scripts/lib/fhconvert.js + + hwPEBPgd8JMYCGiyzfFyo4HNOQs= + + Resources/scripts/lib/inflection.js + + oLFsYzgfHDYiw31LkR8ja68qKDA= + + Resources/scripts/lib/showdown.js + + 88ISLOStGJpv3XUPBf+SwNkUImI= + + Resources/scripts/lib/v8cgi/html.js + + 6OvL8GpHkm9npwp14ccIhJe7SSQ= + + Resources/scripts/lib/v8cgi/util.js + + xeMzofNzRswQWX6mtJCiFVZpwvg= + + + files2 + + Resources/AppIcon.icns + + hash2 + + lkCf2XohqsT/GAnvLgx4P90g1p1UcgASH3PIRCDeZN8= + + + Resources/Assets.car + + hash2 + + HW/dbPT9zpNVXE0tKIaOVirRQBU1lMI0IAWjIo1ptXs= + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Info.plist + + hash2 + + v9G21UecPnjGqO2UI+PKAmOH7pYiyQZz2rRbfjsk8hw= + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ar.lproj/Localizable.strings + + hash2 + + svKfLUvU5x02vxLEE/Ula2c/2PYy98iS4x8t9b+8eOM= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/cs.lproj/Localizable.strings + + hash2 + + 770JnZkelzoD8ROGj1uO19US3HpR01X5SvvdyTrMRTU= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/de.lproj/Localizable.strings + + hash2 + + NUf1PtgnR2lBeAMI4dk4SaAWMZ6vCvro29uhftJVcB0= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/en.lproj/Localizable.strings + + hash2 + + EhofmGwibYkTO7sE72G13deHGlAd59C1hNw6bqdZwn0= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/es.lproj/Localizable.strings + + hash2 + + uJjN1iAHPs87ppb4oyghbQNxd3N8++opbJiAmq8Dko4= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/fr.lproj/Localizable.strings + + hash2 + + ZfJaU+Ga0dEMcI6wChOJ4QqZOsbTl91YPq0jlHOhlu8= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/hu.lproj/Localizable.strings + + hash2 + + KaJv1jsb8eY7LSKebPhEYZcCiAhDV9UiwKbuI5qmnW0= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/it.lproj/Localizable.strings + + hash2 + + 2PKmPAMhOuCZfuBQkehF2eLTgYX5y950P1lFJWP1QrU= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ja.lproj/Localizable.strings + + hash2 + + FRphgWWYMtK/oXTKvnQSCfTBuN9kMcJ5DKBgwjhLGYs= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ko.lproj/Localizable.strings + + hash2 + + K+DerEC1CJEhwqOV2Ru/utwKdrGc6Ff6JWEL/samA/A= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/nl.lproj/Localizable.strings + + hash2 + + koXnMjqJRmRxFEVe7YIEiw2wrJmrlR0ZAtgZ/UEqhdY= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/pt-BR.lproj/Localizable.strings + + hash2 + + cbgZXLqlSurN/FvDYdgX3VoFWXO+Kj2VVEtqxkBsa34= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/ru.lproj/Localizable.strings + + hash2 + + vdK1RbwGm6IxnZTy+lQ+Ez7gxZz8hPKDRpmvG4V7jDo= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/sk.lproj/Localizable.strings + + hash2 + + iEin/9FNQGgdPom5BHdneLyMtqHS2Oe9CDEHjNlGfYo= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-Hans.lproj/Localizable.strings + + hash2 + + YHNiRoAwYHAxqL5TWqcxzTKgjeBB2T/+Kvt7EZNQh90= + + optional + + + Resources/KeyboardShortcuts_KeyboardShortcuts.bundle/Contents/Resources/zh-TW.lproj/Localizable.strings + + hash2 + + yjYMIkpk6bRvOMRXs9Tkp3C0xh/cOgLO8/hiKbDRdxU= + + optional + + + Resources/scripts/action/Case/Capitalize.js + + hash2 + + oEG6pKBm4mL7rI2Jp/P+68UWt6JdrYlJ/k6GgdhZeYA= + + + Resources/scripts/action/Case/Title Case.js + + hash2 + + RwC7teO3q/YNzb8F1KpcZ8T4coApcKRbMII17WKbIIs= + + + Resources/scripts/action/Case/UPPERCASE.js + + hash2 + + j2AMP18y5aOLnAMjRQHXqoYr2bGUObSImzmBvA/pP8U= + + + Resources/scripts/action/Case/lowercase.js + + hash2 + + ELyQy81ZTGAZio+p3L+Hz4aKwrGWxvpevE9Rc17w6EE= + + + Resources/scripts/action/Collapse Spaces.js + + hash2 + + E03QmjrkSQ8JlVdDZro0ABX9MnHuRRdOKZ+8Zc5xrzc= + + + Resources/scripts/action/Crypt/Calculate MD5 hash.js + + hash2 + + fXDwoFcZ1pXYtZNp8Kuv5M3EXR3k0uXifgMz414iW40= + + + Resources/scripts/action/Crypt/Calculate SHA-1 hash.js + + hash2 + + madcbh9UQkZLwoI6htOaEnMx05/jQ6Dy/X83anP2rLA= + + + Resources/scripts/action/Crypt/Decode from Base64.js + + hash2 + + +Zzp/YX6YHM8CzNijsG1aI5/vDxWkca8ISLXYrH2HNA= + + + Resources/scripts/action/Crypt/Encode to Base64.js + + hash2 + + pSZIus6HP/C0VCc5rCFSpSwS3PIkeEhNvvROCiEwiVY= + + + Resources/scripts/action/HTML/Convert Character to Decimal.js + + hash2 + + exKDbeSB8v3xFfZFxxxCS30cinTXx0r6EktBogJhSNg= + + + Resources/scripts/action/HTML/Convert Decimal to Character.js + + hash2 + + 7xMu4d/KQaV9xG+J5gqX29J9QS80rK/kziWv567BXE0= + + + Resources/scripts/action/HTML/Convert Markdown to HTML.js + + hash2 + + BM9IoCVN3JPNnsnaMAqv6SLSItO9yUVsCUay8PT7oDE= + + + Resources/scripts/action/HTML/Decode URI component.js + + hash2 + + fvDTs9+zLaK/oPX029U0vkYkG510ArmpVve0mqsE2Wg= + + + Resources/scripts/action/HTML/Encode URI component.js + + hash2 + + 6Qh5zPYTV7W87HEcQL8yUBpy4kDywvxEKruUtligZIo= + + + Resources/scripts/action/HTML/Escape HTML characters.js + + hash2 + + Gv0WAoqdRMt0lGYcgnNI8rmA5ZEPwsQxhwFI5rE5j1Y= + + + Resources/scripts/action/HTML/Strip Tags.js + + hash2 + + iIVcBpB1aMfshBTy83PFGK1oRIdgsPg/XnV0Hq/Crtw= + + + Resources/scripts/action/HTML/Surround with Tags....js + + hash2 + + zUrKOdcjH47MUyTpEyMlDZBnVSP+JIay1lgYZKs0hQ4= + + + Resources/scripts/action/HTML/Unescape HTML characters.js + + hash2 + + h3dmMAjX96zajYMIsDlMrpOQaqV6Q1hZjRafFWUaBCU= + + + Resources/scripts/action/Japanese/Convert Hankaku alphanumeric characters to Zenkaku.js + + hash2 + + 3YILPxQRbZh4LRXeITVO2/ZE2WmzDS/CzB/aQRxA59k= + + + Resources/scripts/action/Japanese/Convert Hankaku katakana to Zenkaku katakana.js + + hash2 + + Zoc9jWPEfOYVhSqWqdd2JyTYvH381FQezLrmW7SIzn4= + + + Resources/scripts/action/Japanese/Convert Hiragana to Katakana.js + + hash2 + + t2Y136myVO+T/FmRN1YGfMl4QgorjIWsVDyIfe+/NFc= + + + Resources/scripts/action/Japanese/Convert Katakana to Hiragana.js + + hash2 + + 6b1YTavFloyDWs8FoMS4vhrJh7mu8HT/ZSQwxxHx/jY= + + + Resources/scripts/action/Japanese/Convert Zenkaku alphanumeric characters to Hankaku.js + + hash2 + + 6C3yZmvv9akMR7NKyLhl66SIOzap1kw0WwF1s2lMtYg= + + + Resources/scripts/action/Japanese/Convert Zenkaku katakana to Hankaku katakana.js + + hash2 + + 0tNeB/21HZHXn8l3gZshtXvOKzhYIhK2xBm/mUKZiS4= + + + Resources/scripts/action/Reverse.js + + hash2 + + gdB10+qDy5fSaUhp9Htz6U/DgtERmPmY/9U9rF7nplk= + + + Resources/scripts/action/Surround with (Japanese)/‘ ’.js + + hash2 + + AWyopaLwY2Z3sgAll3k1gYxWNCYqaxfo3oCqhjtN0b0= + + + Resources/scripts/action/Surround with (Japanese)/“ ”.js + + hash2 + + xAmre//AFArddMhCcA8n+GaSM0DFy41Uv+GLXbgF/hI= + + + Resources/scripts/action/Surround with (Japanese)/〈 〉.js + + hash2 + + iiVa2r0Sm1QG1j/4QOoJoZCETpZejKTNksyfINMmf/A= + + + Resources/scripts/action/Surround with (Japanese)/《 》.js + + hash2 + + fQM+E4pFisgp39qMWpGNRP03uoSYmd6S00iuPP3Htj0= + + + Resources/scripts/action/Surround with (Japanese)/「 」.js + + hash2 + + fDbDaRl0HFsYF3VOpwk3f5o4XPn39byfd7tKaKnPiAA= + + + Resources/scripts/action/Surround with (Japanese)/『 』.js + + hash2 + + fffYpX4roydweNAR30S/ejUShyBwcCoEjkKu91ZEe+Q= + + + Resources/scripts/action/Surround with (Japanese)/【 】.js + + hash2 + + L7A0xWsiSicoP7WhPW3cZV3WSJsrjeknw9FLmRhHyac= + + + Resources/scripts/action/Surround with (Japanese)/〔 〕.js + + hash2 + + w0kUrFrwOM1/37ZThC6tClQc2ydc91Uk72kdLp7OdBo= + + + Resources/scripts/action/Surround with (Japanese)/( ).js + + hash2 + + 4ylw4xB04cw4DOMb8QEeQPI/4M+dqICRM1i5/XZjbHU= + + + Resources/scripts/action/Surround with (Japanese)/< >.js + + hash2 + + vQXqpBkZtu3DbroVxgxIh6KZqs+yKArSUHTvBJZTaqY= + + + Resources/scripts/action/Surround with (Japanese)/[ ].js + + hash2 + + dR/pvEo4WG5anQlA/mLHNKS+VjgbNeTf4eM36vLvNdQ= + + + Resources/scripts/action/Surround with (Japanese)/{ }.js + + hash2 + + 2UF3lRTEpiMbMvoB7qv6kVRaPY8/UzW/ycAnregQX1o= + + + Resources/scripts/action/Surround with/" ".js + + hash2 + + /iZYMZoYdYTgMhnXnzEb9VfY1x1ZQ4Emp01Tiw8VslQ= + + + Resources/scripts/action/Surround with/' '.js + + hash2 + + QcDDCgg2OCc3FIIhVweLC2cb0OjPQACgTezKDL5pm58= + + + Resources/scripts/action/Surround with/( ).js + + hash2 + + Ue2O7yzMTmySjPLy/hTpJXkf52zGyZFcm+ZfjcI/fNQ= + + + Resources/scripts/action/Surround with/< >.js + + hash2 + + FN2pcMNikvjIg8h2vQsvfH1s66aLc7SFjyMOWysoV40= + + + Resources/scripts/action/Surround with/[ ].js + + hash2 + + pRWGqT1S0Rlrq04rb00EYgR+RobA5zqMXv2exq6L7dI= + + + Resources/scripts/action/Surround with/` `.js + + hash2 + + 2yVJ5CcVEi9uK2Mi388kTwp2kp9cwAZaJzLMbmimd2I= + + + Resources/scripts/action/Surround with/{ }.js + + hash2 + + z0b6hEvAcJjdYeoaCadKTaZG37OnlVUSzI/1sEO/SM8= + + + Resources/scripts/action/Trim/LTrim.js + + hash2 + + cIbvcVshukYYh3i/SeAekP2mvc4BepPePFZv1T6ymYw= + + + Resources/scripts/action/Trim/RTrim.js + + hash2 + + U1rfr7gvZc98uUhjpFH3Gw5mD1mRjlXa3414pIwBrf0= + + + Resources/scripts/action/Trim/Trim.js + + hash2 + + j9lvRuVePu2mq8TWHTKx7n+ItiLMyYBoZ+K0qUZTZKI= + + + Resources/scripts/lib/JS-methods/char.js + + hash2 + + Q1/sGhQejqO79g2Cd0+lJtBUjPXZGf4gApPduKMxLp0= + + + Resources/scripts/lib/JS-methods/string.js + + hash2 + + 3n9/682H+FHSa8h5c5Ho5BAlAo9bKRz4mJ7e28duBoo= + + + Resources/scripts/lib/fhconvert.js + + hash2 + + cALcSy4L3PNgejiJBh1JJ+4mjavii52pdQ2ev2QSv74= + + + Resources/scripts/lib/inflection.js + + hash2 + + YugOzP1zeURZRBWRQYPgOFwMU3arLAVkhw5ALhXzTbw= + + + Resources/scripts/lib/showdown.js + + hash2 + + iBgvH9jV1J3Hc3/p0SUWoUH9rnXaURA63xRy0dDi220= + + + Resources/scripts/lib/v8cgi/html.js + + hash2 + + ZYnogeoDGfZDTqGZoGuZcQSk09Hq0HIk0Aql5FcWsXs= + + + Resources/scripts/lib/v8cgi/util.js + + hash2 + + y217T4HANHIX4sruRvinblHA5WTnUFJbiwRL7cIFD2I= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/dist/ClipMenu.dmg b/dist/ClipMenu.dmg new file mode 100644 index 0000000..91d3f7e Binary files /dev/null and b/dist/ClipMenu.dmg differ diff --git a/doc/VersionHistory-en.yaml b/doc/VersionHistory-en.yaml deleted file mode 100644 index eb75649..0000000 --- a/doc/VersionHistory-en.yaml +++ /dev/null @@ -1,120 +0,0 @@ - -0.4.3: - date: 2009-11-09 - changes: - fixed: - - Fix a bug where you couldn't edit snippets in version 0.4.2. - -0.4.2: - date: 2009-11-08 - changes: - new: - - Add a feature to exclude applications from checking the clipboard. - - Add a feature to export clipboard history as text file(s). - - Add an option to check for pre-releases. - changed: - - Change how to manage clipboard history. - - Change how to check for duplicate of history items. - - Change how to sort history order. - - Change how to make thumbnail image in the menu. - - Change initialization process. - fixed: - - Fix a issue that always show status bar icon whether turned on/off. - -0.4.1: - date: 2009-10-21 - changes: - fixed: - - Fix a bug that causes force pasting regardless of the preference. - -0.4.0: - date: 2009-10-20 - changes: - new: - - 64-bit support in Mac OS X 10.6 (Snow Leopard). - - Add autosave function to save clipboard history periodically. - - Automatic update support using Sparkle Framework. - - Add a dialog to ask you whether enable/disable "Launch on Login" option. - - Add an option to enable/disable re-ordering history when clipboard data is changed. - - Append the application's version number to a tooltip on the status menubar icon. - changed: - - Change default keyboard shortcut keys (command-shift-v, command-shift-b). - - Change folder icon when mouse over a folder menu item in a menu. - - Make status bar icon selectable. - - Add new status bar icons (by Dave Ulrich). - - Change the label of "Quit" menu item to "Quit ClipMenu". - - Add a suppression button to the dialog window to ask whether show it or not. - - Multi-thread start up operations. - - Update Shortcut Recorder framework. - fixed: - - Fix a glitch occurred when max history size is decreased. - - Fix an issue with preferences panel. - -0.3.5: - date: 2009-06-17 - changes: - new: - - Added "Paste as File Path" action. - - Added "Paste as HFS File Path" action. - - Added Japanese hiragana <-> katakana converter actions. - - Added Japanese half-width katakana <-> full-width katakana converter actions. - - Added actions for surrounding selected item with parenthesizes or HTML tags. - - Added actions for calculating MD5/SHA-1 hash and Base64 encoding/decoding. - - Added actions for Markdown conversion, encoding/decoding URI component, escaping/unescaping HTML characters, removing HTML tags, collapsing spaces and converting characters to decimals. - - Included JavaScript libraries, fhconvert.js, showdown.js, v8cgi and JS-methods. - - Added activate() method for JavaScript action. - - Added a setting to limit the maximum length of tool tip string. - changed: - - You can now apply actions to snippets. - - Changed a behavior when you create a new snippet. If you forget to enter the content of the snippet, its title will be copied automatically to the content. - - Improved the way to check duplication of history items. - - Changed serialization format of registered actions to Property List. - - Changed default action set. - - Changed the way to load bundled JavaScript actions. - - Changed a JavaScript library for Japanese characters conversion "z2h_word.js" to "fhconvert.js". - - Updated inflection.js to the most recent version. - - Added Japanese localization for names of JavaScript actions at Preferences panel. - - Improved usability of preferences panel. - fixed: - - Fixed a glitch that an error dialog called in JavaScript actions is not the most front window. - -0.3.4: - date: 2009-05-24 - changes: - new: - - Support Spaces on Leopard. - - New website. - - Add ReadMe file in English. - changed: - - Accept a shortcut key combination (Command-Option-V). - fixed: - - Removed snippets remain in Snippets.xml file. - - Cannot close Preferences panel by shortcut key combination. - -0.3.3: - date: 2008-12-06 - -0.3.2: - date: 2008-11-26 - -0.3.1: - date: 2008-11-12 - -0.3.0: - date: 2008-11-09 - note: Mac OS X 10.5 or later. - -0.2.1: - date: 2008-03-13 - -0.2.0: - date: 2008-03-10 - note: Mac OS X 10.4 or later. - -0.1.1: - date: 2008-01-15 - -0.1.0: - date: 2008-01-03 - note: Mac OS X 10.3 or later. - diff --git a/doc/VersionHistory-ja.yaml b/doc/VersionHistory-ja.yaml deleted file mode 100644 index f9a8db8..0000000 --- a/doc/VersionHistory-ja.yaml +++ /dev/null @@ -1,180 +0,0 @@ - -0.4.3: - date: 2009-11-09 - changes: - fixed: - - v0.4.2で、スニペットが編集できない問題を修正。 - -0.4.2: - date: 2009-11-08 - changes: - new: - - 指定したアプリケーションをクリップボードの監視対象から外すための、除外アプリケーション機能を追加。 - - クリップボード履歴を、テキストファイルとして書き出す機能を追加。 - - プレリリース版の自動アップデートに対応。 - changed: - - 履歴の管理方式を変更。 - - 履歴の重複チェックの方法を変更。 - - 履歴のソート順の設定方法を変更。 - - メニュー内の画像表示方法を変更。 - - 起動時の初期化方法を変更。 - fixed: - - ステータスバーにアイコンを表示しない設定にしていても、起動時に反映されない問題を修正。 - -0.4.1: - date: 2009-10-21 - changes: - fixed: - - 環境設定でオフにしていても、ペーストしてしまう問題を修正。 - -0.4.0: - date: 2009-10-20 - changes: - new: - - 64ビットモードに対応。 - - 履歴の自動保存機能を追加。 - - Sparkleフレームワークによる、自動アップデート機能を追加。 - - ログイン項目に追加するか問い合わせるダイアローグを追加。 - - 履歴の順序を変更するか設定できるオプションを追加。 - - ステータスバー・アイコン上のツールチップに、バージョン番号を表示するように変更。 - changed: - - ショートカットキーの組み合わせを変更(command-shift-v)。 - - メニュー内のフォルダ項目にマウスオーバーすると、開いた状態のアイコンに変化するように変更。 - - ステータスバー・アイコンを選択可能に変更。 - - ステータスバー・アイコンを追加(Dave Ulrich氏作)。 - - メニューの「終了」を「ClipMenuを終了」に変更。 - - 「履歴をクリア」で現れるダイアローグに、ダイアローグを表示しないように設定できるチェックボックスを追加。 - - 起動時の処理をマルチスレッド化。 - - Shortcut Recorderフレームワークをアップデート。 - fixed: - - 履歴の最大値を減少させても、すぐに反映されない問題を修正。 - - 環境設定のアクション登録画面で、アクション名が長すぎると、表示が途切れてしまう問題を修正。 - -0.3.5: - date: 2009-06-17 - changes: - new: - - 「ファイルパスとしてペースト」をアクションに追加。 - - 「HFSファイルパスとしてペースト」をアクションに追加。 - - ひらがな/カタカナを相互変換するアクションを追加。 - - 全角/半角カタカナを相互変換するアクションを追加。 - - 文字列を指定した括弧で囲んだり、不要な空白を削除するアクションを追加。 - - Markdown形式に変換、URIコンポーネントのエンコード/デコード、HTML文字実体参照のエスケープ/アンエスケープ、HTMLタグで囲む、HTMLタグを削除する、10進数値参照に変換するアクションを追加。 - - MD5/SHA-1/Base64に変換するアクションを追加。 - - JavaScriptライブラリの、fhconvert.js、showdown.js、v8cgi、JS-methodsを同梱。 - - JavaScriptアクションの組み込みメソッドに、activate()を追加。 - - ツールチップに表示する文字列の最大値を指定する設定項目を追加。 - changed: - - スニペットに対しても、アクションを適用可能に変更。 - - 新規スニペット作成の際に、入力されたのがタイトルだけで内容が空の場合、自動的にタイトルの文字列をスニペットの内容としてコピーするように変更。 - - 履歴の重複チェック方法を、若干の効率化。 - - 登録したアクションの保存形式を、Property List形式に変更。 - - デフォルトで登録されるアクションを変更。 - - 同梱するJavaScriptアクションの読み込み方法を変更。 - - 同梱する日本語文字列変換用のJavaScriptライブラリを、z2h_word.jsからfhconvert.jsに変更。 - - 同梱するJavaScriptライブラリのinflection.jsを、最新版に更新。 - - JavaScriptアクションの日本語ローカライズ表示を復活。 - - 環境設定画面のユーザビリティの向上。 - fixed: - - JavaScriptアクションのエラー・ダイアローグが、最前面に表示されなかった問題を修正。 - -0.3.4: - date: 2009-05-24 - changes: - new: - - Spacesに対応。 - - ClipMenu.comを作成。 - - 英文のReadMeを追加。 - changed: - - 登録できるショートカットキーを追加(Command + Option + V)。 - fixed: - - 環境設定画面で、フォルダ内で削除したスニペットがSnippets.xmlに残ってしまう問題を修正。 - - 環境設定画面をショートカットキーで閉じられなかった問題を修正。 - -0.3.3: - date: 2008-12-06 - changes: - fixed: - - XMLファイルから読み込んだスニペットが、メニュー内に現れなかった問題を修正。 - - 環境設定パネルで、メニューのフォントサイズを変更できなくなっていた問題を修正 - -0.3.2: - date: 2008-11-26 - changes: - new: - - メニュー項目上での「修飾キー + クリック」に、アクション割り当て機能を追加。 - - XML形式でスニペットを、読み込み/書き出しする機能を追加。 - changed: - - アクションメニューの呼び出し方法の初期設定を、「右クリック」、「Control + クリック」、「Control + Enter」の3種類に変更。 - - 履歴数の初期値を、50から20に変更。 - fixed: - - キー入力でアクションメニューがポップアップされなかった問題を修正。 - - ステータスバーのアイコンを非表示にする際の問題を修正。 - -0.3.1: - date: 2008-11-12 - changes: - new: - - 登録したアクションが一つだけだった場合は、メニューをポップアップせず、即座にアクションを適用できる設定を追加。 - - ツールチップの表示/非表示を選択できる設定を追加。 - changed: - - 環境設定画面の設定項目の整理。 - fixed: - - PowerPC搭載のMacで、環境設定画面が開けなかった問題を修正。 - -0.3.0: - date: 2008-11-09 - note: 動作環境: Mac OS X 10.5以降。 - changes: - new: - - 新しいアイコン(製作・著作権者: K2DesignWorksのK2さん)を採用。 - - スニペット機能を追加。 - - ログイン項目に、ClipMenuを登録する設定を追加。 - - 終了時に、履歴を保存するかを変更できる設定を追加。 - - メニュー項目の種類を表すラベルを追加。 - changed: - - 対応OSを、Mac OS X v10.5以降に変更。 - - ショートカットキーへの登録方法を一新。 - - メニューにインライン表示する履歴数を変更可能に。 - - 一つのフォルダに含む履歴数を変更可能に。 - - クリップボードの種類がファイル名なら、PICT画像をメニュー内に表示しないように変更。 - - 環境設定画面を再構成。 - -0.2.1: - date: 2008-03-13 - changes: - changed: - - アクション機能の動作対象OSを、暫定的にMac OS X v10.4.xに限定(Mac OS X v10.5環境において、表示に問題が生じたため)。 - fixed: - - 履歴クリアの際に起こる不具合を修正。 - - メニュー内のアイコン表示の不具合を修正。 - - ホットキーで起動した際に、正しい位置に表示されない問題を修正。 - -0.2.0: - date: 2008-03-10 - note: 動作環境: Mac OS X 10.4以降。 - changes: - new: - - アクション機能を実装。 - - 環境設定画面にツールバーを搭載。 - - メニューに、数字キーのショートカットを追加。 - - 履歴を全消去できる、メニュー項目を追加。 - changed: - - 動作対象OSを、Mac OS X v10.4以降に変更。 - -0.1.1: - date: 2008-01-15 - changes: - new: - - メニューのフォントサイズ変更に対応。 - changed: - - メニューに表示する文字列を、トリムしてから表示するように変更。 - fixed: - - メニューの表示文字数に、小さすぎる値を入れた際に、正常に動作しない問題を修正。 - -0.1.0: - date: 2008-01-03 - note: 動作環境: Mac OS X 10.3以降。 - changes: - new: - - 最初のリリース。 diff --git a/doc/archive_contents/ClipMenu website.webloc b/doc/archive_contents/ClipMenu website.webloc deleted file mode 100644 index 78f1403..0000000 Binary files a/doc/archive_contents/ClipMenu website.webloc and /dev/null differ diff --git "a/doc/archive_contents/JavaScript\343\202\242\343\202\257\343\202\267\343\203\247\343\203\263\343\201\256\346\233\270\343\201\215\346\226\271.txt" "b/doc/archive_contents/JavaScript\343\202\242\343\202\257\343\202\267\343\203\247\343\203\263\343\201\256\346\233\270\343\201\215\346\226\271.txt" deleted file mode 100644 index ea4b82c..0000000 --- "a/doc/archive_contents/JavaScript\343\202\242\343\202\257\343\202\267\343\203\247\343\203\263\343\201\256\346\233\270\343\201\215\346\226\271.txt" +++ /dev/null @@ -1,91 +0,0 @@ ---------------------------------------------------------------------------- - - JavaScriptアクションの書き方 - ---------------------------------------------------------------------------- - -0. 基本 -1. 設置 -2. スクリプトの書き方 -3. その他 - ---------------------------------------------------------------------------- -0. 基本 - -ClipMenuでは、ユーザーの作成したアクションを使って、テキスト形式のクリップボード履歴に対する文字列処理を行うことができます。ユーザーアクションの実行には、スクリプト言語のJavaScriptを使用します。 - -ClipMenuのJavaScript実行エンジンには、WebKitに含まれるJavaScriptCoreを利用しています。JavaScriptの動作仕様は、Safariを参考にしてください。なお、ClipMenuでは基本的に、コアJavaScript部分のみを使用します。 - ---------------------------------------------------------------------------- -1. 設置 - -ユーザー作成のJavaScriptファイルは、以下のフォルダに設置します。このフォルダが存在しない場合は、Finderから新規に作成してください。 - -/Users/<ユーザ名>/ライブラリ/Application Support/ClipMenu/script/action - -スクリプトファイルの拡張子は、".js" になります。これ以外の拡張子を持ったファイルは、無視されます。 - -actionフォルダ以下に存在するフォルダは、アクションメニューのサブメニューとして機能します。同じ種類のスクリプトファイルは、フォルダにまとめておくと便利です。 - - ---------------------------------------------------------------------------- -2. スクリプトの書き方 - -[クリップボード文字列] -ClipMenuアプリケーションから渡されたクリップボード履歴の文字列は、clipText 変数に代入されています。この変数に対して関数を適用したり、メソッドを実行して文字列処理を行ってください。 - -例)アルファベットをすべて大文字に変える -clipText.toUpperCase(); - - -[処理の終了] -必要な処理が済んだら、return 文で値を戻します。return 文に渡す式の戻り値は、文字列か数値になるようにしてください。 - -例)アルファベットをすべて大文字に変えて、クリップボードに送る -return clipText.toUpperCase(); - -この時、return 文に式を指定しないと、クリップボード履歴に対する処理は何も行われません。 - -例)何も返さず、終了 -return; - - -[ライブラリの読み込み] -複数のファイルで共通して使用する関数などは、ライブラリとして別ファイルに保存しておくと便利です。ClipMenuでは、指定したフォルダに置かれたスクリプトを、ライブラリとして読み込むことができます。読み込みには、ClipMenuオブジェクトの、require() メソッドを使用します。 - -例)inflection-jsを読み込む -ClipMenu.require('inflection'); - -require() メソッドの引数には、ライブラリスクリプトのファイル名を渡します。拡張子の".js"は、有っても無くても構いません。読み込みが成功したかどうかは、require() メソッドの戻り値を使ってチェックできます。ライブラリが見つかれば 1 を、見つからなければ 0 を返します。 - -例)require() メソッドの戻り値をチェック -var isExist = ClipMenu.require('inflection'); -if (!isExist) { - throw new Error('Cound not find the file'); -} - -ライブラリの読み込みが成功すると、ライブラリ内で定義された関数が利用可能になります。 - -例)inflection-jsで定義された、capitalize() メソッドを使用する -clipText.capitalize(); - -ライブラリフォルダには、アプリケーションバンドル内にある標準ライブラリフォルダと、ユーザーが設置するユーザーライブラリフォルダの二種類があります。ユーザーライブラリフォルダは、以下のパスに作成してください。 - -/Users/<ユーザ名>/ライブラリ/Application Support/ClipMenu/script/lib - -ライブラリの読み込みは、ユーザーライブラリフォルダが優先されます。こちらから検索した後、標準ライブラリフォルダの検索を行います。 - - -[ユーザー入力] -prompt() メソッドを使用すれば、ユーザー入力を組み合わせた処理ができます。 - -例)クリップボードにコピーしたURLと、入力したタイトルを組み合わせて、HTMLコードを作成 -var input = prompt('タイトルを入力:'); -return '' + input + ''; - - ---------------------------------------------------------------------------- -3. その他 - -- alert() 、 confirm() メソッドは動作しません。 - diff --git a/doc/archive_contents/ReadMe (Japanese).rtfd/TXT.rtf b/doc/archive_contents/ReadMe (Japanese).rtfd/TXT.rtf deleted file mode 100644 index 1bbfd09..0000000 --- a/doc/archive_contents/ReadMe (Japanese).rtfd/TXT.rtf +++ /dev/null @@ -1,742 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf110 -\readonlydoc1{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 LucidaGrande;\f2\fswiss\fcharset0 ArialMT; -\f3\fnil\fcharset128 HiraKakuPro-W3;\f4\fnil\fcharset0 HelveticaNeue;\f5\fnil\fcharset0 Monaco; -\f6\fnil\fcharset128 HiraKakuProN-W3;} -{\colortbl;\red255\green255\blue255;\red0\green0\blue128;\red35\green110\blue37;\red51\green51\blue51; -\red0\green0\blue255;} -{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid1\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid1} -{\list\listtemplateid2\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid101\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid102\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid2} -{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}\levelprepend{\leveltext\leveltemplateid201\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3} -{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid301\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4} -{\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}\levelprepend{\leveltext\leveltemplateid401\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid5} -{\list\listtemplateid6\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}\levelprepend{\leveltext\leveltemplateid501\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid6} -{\list\listtemplateid7\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}\levelprepend{\leveltext\leveltemplateid601\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid7} -{\list\listtemplateid8\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid701\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid702\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid8} -{\list\listtemplateid9\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid801\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid802\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid9} -{\list\listtemplateid10\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid901\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid902\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid10} -{\list\listtemplateid11\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1001\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1002\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid11} -{\list\listtemplateid12\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid12} -{\list\listtemplateid13\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid13} -{\list\listtemplateid14\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid14} -{\list\listtemplateid15\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1401\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid15} -{\list\listtemplateid16\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1501\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid16} -{\list\listtemplateid17\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1601\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid17} -{\list\listtemplateid18\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1701\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid18} -{\list\listtemplateid19\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1801\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid19} -{\list\listtemplateid20\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1901\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid20} -{\list\listtemplateid21\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid2001\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid21} -{\list\listtemplateid22\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid2101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid22} -{\list\listtemplateid23\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid2201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid23} -{\list\listtemplateid24\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid2301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid24}} -{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}{\listoverride\listid8\listoverridecount0\ls8}{\listoverride\listid9\listoverridecount0\ls9}{\listoverride\listid10\listoverridecount0\ls10}{\listoverride\listid11\listoverridecount0\ls11}{\listoverride\listid12\listoverridecount0\ls12}{\listoverride\listid13\listoverridecount0\ls13}{\listoverride\listid14\listoverridecount0\ls14}{\listoverride\listid15\listoverridecount0\ls15}{\listoverride\listid16\listoverridecount0\ls16}{\listoverride\listid17\listoverridecount0\ls17}{\listoverride\listid18\listoverridecount0\ls18}{\listoverride\listid19\listoverridecount0\ls19}{\listoverride\listid20\listoverridecount0\ls20}{\listoverride\listid21\listoverridecount0\ls21}{\listoverride\listid22\listoverridecount0\ls22}{\listoverride\listid23\listoverridecount0\ls23}{\listoverride\listid24\listoverridecount0\ls24}} -\paperw11900\paperh16840\vieww12380\viewh13400\viewkind0 -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\fs24 \cf0 {{\NeXTGraphic ozmCP.tiff \width640 \height640 \noorient -}}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural -\cf0 -\f1\b\fs48 \up6 ClipMenu -\f0\fs24 \up0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b0 \cf0 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf2 ClipMenu -\f3 \'82\'c9\'82\'c2\'82\'a2\'82\'c4 -\f2 -\fs24 \cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\b0 \cf0 ClipMenu -\f3 \'82\'cd\'81\'41\'95\'a1\'90\'94\'82\'cc\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'97\'9a\'97\'f0\'82\'f0\'82\'c6\'82\'e9\'82\'bd\'82\'df\'82\'cc\'83\'5c\'83\'74\'83\'67\'82\'c5\'82\'b7\'81\'42\'8b\'4c\'98\'5e\'82\'b5\'82\'c4\'82\'a8\'82\'af\'82\'e9\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'8c\'60\'8e\'ae\'82\'cd\'81\'41\'83\'76\'83\'8c\'81\'5b\'83\'93\'83\'65\'83\'4c\'83\'58\'83\'67\'82\'a9\'82\'e7\'89\'e6\'91\'9c\'82\'dc\'82\'c5\'81\'41\'91\'53\'95\'94\'82\'c58\'8e\'ed\'97\'de\'82\'c9\'91\'ce\'89\'9e\'81\'42\ -\ -\'82\'dc\'82\'bd\'81\'41\'82\'e6\'82\'ad\'8e\'67\'82\'a4\'92\'e8\'8c\'5e\'95\'b6\'82\'c8\'82\'c7\'82\'f0\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'c6\'82\'b5\'82\'c4\'93\'6f\'98\'5e\'82\'b5\'82\'c4\'82\'a8\'82\'af\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\b \cf0 ClipMenu -\f3 \'82\'cc\'8e\'e5\'82\'c8\'8b\'40\'94\'5c -\b0 \'81\'46\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f4\b\fs26 \cf0 \'95 -\f3\b0\fs24 \'8b\'4c\'98\'5e\'82\'b7\'82\'e9\'97\'9a\'97\'f0\'90\'94\'82\'cd\'81\'41\'8e\'a9\'97\'52\'82\'c9\'90\'dd\'92\'e8\'89\'c2\'94\'5c\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'83\'7c\'83\'62\'83\'76\'83\'41\'83\'62\'83\'76\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'cd\'81\'41\'8e\'a9\'97\'52\'82\'c9\'90\'dd\'92\'e8\'89\'c2\'94\'5c\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'c9\'82\'cd\'81\'41\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'8c\'60\'8e\'ae\'82\'c9\'89\'9e\'82\'b6\'82\'bd\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'95\'5c\'8e\'a6\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'97\'9a\'97\'f0\'82\'c9\'89\'e6\'91\'9c\'82\'aa\'8a\'dc\'82\'dc\'82\'ea\'82\'c4\'82\'a2\'82\'ea\'82\'ce\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'c9\'88\'ea\'95\'94\'82\'f0\'95\'5c\'8e\'a6\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'97\'9a\'97\'f0\'82\'c9\'83\'65\'83\'4c\'83\'58\'83\'67\'82\'aa\'8a\'dc\'82\'dc\'82\'ea\'82\'c4\'82\'a2\'82\'ea\'82\'ce\'81\'41\'83\'63\'81\'5b\'83\'8b\'83\'60\'83\'62\'83\'76\'82\'c5\'93\'e0\'97\'65\'82\'f0\'95\'5c\'8e\'a6\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'82\'c9\'81\'41\'83\'41\'83\'43\'83\'52\'83\'93\'82\'cc\'95\'5c\'8e\'a6\'81\'5e\'94\'f1\'95\'5c\'8e\'a6\'82\'f0\'91\'49\'91\'f0\'89\'c2\'94\'5c -\f4\b\fs26 \'95 -\f3\b0\fs24 JavaScript\'82\'f0\'97\'98\'97\'70\'82\'b5\'82\'c4\'81\'41\'83\'65\'83\'4c\'83\'58\'83\'67\'8c\'60\'8e\'ae\'82\'cc\'97\'9a\'97\'f0\'82\'f0\'89\'c1\'8d\'48\'89\'c2\'94\'5c -\f4\b\fs26 \ - \'95 -\f3\b0\fs24 \'92\'e8\'8c\'5e\'95\'b6\'82\'f0\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'c6\'82\'b5\'82\'c4\'93\'6f\'98\'5e\'89\'c2\'94\'5c\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 \'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'be\'82\'af\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'81\'41\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'e0\'8e\'67\'97\'70\'89\'c2\'94\'5c\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\b \cf0 \'93\'ae\'8d\'ec\'8f\'f0\'8c\'8f -\f2\b0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f4\b\fs26 \cf0 \'95 -\f3\b0\fs24 Mac OS X v10.5 \'88\'c8\'8d\'7e\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 64\'83\'72\'83\'62\'83\'67\'83\'82\'81\'5b\'83\'68\'82\'c5\'82\'cc\'8e\'67\'97\'70\'82\'c9\'82\'cd\'81\'41Mac OS X v10.6 \'88\'c8\'8d\'7e\'82\'aa\'95\'4b\'97\'76\'82\'c5\'82\'b7\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 PowerPC \'82\'dc\'82\'bd\'82\'cd Intel \'83\'76\'83\'8d\'83\'5a\'83\'62\'83\'54\'82\'f0\'93\'8b\'8d\'da\'82\'b5\'82\'bd Macintosh\ - ClipMenu \'82\'cd Universal\'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93\'82\'c5\'82\'b7\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\b \cf0 \'83\'43\'83\'93\'83\'58\'83\'67\'81\'5b\'83\'8b -\f2\b0 \ -ClipMenu -\f3 \'82\'f0\'81\'41 \'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93 \'83\'74\'83\'48\'83\'8b\'83\'5f\'82\'c9\'83\'52\'83\'73\'81\'5b\'82\'b5\'82\'dc\'82\'b7\'81\'42\ -\ -\'8f\'ed\'97\'70\'82\'b7\'82\'e9\'8f\'ea\'8d\'87\'82\'cd\'81\'41\'83\'8d\'83\'4f\'83\'43\'83\'93\'8d\'80\'96\'da\'82\'c9\'8e\'77\'92\'e8\'82\'b5\'82\'c4\'82\'a8\'82\'ad\'82\'c6\'95\'d6\'97\'98\'82\'c5\'82\'b7\'81\'42\'83\'8d\'83\'4f\'83\'43\'83\'93\'8d\'80\'96\'da\'82\'d6\'82\'cc\'93\'6f\'98\'5e\'81\'5e\'93\'6f\'98\'5e\'89\'f0\'8f\'9c\'82\'cd\'81\'41\'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'82\'cc\'81\'75\'83\'8d\'83\'4f\'83\'43\'83\'93\'8e\'9e\'82\'c9\'8b\'4e\'93\'ae\'81\'76\'83\'60\'83\'46\'83\'62\'83\'4e\'83\'7b\'83\'62\'83\'4e\'83\'58\'82\'c5\'90\'d8\'82\'e8\'91\'d6\'82\'a6\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'83\'41\'83\'93\'83\'43\'83\'93\'83\'58\'83\'67\'81\'5b\'83\'8b -\f2\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f3 \cf0 \'83\'43\'83\'93\'83\'58\'83\'67\'81\'5b\'83\'8b\'82\'b5\'82\'bd -\f2 ClipMenu -\f3 \'82\'f0\'83\'53\'83\'7e\'94\'a0\'82\'c9\'88\'da\'93\'ae\'82\'b5\'81\'41Finder\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'a9\'82\'e7\'81\'75\'83\'53\'83\'7e\'94\'a0\'82\'f0\'8b\'f3\'82\'c9\'82\'b7\'82\'e9...\'81\'76\'82\'f0\'91\'49\'91\'f0\'82\'b5\'82\'dc\'82\'b7\'81\'42\ -\ -\'90\'dd\'92\'e8\'83\'74\'83\'40\'83\'43\'83\'8b\'82\'e2\'97\'9a\'97\'f0\'83\'66\'81\'5b\'83\'5e\'82\'e0\'8d\'ed\'8f\'9c\'82\'b5\'82\'bd\'82\'a2\'8f\'ea\'8d\'87\'82\'cd\'81\'41\'88\'c8\'89\'ba\'82\'cc\'83\'74\'83\'40\'83\'43\'83\'8b\'82\'e0\'83\'53\'83\'7e\'94\'a0\'82\'c9\'88\'da\'93\'ae\'82\'b5\'82\'c4\'82\'ad\'82\'be\'82\'b3\'82\'a2\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f4\b\fs26 \cf0 \'95 -\f3\b0\fs24 /Users/<\'83\'86\'81\'5b\'83\'55\'96\'bc>/\'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a/Preferences/com.naotaka.ClipMenu.plist\ - -\f4\b\fs26 \'95 -\f3\b0\fs24 /Users/<\'83\'86\'81\'5b\'83\'55\'96\'bc>/\'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a/Application Support/ClipMenu -\f2 \ -\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\b\fs28 \cf2 \'8e\'67\'82\'a2\'95\'fb -\f2\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\b \cf0 \'8b\'4e\'93\'ae -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2 \cf0 ClipMenu -\f3 \'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'83\'5f\'83\'75\'83\'8b\'83\'4e\'83\'8a\'83\'62\'83\'4e\'82\'b5\'82\'c4\'8b\'4e\'93\'ae\'82\'b5\'82\'dc\'82\'b7\'81\'42\'8b\'4e\'93\'ae\'8c\'e3\'82\'cd\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'83\'6f\'81\'5b\'89\'45\'91\'a4\'82\'cc\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'41\'83\'43\'83\'65\'83\'80\'82\'cc\'95\'5c\'8e\'a6\'97\'cc\'88\'e6\'82\'c9\'81\'41\'83\'41\'83\'43\'83\'52\'83\'93\'82\'aa\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'95\'5c\'8e\'a6 -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2 \cf0 ClipMenu -\f3 \'82\'cc\'8c\'c4\'82\'d1\'8f\'6f\'82\'b5\'95\'fb\'96\'40\'82\'cd\'82\'51\'8e\'ed\'97\'de\'82\'a0\'82\'e8\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls1\ilvl0\cf0 {\listtext 1. }\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'82\'cc\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'41\'83\'43\'83\'65\'83\'80\'82\'a9\'82\'e7\'81\'41\'82\'a2\'82\'c2\'82\'c5\'82\'e0\'83\'41\'83\'4e\'83\'5a\'83\'58\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42 -\f1 \uc0\u8232 \u8232 -\f3 \'82\'c8\'82\'a8\'81\'41Mac OS X\'82\'cc\'8e\'64\'97\'6c\'82\'c9\'82\'e6\'82\'e8\'81\'41\'8d\'c5\'91\'4f\'96\'ca\'82\'cc\'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93\'82\'aa\'8e\'67\'97\'70\'82\'b7\'82\'e9\'83\'81\'83\'6a\'83\'85\'81\'5b\'97\'cc\'88\'e6\'82\'cc\'89\'a1\'95\'9d\'82\'aa\'8d\'4c\'82\'ad\'82\'c8\'82\'e9\'82\'c6\'81\'41\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'82\'c9\'83\'41\'83\'43\'83\'52\'83\'93\'82\'aa\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'c8\'82\'ad\'82\'c8\'82\'e9\'82\'b1\'82\'c6\'82\'e0\'82\'a0\'82\'e8\'82\'dc\'82\'b7\'81\'42 -\f1 \uc0\u8232 -\f3 \ -{\listtext 2. }\'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'81\'69\'83\'4c\'81\'5b\'83\'7b\'81\'5b\'83\'68\'81\'45\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'81\'6a\'82\'f0\'89\'9f\'82\'b5\'82\'c4\'83\'7d\'83\'45\'83\'58\'83\'7c\'83\'43\'83\'93\'83\'5e\'82\'cc\'91\'a4\'82\'c9\'83\'7c\'83\'62\'83\'76\'83\'41\'83\'62\'83\'76\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'81\'42 -\f1 \uc0\u8232 \u8232 -\f3 \'83\'66\'83\'74\'83\'48\'83\'8b\'83\'67\'81\'69\'8f\'89\'8a\'fa\'8f\'f3\'91\'d4\'81\'6a\'82\'c5\'82\'cd\'81\'41" -\b Command + Shift + V -\b0 "\'82\'c9\'90\'dd\'92\'e8\'82\'b3\'82\'ea\'82\'c4\'82\'a2\'82\'dc\'82\'b7\'81\'42\'82\'b1\'82\'cc\'83\'4c\'81\'5b\'82\'cc\'91\'67\'82\'dd\'8d\'87\'82\'ed\'82\'b9\'82\'f0\'93\'af\'8e\'9e\'82\'c9\'89\'9f\'82\'b7\'82\'c6\'81\'41\'83\'7d\'83\'45\'83\'58\'83\'7c\'83\'43\'83\'93\'83\'5e\'82\'cc\'82\'a0\'82\'e9\'88\'ca\'92\'75\'82\'c9\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'aa\'8c\'bb\'82\'ea\'82\'dc\'82\'b7\'81\'42\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'e9\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cd\'82\'c7\'82\'bf\'82\'e7\'82\'e0\'93\'af\'82\'b6\'82\'e0\'82\'cc\'82\'c8\'82\'cc\'82\'c5\'81\'41\'82\'a8\'8d\'44\'82\'dd\'82\'c9\'89\'9e\'82\'b6\'82\'bd\'95\'fb\'96\'40\'82\'f0\'82\'a8\'8e\'67\'82\'a2\'82\'ad\'82\'be\'82\'b3\'82\'a2\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'97\'9a\'97\'f0\'82\'cc\'91\'49\'91\'f0 -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \'95\'5c\'8e\'a6\'82\'b5\'82\'bd\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'a9\'82\'e7\'81\'41\'83\'79\'81\'5b\'83\'58\'83\'67\'81\'69\'93\'5c\'95\'74\'82\'af\'81\'6a\'82\'b5\'82\'bd\'82\'a2\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'82\'cc\'97\'9a\'97\'f0\'82\'f0\'91\'49\'82\'f1\'82\'c5\'82\'ad\'82\'be\'82\'b3\'82\'a2\'81\'42\ -\ -\'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'cc\'88\'da\'93\'ae\'82\'c9\'82\'cd\'81\'41\'83\'7d\'83\'45\'83\'58\'82\'be\'82\'af\'82\'c5\'82\'c8\'82\'ad\'81\'41\'83\'4c\'81\'5b\'83\'7b\'81\'5b\'83\'68\'82\'f0\'8e\'67\'82\'a4\'95\'fb\'96\'40\'82\'e0\'82\'a0\'82\'e8\'82\'dc\'82\'b7\'81\'42\'96\'ee\'88\'f3\'83\'4c\'81\'5b\'82\'cc\'8f\'e3\'89\'ba\'82\'aa\'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'cc\'8f\'63\'95\'fb\'8c\'fc\'82\'cc\'88\'da\'93\'ae\'82\'c9\'91\'ce\'89\'9e\'82\'b5\'81\'41\'8d\'b6\'89\'45\'82\'aa\'8a\'4b\'91\'77\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'88\'da\'93\'ae\'82\'c9\'91\'ce\'89\'9e\'82\'b5\'82\'c4\'82\'a2\'82\'dc\'82\'b7\'81\'42\ -\ -\'82\'dc\'82\'bd\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'95\'5c\'8e\'a6\'82\'b5\'82\'bd\'8f\'f3\'91\'d4\'82\'c5\'90\'94\'8e\'9a\'83\'4c\'81\'5b\'82\'f0\'89\'9f\'82\'b7\'82\'c6\'81\'41\'82\'bb\'82\'cc\'94\'d4\'8d\'86\'82\'aa\'82\'d3\'82\'e7\'82\'ea\'82\'bd\'88\'ca\'92\'75\'82\'c9\'83\'57\'83\'83\'83\'93\'83\'76\'82\'b7\'82\'e9\'82\'b1\'82\'c6\'82\'e0\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\ -\ -\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'a9\'82\'e7\'97\'9a\'97\'f0\'82\'f0\'91\'49\'82\'d4\'82\'c6\'81\'41\'82\'bb\'82\'cc\'97\'9a\'97\'f0\'83\'66\'81\'5b\'83\'5e\'82\'cc\'93\'e0\'97\'65\'82\'aa\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'82\'c9\'83\'52\'83\'73\'81\'5b\'82\'b3\'82\'ea\'81\'41\'83\'79\'81\'5b\'83\'58\'83\'67\'82\'aa\'8d\'73\'82\'ed\'82\'ea\'82\'dc\'82\'b7\'81\'42\'82\'bb\'82\'cc\'8c\'e3\'81\'41\'91\'49\'91\'f0\'82\'b5\'82\'bd\'97\'9a\'97\'f0\'82\'cd\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'8d\'c5\'8f\'e3\'95\'94\'82\'c9\'88\'da\'93\'ae\'82\'b3\'82\'ea\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'90\'dd\'92\'e8 -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'83\'70\'83\'6c\'83\'8b\'82\'c5\'82\'cd\'81\'41\'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'cc\'95\'cf\'8d\'58\'82\'e2\'81\'41\'8b\'4c\'98\'5e\'82\'b7\'82\'e9\'97\'9a\'97\'f0\'82\'cc\'90\'94\'82\'cc\'90\'dd\'92\'e8\'81\'41\'91\'ce\'89\'9e\'82\'b7\'82\'e9\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'8c\'60\'8e\'ae\'82\'cc\'91\'49\'91\'f0\'82\'c8\'82\'c7\'82\'f0\'8d\'73\'82\'a6\'82\'dc\'82\'b7\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67 -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \'82\'e6\'82\'ad\'8e\'67\'82\'a4\'92\'e8\'8c\'5e\'95\'b6\'82\'cd\'81\'41\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'c6\'82\'b5\'82\'c4\'93\'6f\'98\'5e\'82\'b5\'82\'c4\'82\'a8\'82\'ad\'82\'c6\'95\'d6\'97\'98\'82\'c5\'82\'b7\'81\'42\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'cc\'93\'6f\'98\'5e\'82\'cd\'81\'41\'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'82\'cc\'81\'75\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'81\'76\'82\'a9\'82\'e7\'8d\'73\'82\'a6\'82\'dc\'82\'b7\'81\'42\ -\ -\'93\'6f\'98\'5e\'82\'b5\'82\'bd\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'cd\'81\'41ClipMenu\'82\'cc\'97\'9a\'97\'f0\'82\'cc\'8f\'e3\'82\'a9\'89\'ba\'81\'69\'90\'dd\'92\'e8\'82\'c9\'82\'e6\'82\'e8\'95\'cf\'8d\'58\'89\'c2\'94\'5c\'81\'6a\'82\'c9\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'dc\'82\'b7\'81\'42\ -\ -\'82\'dc\'82\'bd\'81\'41\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'be\'82\'af\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'81\'75\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'83\'81\'83\'6a\'83\'85\'81\'5b\'81\'76\'82\'e0\'82\'b2\'97\'98\'97\'70\'82\'a2\'82\'bd\'82\'be\'82\'af\'82\'dc\'82\'b7\'81\'42\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'8c\'c4\'82\'d1\'8f\'6f\'82\'b7\'82\'bd\'82\'df\'82\'cc\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'cd\'81\'41" -\b Command + Shift + B -\b0 "\'82\'c5\'82\'b7\'81\'42\'82\'b1\'82\'bf\'82\'e7\'82\'cc\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'e0\'81\'41\'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'82\'a9\'82\'e7\'8e\'a9\'97\'52\'82\'c9\'95\'cf\'8d\'58\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42 -\f5 \cf3 \ul \ulc3 \CocoaLigature0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f3 \cf0 \ulnone \CocoaLigature1 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93 -\b0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \'83\'81\'83\'6a\'83\'85\'81\'5b\'8d\'80\'96\'da\'8f\'e3\'82\'c5\'83\'7d\'83\'45\'83\'58\'82\'cc " -\b \'89\'45\'83\'4e\'83\'8a\'83\'62\'83\'4e -\b0 " \'82\'e2 " -\b Control + \'83\'4e\'83\'8a\'83\'62\'83\'4e -\b0 " \'82\'f0\'82\'b7\'82\'e9\'82\'a9\'81\'41 " -\b Control + Enter -\b0 " \'82\'f0\'93\'fc\'97\'cd\'82\'b7\'82\'e9\'82\'b1\'82\'c6\'82\'c5\'81\'41\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'82\'b1\'82\'c6\'82\'aa\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'a9\'82\'e7\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'91\'49\'82\'f1\'82\'c5\'81\'41\'82\'bb\'82\'cc\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'97\'9a\'97\'f0\'82\'c9\'91\'ce\'82\'b5\'82\'c4\'97\'6c\'81\'58\'82\'c8\'8f\'88\'97\'9d\'82\'f0\'8d\'73\'82\'a6\'82\'dc\'82\'b7\'81\'42\ -\ -\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'c9\'82\'cd\'93\'f1\'82\'c2\'82\'cc\'8e\'ed\'97\'de\'82\'aa\'82\'a0\'82\'e8\'82\'dc\'82\'b7\'81\'42\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\cf0 \ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls2\ilvl0 -\b \cf4 {\listtext 1. }\'93\'e0\'91\'a0\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93 -\f1 \uc0\u8232 -\f3\b0 \cf0 \'91\'49\'91\'f0\'82\'b5\'82\'bd\'8d\'80\'96\'da\'82\'cc\'8d\'ed\'8f\'9c\'82\'c8\'82\'c7\'82\'f0\'8d\'73\'82\'a6\'82\'dc\'82\'b7\'81\'42\'83\'86\'81\'5b\'83\'55\'81\'5b\'82\'c9\'82\'e6\'82\'e9\'8a\'67\'92\'a3\'82\'cd\'82\'c5\'82\'ab\'82\'dc\'82\'b9\'82\'f1\'81\'42 -\f1 \uc0\u8232 -\f3 \ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls2\ilvl0 -\b \cf0 {\listtext 2. }\cf4 JavaScript\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93 -\f1 \uc0\u8232 -\f3\b0 \cf0 \'91\'49\'91\'f0\'82\'b5\'82\'bd\'83\'65\'83\'4c\'83\'58\'83\'67\'8c\'60\'8e\'ae\'82\'cc\'97\'9a\'97\'f0\'82\'c9\'91\'ce\'82\'b5\'82\'c4\'81\'41\'95\'b6\'8e\'9a\'97\'f1\'89\'c1\'8d\'48\'82\'f0\'8e\'7b\'82\'b7\'82\'b1\'82\'c6\'82\'aa\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\'8e\'c0\'8d\'73\'83\'47\'83\'93\'83\'57\'83\'93\'82\'c9\'82\'cd\'81\'41\'8d\'4c\'82\'ad\'95\'81\'8b\'79\'82\'b5\'82\'c4\'82\'a2\'82\'e9\'83\'58\'83\'4e\'83\'8a\'83\'76\'83\'67\'8c\'be\'8c\'ea\'81\'41JavaScript\'82\'f0\'97\'98\'97\'70\'82\'b5\'82\'c4\'82\'a2\'82\'dc\'82\'b7\'81\'42\'82\'bb\'82\'cc\'82\'bd\'82\'df\'81\'41\'83\'86\'81\'5b\'83\'55\'81\'5b\'8e\'a9\'90\'67\'82\'cc\'8e\'e8\'82\'c9\'82\'e6\'82\'e8\'81\'41\'8e\'a9\'97\'52\'82\'c9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'82\'b5\'82\'c4\'8e\'67\'97\'70\'82\'b7\'82\'e9\'82\'b1\'82\'c6\'82\'aa\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42 -\f1 \uc0\u8232 \u8232 -\f3 \'97\'e1\'81\'6a\ -\pard\tx940\tx1440\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li1440\fi-1440\ql\qnatural\pardirnatural -\ls2\ilvl1\cf0 {\listtext \uc0\u9642 }\'83\'41\'83\'8b\'83\'74\'83\'40\'83\'78\'83\'62\'83\'67\'82\'cc\'91\'e5\'95\'b6\'8e\'9a\'81\'5e\'8f\'ac\'95\'b6\'8e\'9a\'82\'f0\'95\'cf\'8a\'b7\ -{\listtext \uc0\u9642 }\'94\'bc\'8a\'70\'89\'70\'90\'94\'8e\'9a\'82\'c6\'91\'53\'8a\'70\'89\'70\'90\'94\'8e\'9a\'82\'cc\'91\'8a\'8c\'dd\'95\'cf\'8a\'b7\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls3\ilvl0\cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'93\'ae\'8d\'ec\'90\'e0\'96\'be\'82\'cd\'81\'41\'83\'77\'83\'8b\'83\'76\'83\'79\'81\'5b\'83\'57\'82\'f0\'82\'b2\'97\'97\'89\'ba\'82\'b3\'82\'a2\'81\'42\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls4\ilvl0\cf0 {\listtext \uc0\u9642 }{\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/ja/help/builtin-action"}}{\fldrslt \'93\'e0\'91\'a0\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93}}\ -{\listtext \uc0\u9642 }{\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/ja/help/javascript-action"}}{\fldrslt JavaScript\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93}}\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls5\ilvl0\cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 JavaScript\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'8f\'91\'82\'ab\'95\'fb\'82\'cd\'81\'41\'93\'af\'8d\'ab\'82\'cc\'95\'b6\'8f\'91\'81\'77JavaScript\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'8f\'91\'82\'ab\'95\'fb.txt\'81\'78\'82\'f0\'82\'b2\'8e\'51\'8f\'c6\'82\'ad\'82\'be\'82\'b3\'82\'a2\'81\'42\ -\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf2 \'83\'7a\'81\'5b\'83\'80\'83\'79\'81\'5b\'83\'57 -\f2\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 URL: {\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/"}}{\fldrslt \cf5 http://www.clipmenu.com/}}\ -Twitter: {\field{\*\fldinst{HYPERLINK "http://twitter.com/clipmenu"}}{\fldrslt \cf5 http://twitter.com/clipmenu}}\ -\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\b\fs28 \cf2 \'83\'89\'83\'43\'83\'5a\'83\'93\'83\'58 -\f2\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f3 \cf0 \'96\'7b\'83\'76\'83\'8d\'83\'4f\'83\'89\'83\'80\'82\'cd\'83\'74\'83\'8a\'81\'5b\'83\'45\'83\'46\'83\'41\'82\'c5\'82\'b7\'81\'42\'96\'b3\'8f\'9e\'82\'c5\'8e\'67\'97\'70\'82\'b7\'82\'e9\'82\'b1\'82\'c6\'82\'aa\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\ -\'96\'7b\'83\'76\'83\'8d\'83\'4f\'83\'89\'83\'80\'82\'cc\'94\'7a\'95\'7a\'95\'a8\'82\'c9\'95\'cf\'8d\'58\'82\'f0\'89\'c1\'82\'a6\'82\'c8\'82\'a2\'8c\'c0\'82\'e8\'81\'41\'8e\'a9\'97\'52\'82\'c9\'8d\'c4\'94\'7a\'95\'7a\'82\'c5\'82\'ab\'82\'dc\'82\'b7\'81\'42\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f2\b \cf0 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\fs28 \cf2 \'98\'41\'97\'8d\'90\'e6 -\f2\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\b0 \cf0 Name: Naotaka Morimoto\ -E-mail: \cf5 webmaster@naotaka.com\cf0 \ -Twitter: {\field{\*\fldinst{HYPERLINK "http://twitter.com/naotakaM"}}{\fldrslt \cf5 http://twitter.com/naotakaM}}\ -URL: {\field{\*\fldinst{HYPERLINK "http://www.naotaka.com/"}}{\fldrslt \cf5 http://www.naotaka.com/}}\cf5 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf5 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f3 \cf0 \'81\'a6 \'8f\'91\'90\'d0\'81\'45\'8e\'47\'8e\'8f\'93\'99\'82\'d6\'82\'cc\'8c\'66\'8d\'da\'82\'e2\'81\'41\'8b\'4c\'98\'5e\'94\'7d\'91\'cc\'81\'69CD-ROM / DVD-ROM\'82\'c8\'82\'c7\'81\'6a\'82\'d6\'82\'cc\'8e\'fb\'98\'5e\'82\'c9\'81\'41\'8d\'ec\'8e\'d2\'82\'cc\'8b\'96\'89\'c2\'82\'cd\'95\'4b\'97\'76\'82\'a0\'82\'e8\'82\'dc\'82\'b9\'82\'f1\'81\'42\'8f\'e3\'8f\'71\'82\'cc\'81\'75\'83\'89\'83\'43\'83\'5a\'83\'93\'83\'58\'81\'76\'82\'c9\'94\'bd\'82\'b5\'82\'c8\'82\'a2\'8c\'c0\'82\'e8\'81\'41\'82\'b2\'8e\'a9\'97\'52\'82\'c9\'83\'8a\'83\'93\'83\'4e\'81\'41\'8d\'c4\'94\'7a\'95\'7a\'93\'99\'82\'f0\'8d\'73\'82\'c1\'82\'c4\'82\'ad\'82\'be\'82\'b3\'82\'a2\'81\'42\ -\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural - -\f2 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3\b\fs28 \cf2 \'92\'98\'8d\'ec\'8c\'a0\'95\'5c\'8e\'a6 -\f2 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f3\b0\fs24 \cf0 \'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93 ( -\f6 ClipMenu.icns, StatusMenuIcon.png, StatusMenuIcon_pressed.png)\ - -\f3 http://www.max.hi-ho.ne.jp/painter/\ -Copyright (c) 2008 K2DesignWorks. All rights reserved.\ -\ -\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93 ( -\f6 StatusMenuIconByDaveUlrich*.png)\ - -\f3 http://daveulrich.net/\ -Copyright (c) 2009 Dave Ulrich. All rights reserved.\ -\ -PTHotKey\ -http://www.rogueamoeba.com/utm/posts/Random/Homegrown_Developer_Tools-2004-07-14-12-00\ -Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.\ -\ -Shortcut Recorder\ -http://code.google.com/p/shortcutrecorder/\ -Copyright (c) 2006, contributors to ShortcutRecorder. (See the contributors listed in detail later in the file, or see .) All rights reserved.\ -\ -Sparkle\ -http://sparkle.andymatuschak.org/\ -Copyright (c) 2006 Andy Matuschak\ -\ -DBPrefsWindowController\ -http://www.mere-mortal-software.com/blog/sourcecode.php\ -Created by Dave Batton\ -Copyright 2007. Some rights reserved.\ -This work is licensed under a Creative Commons license:\ -http://creativecommons.org/licenses/by/3.0/\ -\ -Google Toolbox for Mac\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural -\cf0 http://code.google.com/p/google-toolbox-for-mac/\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 Copyright 2007-2008 Google Inc.\ -Licensed under the Apache License, Version 2.0 (the "License"); you may not\ -use this file except in compliance with the License. You may obtain a copy\ -of the License at\ -http://www.apache.org/licenses/LICENSE-2.0\ -Unless required by applicable law or agreed to in writing, software\ -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\ -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\ -License for the specific language governing permissions and limitations under\ -the License.\ -\ -inflection-js\ -http://code.google.com/p/inflection-js/\ -Copyright (c) 2007 Ryan Schuft (ryan.schuft@gmail.com)\ -\ -fhconvert.js\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural -\cf0 http://distraid.co.jp/demo/js_codeconv.html\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 copyright (c) 2008 distraid Inc. \ -This script is freely distributable under the terms of an MIT-style license.\ -\pard\pardeftab720\ql\qnatural -\cf0 \ -showdown.js\ -http://attacklab.net/showdown/\ -Copyright (c) 2007, John Fraser \ - \ -All rights reserved.\ -Original Markdown copyright (c) 2004, John Gruber \ - \ -All rights reserved.\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 \ -v8cgi\ -http://code.google.com/p/v8cgi/\ -\pard\pardeftab720\ql\qnatural -\cf0 Ond\uc0\u345 ej \u381 \u225 ra (ondras@zarovi.cz)\ -\ -JS-methods\ -http://js-methods.googlecode.com/\ -Copyright (c) 2007 Harald Hanek (http://js-methods.googlecode.com)\ -Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)\ -and GPL (http://www.gnu.org/licenses/gpl.html) licenses.\ -\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls6\ilvl0\cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf2 \'8e\'d3\'8e\'ab -\b0\fs24 \cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls7\ilvl0\cf0 {\listtext \uc0\u9642 }ClipMenu\'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'81\'41K2DesignWorks\'82\'ccK2\'82\'b3\'82\'f1\'82\'c9\'92\'f1\'8b\'9f\'82\'b5\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93\'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'81\'41Dave Ulrich\'82\'b3\'82\'f1\'82\'c9\'92\'f1\'8b\'9f\'82\'b5\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'90\'dd\'92\'e8\'82\'cc\'82\'bd\'82\'df\'82\'c9\'81\'41Shortcut Recorder\'83\'74\'83\'8c\'81\'5b\'83\'80\'83\'8f\'81\'5b\'83\'4e\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'90\'dd\'92\'e8\'82\'cc\'82\'bd\'82\'df\'82\'c9\'81\'41Rogue Amoeba Software\'8e\'d0\'82\'cc -\f0 PTHotKey -\f3 \'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'8e\'a9\'93\'ae\'8d\'58\'90\'56\'8b\'40\'94\'5c\'82\'cc\'82\'bd\'82\'df\'82\'c9\'81\'41Andy Matuschak\'8e\'81\'82\'ccSparkle\'83\'74\'83\'8c\'81\'5b\'83\'80\'83\'8f\'81\'5b\'83\'4e\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'83\'45\'83\'42\'83\'93\'83\'68\'83\'45\'8d\'ec\'90\'ac\'82\'c9\'81\'41Dave Batton\'8e\'81\'82\'ccDBPrefsWindowController\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'83\'8d\'83\'4f\'83\'43\'83\'93\'8d\'80\'96\'da\'82\'d6\'82\'cc\'93\'6f\'98\'5e\'82\'c9\'81\'41Google\'8e\'d0\'82\'ccGoogle Toolbox for Mac\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }\'97\'9a\'97\'f0\'82\'cc\'8a\'c7\'97\'9d\'82\'e2\'81\'41Pasteboard Server\'82\'cc\'8a\'c4\'8e\'8b\'8a\'d4\'8a\'75\'82\'c9\'81\'41Coleman Nitroy\'8e\'81\'82\'cc -\f0 Clipper -\f3 \'82\'f0\'8e\'51\'8d\'6c\'82\'c9\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -{\listtext \uc0\u9642 }v0.2.1\'82\'dc\'82\'c5\'82\'cc\'93\'fa\'96\'7b\'8c\'ea\'83\'8a\'83\'5c\'81\'5b\'83\'58\'82\'cc\'8d\'ec\'90\'ac\'82\'c9\'81\'41\'8a\'d6\'8d\'aa\'89\'84\'93\'c4\'8e\'81\'82\'cciLingual\'82\'f0\'8e\'67\'97\'70\'82\'b3\'82\'b9\'82\'c4\'82\'a2\'82\'bd\'82\'be\'82\'ab\'82\'dc\'82\'b5\'82\'bd\'81\'42\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 \ -ClipMenu\'82\'f0\'8d\'ec\'82\'eb\'82\'a4\'82\'c6\'8e\'76\'82\'c1\'82\'bd\'93\'ae\'8b\'40\'82\'cc\'88\'ea\'82\'c2\'82\'aa\'81\'41\'81\'75CLCL\'82\'cc\'82\'e6\'82\'a4\'82\'c8\'83\'5c\'83\'74\'83\'67\'82\'aa\'97\'7e\'82\'b5\'82\'a2\'81\'76\'82\'c5\'82\'b5\'82\'bd\'81\'42CLCL\'82\'cd\'81\'41Windows\'82\'f0\'8e\'67\'82\'a4\'8f\'e3\'82\'c5\'82\'cd\'8c\'87\'82\'a9\'82\'b9\'82\'c8\'82\'a2\'81\'41\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'8a\'c7\'97\'9d\'83\'5c\'83\'74\'83\'67\'82\'c5\'82\'b7\'81\'42\'82\'b1\'82\'cc\'91\'66\'90\'b0\'82\'e7\'82\'b5\'82\'a2\'83\'5c\'83\'74\'83\'67\'83\'45\'83\'46\'83\'41\'82\'f0\'8c\'f6\'8a\'4a\'82\'b5\'82\'c4\'82\'ad\'82\'be\'82\'b3\'82\'c1\'82\'c4\'82\'a2\'82\'e9\'81\'41\'8d\'ec\'8e\'d2\'82\'ccNakashima Tomoaki\'8e\'81\'82\'c9\'89\'fc\'82\'df\'82\'c4\'8a\'b4\'8e\'d3\'82\'a2\'82\'bd\'82\'b5\'82\'dc\'82\'b7\'81\'42 -\f2 \cf5 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3 \cf0 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf2 \'8d\'58\'90\'56\'97\'9a\'97\'f0\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\fs24 \cf0 0.4.3 -\b0 (2009/11/9) -\f1 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3 \cf0 fixed:\ - - v0.4.2\'82\'c5\'81\'41\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'aa\'95\'d2\'8f\'57\'82\'c5\'82\'ab\'82\'c8\'82\'a2\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 0.4.2 -\b0 (2009/11/8) -\f1 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f3 \cf0 new:\ - - \'8e\'77\'92\'e8\'82\'b5\'82\'bd\'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93\'82\'f0\'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'82\'cc\'8a\'c4\'8e\'8b\'91\'ce\'8f\'db\'82\'a9\'82\'e7\'8a\'4f\'82\'b7\'82\'bd\'82\'df\'82\'cc\'81\'41\'8f\'9c\'8a\'4f\'83\'41\'83\'76\'83\'8a\'83\'50\'81\'5b\'83\'56\'83\'87\'83\'93\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'97\'9a\'97\'f0\'82\'f0\'81\'41\'83\'65\'83\'4c\'83\'58\'83\'67\'83\'74\'83\'40\'83\'43\'83\'8b\'82\'c6\'82\'b5\'82\'c4\'8f\'91\'82\'ab\'8f\'6f\'82\'b7\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'76\'83\'8c\'83\'8a\'83\'8a\'81\'5b\'83\'58\'94\'c5\'82\'cc\'8e\'a9\'93\'ae\'83\'41\'83\'62\'83\'76\'83\'66\'81\'5b\'83\'67\'82\'c9\'91\'ce\'89\'9e\'81\'42\ - changed:\ - - \'97\'9a\'97\'f0\'82\'cc\'8a\'c7\'97\'9d\'95\'fb\'8e\'ae\'82\'f0\'95\'cf\'8d\'58\'81\'42\ - - \'97\'9a\'97\'f0\'82\'cc\'8f\'64\'95\'a1\'83\'60\'83\'46\'83\'62\'83\'4e\'82\'cc\'95\'fb\'96\'40\'82\'f0\'95\'cf\'8d\'58\'81\'42\ - - \'97\'9a\'97\'f0\'82\'cc\'83\'5c\'81\'5b\'83\'67\'8f\'87\'82\'cc\'90\'dd\'92\'e8\'95\'fb\'96\'40\'82\'f0\'95\'cf\'8d\'58\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'cc\'89\'e6\'91\'9c\'95\'5c\'8e\'a6\'95\'fb\'96\'40\'82\'f0\'95\'cf\'8d\'58\'81\'42\ - - \'8b\'4e\'93\'ae\'8e\'9e\'82\'cc\'8f\'89\'8a\'fa\'89\'bb\'95\'fb\'96\'40\'82\'f0\'95\'cf\'8d\'58\'81\'42\ - fixed:\ - - \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'82\'c9\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'95\'5c\'8e\'a6\'82\'b5\'82\'c8\'82\'a2\'90\'dd\'92\'e8\'82\'c9\'82\'b5\'82\'c4\'82\'a2\'82\'c4\'82\'e0\'81\'41\'8b\'4e\'93\'ae\'8e\'9e\'82\'c9\'94\'bd\'89\'66\'82\'b3\'82\'ea\'82\'c8\'82\'a2\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 0.4.1 -\b0 (2009/10/21) -\f1 \ - -\f3 fixed:\ - - \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'82\'c5\'83\'49\'83\'74\'82\'c9\'82\'b5\'82\'c4\'82\'a2\'82\'c4\'82\'e0\'83\'79\'81\'5b\'83\'58\'83\'67\'82\'b5\'82\'c4\'82\'b5\'82\'dc\'82\'a4\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\ - -\b 0.4.0 -\b0 (2009/10/20) -\f1 \ - -\f3 new:\ - - 64\'83\'72\'83\'62\'83\'67\'83\'82\'81\'5b\'83\'68\'82\'c9\'91\'ce\'89\'9e\'81\'42\ - - \'97\'9a\'97\'f0\'82\'cc\'8e\'a9\'93\'ae\'95\'db\'91\'b6\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - Sparkle\'83\'74\'83\'8c\'81\'5b\'83\'80\'83\'8f\'81\'5b\'83\'4e\'82\'c9\'82\'e6\'82\'e9\'81\'41\'8e\'a9\'93\'ae\'83\'41\'83\'62\'83\'76\'83\'66\'81\'5b\'83\'67\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'8d\'83\'4f\'83\'43\'83\'93\'8d\'80\'96\'da\'82\'c9\'92\'c7\'89\'c1\'82\'b7\'82\'e9\'82\'a9\'96\'e2\'82\'a2\'8d\'87\'82\'ed\'82\'b9\'82\'e9\'83\'5f\'83\'43\'83\'41\'83\'8d\'81\'5b\'83\'4f\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'97\'9a\'97\'f0\'82\'cc\'8f\'87\'8f\'98\'82\'f0\'95\'cf\'8d\'58\'82\'b7\'82\'e9\'82\'a9\'90\'dd\'92\'e8\'82\'c5\'82\'ab\'82\'e9\'83\'49\'83\'76\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93\'8f\'e3\'82\'cc\'83\'63\'81\'5b\'83\'8b\'83\'60\'83\'62\'83\'76\'82\'c9\'81\'41\'83\'6f\'81\'5b\'83\'57\'83\'87\'83\'93\'94\'d4\'8d\'86\'82\'f0\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'82\'e6\'82\'a4\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - changed:\ - - \'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'cc\'91\'67\'82\'dd\'8d\'87\'82\'ed\'82\'b9\'82\'f0\'95\'cf\'8d\'58\'81\'69command-shift-v\'81\'6a\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'cc\'83\'74\'83\'48\'83\'8b\'83\'5f\'8d\'80\'96\'da\'82\'c9\'83\'7d\'83\'45\'83\'58\'83\'49\'81\'5b\'83\'6f\'81\'5b\'82\'b7\'82\'e9\'82\'c6\'81\'41\'8a\'4a\'82\'a2\'82\'bd\'8f\'f3\'91\'d4\'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'82\'c9\'95\'cf\'89\'bb\'82\'b7\'82\'e9\'82\'e6\'82\'a4\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'91\'49\'91\'f0\'89\'c2\'94\'5c\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'81\'45\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'69Dave Ulrich\'8e\'81\'8d\'ec\'81\'6a\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'81\'75\'8f\'49\'97\'b9\'81\'76\'82\'f0\'81\'75ClipMenu\'82\'f0\'8f\'49\'97\'b9\'81\'76\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'81\'75\'97\'9a\'97\'f0\'82\'f0\'83\'4e\'83\'8a\'83\'41\'81\'76\'82\'c5\'8c\'bb\'82\'ea\'82\'e9\'83\'5f\'83\'43\'83\'41\'83\'8d\'81\'5b\'83\'4f\'82\'c9\'81\'41\'83\'5f\'83\'43\'83\'41\'83\'8d\'81\'5b\'83\'4f\'82\'f0\'95\'5c\'8e\'a6\'82\'b5\'82\'c8\'82\'a2\'82\'e6\'82\'a4\'82\'c9\'90\'dd\'92\'e8\'82\'c5\'82\'ab\'82\'e9\'83\'60\'83\'46\'83\'62\'83\'4e\'83\'7b\'83\'62\'83\'4e\'83\'58\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'8b\'4e\'93\'ae\'8e\'9e\'82\'cc\'8f\'88\'97\'9d\'82\'f0\'83\'7d\'83\'8b\'83\'60\'83\'58\'83\'8c\'83\'62\'83\'68\'89\'bb\'81\'42\ - - Shortcut Recorder\'83\'74\'83\'8c\'81\'5b\'83\'80\'83\'8f\'81\'5b\'83\'4e\'82\'f0\'83\'41\'83\'62\'83\'76\'83\'66\'81\'5b\'83\'67\'81\'42\ - fixed:\ - - \'97\'9a\'97\'f0\'82\'cc\'8d\'c5\'91\'e5\'92\'6c\'82\'f0\'8c\'b8\'8f\'ad\'82\'b3\'82\'b9\'82\'c4\'82\'e0\'81\'41\'82\'b7\'82\'ae\'82\'c9\'94\'bd\'89\'66\'82\'b3\'82\'ea\'82\'c8\'82\'a2\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ - - \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'82\'cc\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'93\'6f\'98\'5e\'89\'e6\'96\'ca\'82\'c5\'81\'41\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'96\'bc\'82\'aa\'92\'b7\'82\'b7\'82\'ac\'82\'e9\'82\'c6\'81\'41\'95\'5c\'8e\'a6\'82\'aa\'93\'72\'90\'d8\'82\'ea\'82\'c4\'82\'b5\'82\'dc\'82\'a4\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\ql\qnatural -\ls8\ilvl1 -\b \cf0 0.3.5 -\b0 (2009/6/17) -\f1 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\ql\qnatural -\ls9\ilvl1\cf0 new:\ - - -\f6 \'81\'75\'83\'74\'83\'40\'83\'43\'83\'8b\'83\'70\'83\'58\'82\'c6\'82\'b5\'82\'c4\'83\'79\'81\'5b\'83\'58\'83\'67\'81\'76\'82\'f0\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'c9\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - -\f6 \'81\'75 -\f1 HFS -\f6 \'83\'74\'83\'40\'83\'43\'83\'8b\'83\'70\'83\'58\'82\'c6\'82\'b5\'82\'c4\'83\'79\'81\'5b\'83\'58\'83\'67\'81\'76\'82\'f0\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'c9\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - -\f6 \'82\'d0\'82\'e7\'82\'aa\'82\'c8 -\f1 / -\f6 \'83\'4a\'83\'5e\'83\'4a\'83\'69\'82\'f0\'91\'8a\'8c\'dd\'95\'cf\'8a\'b7\'82\'b7\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - -\f6 \'91\'53\'8a\'70 -\f1 / -\f6 \'94\'bc\'8a\'70\'83\'4a\'83\'5e\'83\'4a\'83\'69\'82\'f0\'91\'8a\'8c\'dd\'95\'cf\'8a\'b7\'82\'b7\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - -\f6 \'95\'b6\'8e\'9a\'97\'f1\'82\'f0\'8e\'77\'92\'e8\'82\'b5\'82\'bd\'8a\'87\'8c\'ca\'82\'c5\'88\'cd\'82\'f1\'82\'be\'82\'e8\'81\'41\'95\'73\'97\'76\'82\'c8\'8b\'f3\'94\'92\'82\'f0\'8d\'ed\'8f\'9c\'82\'b7\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - Markdown -\f6 \'8c\'60\'8e\'ae\'82\'c9\'95\'cf\'8a\'b7\'81\'41 -\f1 URI -\f6 \'83\'52\'83\'93\'83\'7c\'81\'5b\'83\'6c\'83\'93\'83\'67\'82\'cc\'83\'47\'83\'93\'83\'52\'81\'5b\'83\'68 -\f1 / -\f6 \'83\'66\'83\'52\'81\'5b\'83\'68\'81\'41 -\f1 HTML -\f6 \'95\'b6\'8e\'9a\'8e\'c0\'91\'cc\'8e\'51\'8f\'c6\'82\'cc\'83\'47\'83\'58\'83\'50\'81\'5b\'83\'76 -\f1 / -\f6 \'83\'41\'83\'93\'83\'47\'83\'58\'83\'50\'81\'5b\'83\'76\'81\'41 -\f1 HTML -\f6 \'83\'5e\'83\'4f\'82\'c5\'88\'cd\'82\'de\'81\'41 -\f1 HTML -\f6 \'83\'5e\'83\'4f\'82\'f0\'8d\'ed\'8f\'9c\'82\'b7\'82\'e9\'81\'41 -\f1 10 -\f6 \'90\'69\'90\'94\'92\'6c\'8e\'51\'8f\'c6\'82\'c9\'95\'cf\'8a\'b7\'82\'b7\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - MD5/SHA-1/Base64 -\f6 \'82\'c9\'95\'cf\'8a\'b7\'82\'b7\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - JavaScript -\f6 \'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a\'82\'cc\'81\'41 -\f1 fhconvert.js -\f6 \'81\'41 -\f1 showdown.js -\f6 \'81\'41 -\f1 v8cgi -\f6 \'81\'41 -\f1 JS-methods -\f6 \'82\'f0\'93\'af\'8d\'ab\'81\'42 -\f1 \ - - JavaScript -\f6 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'91\'67\'82\'dd\'8d\'9e\'82\'dd\'83\'81\'83\'5c\'83\'62\'83\'68\'82\'c9\'81\'41 -\f1 activate() -\f6 \'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - - -\f6 \'83\'63\'81\'5b\'83\'8b\'83\'60\'83\'62\'83\'76\'82\'c9\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'95\'b6\'8e\'9a\'97\'f1\'82\'cc\'8d\'c5\'91\'e5\'92\'6c\'82\'f0\'8e\'77\'92\'e8\'82\'b7\'82\'e9\'90\'dd\'92\'e8\'8d\'80\'96\'da\'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - changed:\ - - -\f6 \'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'c9\'91\'ce\'82\'b5\'82\'c4\'82\'e0\'81\'41\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'93\'4b\'97\'70\'89\'c2\'94\'5c\'82\'c9\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'90\'56\'8b\'4b\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'8d\'ec\'90\'ac\'82\'cc\'8d\'db\'82\'c9\'81\'41\'93\'fc\'97\'cd\'82\'b3\'82\'ea\'82\'bd\'82\'cc\'82\'aa\'83\'5e\'83\'43\'83\'67\'83\'8b\'82\'be\'82\'af\'82\'c5\'93\'e0\'97\'65\'82\'aa\'8b\'f3\'82\'cc\'8f\'ea\'8d\'87\'81\'41\'8e\'a9\'93\'ae\'93\'49\'82\'c9\'83\'5e\'83\'43\'83\'67\'83\'8b\'82\'cc\'95\'b6\'8e\'9a\'97\'f1\'82\'f0\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'cc\'93\'e0\'97\'65\'82\'c6\'82\'b5\'82\'c4\'83\'52\'83\'73\'81\'5b\'82\'b7\'82\'e9\'82\'e6\'82\'a4\'82\'c9\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'97\'9a\'97\'f0\'82\'cc\'8f\'64\'95\'a1\'83\'60\'83\'46\'83\'62\'83\'4e\'95\'fb\'96\'40\'82\'f0\'81\'41\'8e\'e1\'8a\'b1\'82\'cc\'8c\'f8\'97\'a6\'89\'bb\'81\'42 -\f1 \ - - -\f6 \'93\'6f\'98\'5e\'82\'b5\'82\'bd\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'95\'db\'91\'b6\'8c\'60\'8e\'ae\'82\'f0\'81\'41 -\f1 Property List -\f6 \'8c\'60\'8e\'ae\'82\'c9\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'83\'66\'83\'74\'83\'48\'83\'8b\'83\'67\'82\'c5\'93\'6f\'98\'5e\'82\'b3\'82\'ea\'82\'e9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'93\'af\'8d\'ab\'82\'b7\'82\'e9 -\f1 JavaScript -\f6 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'93\'c7\'82\'dd\'8d\'9e\'82\'dd\'95\'fb\'96\'40\'82\'f0\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'93\'af\'8d\'ab\'82\'b7\'82\'e9\'93\'fa\'96\'7b\'8c\'ea\'95\'b6\'8e\'9a\'97\'f1\'95\'cf\'8a\'b7\'97\'70\'82\'cc -\f1 JavaScript -\f6 \'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a\'82\'f0\'81\'41 -\f1 z2h_word.js -\f6 \'82\'a9\'82\'e7 -\f1 fhconvert.js -\f6 \'82\'c9\'95\'cf\'8d\'58\'81\'42 -\f1 \ - - -\f6 \'93\'af\'8d\'ab\'82\'b7\'82\'e9 -\f1 JavaScript -\f6 \'83\'89\'83\'43\'83\'75\'83\'89\'83\'8a\'82\'cc -\f1 inflection.js -\f6 \'82\'f0\'81\'41\'8d\'c5\'90\'56\'94\'c5\'82\'c9\'8d\'58\'90\'56\'81\'42 -\f1 \ - - JavaScript -\f6 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'93\'fa\'96\'7b\'8c\'ea\'83\'8d\'81\'5b\'83\'4a\'83\'89\'83\'43\'83\'59\'95\'5c\'8e\'a6\'82\'f0\'95\'9c\'8a\'88\'81\'42 -\f1 \ - - -\f6 \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'cc\'83\'86\'81\'5b\'83\'55\'83\'72\'83\'8a\'83\'65\'83\'42\'82\'cc\'8c\'fc\'8f\'e3\'81\'42 -\f1 \ - fixed:\ - - JavaScript -\f6 \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'cc\'83\'47\'83\'89\'81\'5b\'81\'45\'83\'5f\'83\'43\'83\'41\'83\'8d\'81\'5b\'83\'4f\'82\'aa\'81\'41\'8d\'c5\'91\'4f\'96\'ca\'82\'c9\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'c8\'82\'a9\'82\'c1\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42 -\f3 \ -\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\ql\qnatural -\ls10\ilvl1 -\b \cf0 0.3.4 -\b0 (2009/5/24) -\f1 \ - new:\ - - Spaces -\f6 \'82\'c9\'91\'ce\'89\'9e\'81\'42 -\f1 \ - - ClipMenu.com -\f6 \'82\'f0\'8d\'ec\'90\'ac\'81\'42 -\f1 \ - - -\f6 \'89\'70\'95\'b6\'82\'cc -\f1 ReadMe -\f6 \'82\'f0\'92\'c7\'89\'c1\'81\'42 -\f1 \ - changed:\ - - -\f6 \'93\'6f\'98\'5e\'82\'c5\'82\'ab\'82\'e9\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'f0\'92\'c7\'89\'c1\'81\'69 -\f1 Command + Option + V -\f6 \'81\'6a\'81\'42 -\f1 \ - fixed:\ - - -\f6 \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'c5\'81\'41\'83\'74\'83\'48\'83\'8b\'83\'5f\'93\'e0\'82\'c5\'8d\'ed\'8f\'9c\'82\'b5\'82\'bd\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'aa -\f1 Snippets.xml -\f6 \'82\'c9\'8e\'63\'82\'c1\'82\'c4\'82\'b5\'82\'dc\'82\'a4\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42 -\f1 \ - - -\f6 \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'f0\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'c5\'95\'c2\'82\'b6\'82\'e7\'82\'ea\'82\'c8\'82\'a9\'82\'c1\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42 -\f3 \ -\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls10\ilvl0 -\b \cf0 0.3.3 -\b0 (2008/12/6)\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\ql\qnatural -\ls11\ilvl1 -\f1 \cf0 fixed:\ - - XML -\f6 \'83\'74\'83\'40\'83\'43\'83\'8b\'82\'a9\'82\'e7\'93\'c7\'82\'dd\'8d\'9e\'82\'f1\'82\'be\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'aa\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'c9\'8c\'bb\'82\'ea\'82\'c8\'82\'a9\'82\'c1\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42 -\f1 \ - - -\f6 \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'83\'70\'83\'6c\'83\'8b\'82\'c5\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'83\'74\'83\'48\'83\'93\'83\'67\'83\'54\'83\'43\'83\'59\'82\'f0\'95\'cf\'8d\'58\'82\'c5\'82\'ab\'82\'c8\'82\'ad\'82\'c8\'82\'c1\'82\'c4\'82\'a2\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3 -\f1 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls11\ilvl1 -\f3 \cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls12\ilvl0 -\b \cf0 0.3.2 -\b0 (2008/11/26)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls13\ilvl0\cf0 new:\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'8d\'80\'96\'da\'8f\'e3\'82\'c5\'82\'cc\'81\'75\'8f\'43\'8f\'fc\'83\'4c\'81\'5b + \'83\'4e\'83\'8a\'83\'62\'83\'4e\'81\'76\'82\'c9\'81\'41\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'8a\'84\'82\'e8\'93\'96\'82\'c4\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - XML\'8c\'60\'8e\'ae\'82\'c5\'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'82\'f0\'81\'41\'93\'c7\'82\'dd\'8d\'9e\'82\'dd\'81\'5e\'8f\'91\'82\'ab\'8f\'6f\'82\'b5\'82\'b7\'82\'e9\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - changed:\ - - \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'8c\'c4\'82\'d1\'8f\'6f\'82\'b5\'95\'fb\'96\'40\'82\'cc\'8f\'89\'8a\'fa\'90\'dd\'92\'e8\'82\'f0\'81\'41\'81\'75\'89\'45\'83\'4e\'83\'8a\'83\'62\'83\'4e\'81\'76\'81\'41\'81\'75Control + \'83\'4e\'83\'8a\'83\'62\'83\'4e\'81\'76\'81\'41\'81\'75Control + Enter\'81\'76\'82\'cc\'82\'52\'8e\'ed\'97\'de\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'97\'9a\'97\'f0\'90\'94\'82\'cc\'8f\'89\'8a\'fa\'92\'6c\'82\'f0\'81\'4150\'82\'a9\'82\'e720\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - fixed:\ - - \'83\'4c\'81\'5b\'93\'fc\'97\'cd\'82\'c5\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'aa\'83\'7c\'83\'62\'83\'76\'83\'41\'83\'62\'83\'76\'82\'b3\'82\'ea\'82\'c8\'82\'a9\'82\'c1\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ - - \'83\'58\'83\'65\'81\'5b\'83\'5e\'83\'58\'83\'6f\'81\'5b\'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'82\'f0\'94\'f1\'95\'5c\'8e\'a6\'82\'c9\'82\'b7\'82\'e9\'8d\'db\'82\'cc\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls14\ilvl0\cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls15\ilvl0 -\b \cf0 0.3.1 -\b0 (2008/11/12)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls16\ilvl0\cf0 new:\ - - \'93\'6f\'98\'5e\'82\'b5\'82\'bd\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'aa\'88\'ea\'82\'c2\'82\'be\'82\'af\'82\'be\'82\'c1\'82\'bd\'8f\'ea\'8d\'87\'82\'cd\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'f0\'83\'7c\'83\'62\'83\'76\'83\'41\'83\'62\'83\'76\'82\'b9\'82\'b8\'81\'41\'91\'a6\'8d\'c0\'82\'c9\'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'82\'f0\'93\'4b\'97\'70\'82\'c5\'82\'ab\'82\'e9\'90\'dd\'92\'e8\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'63\'81\'5b\'83\'8b\'83\'60\'83\'62\'83\'76\'82\'cc\'95\'5c\'8e\'a6\'81\'5e\'94\'f1\'95\'5c\'8e\'a6\'82\'f0\'91\'49\'91\'f0\'82\'c5\'82\'ab\'82\'e9\'90\'dd\'92\'e8\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - changed:\ - - \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'cc\'90\'dd\'92\'e8\'8d\'80\'96\'da\'82\'cc\'90\'ae\'97\'9d\'81\'42\ - fixed:\ - - PowerPC\'93\'8b\'8d\'da\'82\'ccMac\'82\'c5\'81\'41\'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'aa\'8a\'4a\'82\'af\'82\'c8\'82\'a9\'82\'c1\'82\'bd\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls17\ilvl0\cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls18\ilvl0 -\b \cf0 0.3 -\b0 (2008/11/09)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls19\ilvl0\cf0 new:\ - - \'90\'56\'82\'b5\'82\'a2\'83\'41\'83\'43\'83\'52\'83\'93\'81\'69\'90\'bb\'8d\'ec\'81\'45\'92\'98\'8d\'ec\'8c\'a0\'8e\'d2\'81\'46 K2DesignWorks\'82\'ccK2\'82\'b3\'82\'f1\'81\'6a\'82\'f0\'8d\'cc\'97\'70\'81\'42\ - - \'83\'58\'83\'6a\'83\'79\'83\'62\'83\'67\'8b\'40\'94\'5c\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'8d\'83\'4f\'83\'43\'83\'93\'8d\'80\'96\'da\'82\'c9\'81\'41ClipMenu\'82\'f0\'93\'6f\'98\'5e\'82\'b7\'82\'e9\'90\'dd\'92\'e8\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'8f\'49\'97\'b9\'8e\'9e\'82\'c9\'81\'41\'97\'9a\'97\'f0\'82\'f0\'95\'db\'91\'b6\'82\'b7\'82\'e9\'82\'a9\'82\'f0\'95\'cf\'8d\'58\'82\'c5\'82\'ab\'82\'e9\'90\'dd\'92\'e8\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'8d\'80\'96\'da\'82\'cc\'8e\'ed\'97\'de\'82\'f0\'95\'5c\'82\'b7\'83\'89\'83\'78\'83\'8b\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - changed:\ - - \'91\'ce\'89\'9eOS\'82\'f0\'81\'41Mac OS X v10.5\'88\'c8\'8d\'7e\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'d6\'82\'cc\'93\'6f\'98\'5e\'95\'fb\'96\'40\'82\'f0\'88\'ea\'90\'56\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'c9\'83\'43\'83\'93\'83\'89\'83\'43\'83\'93\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'97\'9a\'97\'f0\'90\'94\'82\'f0\'95\'cf\'8d\'58\'89\'c2\'94\'5c\'82\'c9\'81\'42\ - - \'88\'ea\'82\'c2\'82\'cc\'83\'74\'83\'48\'83\'8b\'83\'5f\'82\'c9\'8a\'dc\'82\'de\'97\'9a\'97\'f0\'90\'94\'82\'f0\'95\'cf\'8d\'58\'89\'c2\'94\'5c\'82\'c9\'81\'42\ - - \'83\'4e\'83\'8a\'83\'62\'83\'76\'83\'7b\'81\'5b\'83\'68\'82\'cc\'8e\'ed\'97\'de\'82\'aa\'83\'74\'83\'40\'83\'43\'83\'8b\'96\'bc\'82\'c8\'82\'e7\'81\'41PICT\'89\'e6\'91\'9c\'82\'f0\'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'c9\'95\'5c\'8e\'a6\'82\'b5\'82\'c8\'82\'a2\'82\'e6\'82\'a4\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - - \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'f0\'8d\'c4\'8d\'5c\'90\'ac\'81\'42\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls20\ilvl0 -\b \cf0 0.2.1 -\b0 (2008/03/13)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls21\ilvl0\cf0 changed:\ - - \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'8b\'40\'94\'5c\'82\'cc\'93\'ae\'8d\'ec\'91\'ce\'8f\'dbOS\'82\'f0\'81\'41\'8e\'62\'92\'e8\'93\'49\'82\'c9Mac OS X v10.4.x\'82\'c9\'8c\'c0\'92\'e8\'81\'69Mac OS X v10.5\'8a\'c2\'8b\'ab\'82\'c9\'82\'a8\'82\'a2\'82\'c4\'81\'41\'95\'5c\'8e\'a6\'82\'c9\'96\'e2\'91\'e8\'82\'aa\'90\'b6\'82\'b6\'82\'bd\'82\'bd\'82\'df\'81\'6a\'81\'42\ - fixed:\ - - \'97\'9a\'97\'f0\'83\'4e\'83\'8a\'83\'41\'82\'cc\'8d\'db\'82\'c9\'8b\'4e\'82\'b1\'82\'e9\'95\'73\'8b\'ef\'8d\'87\'82\'f0\'8f\'43\'90\'b3\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'93\'e0\'82\'cc\'83\'41\'83\'43\'83\'52\'83\'93\'95\'5c\'8e\'a6\'82\'cc\'95\'73\'8b\'ef\'8d\'87\'82\'f0\'8f\'43\'90\'b3\'81\'42\ - - \'83\'7a\'83\'62\'83\'67\'83\'4c\'81\'5b\'82\'c5\'8b\'4e\'93\'ae\'82\'b5\'82\'bd\'8d\'db\'82\'c9\'81\'41\'90\'b3\'82\'b5\'82\'a2\'88\'ca\'92\'75\'82\'c9\'95\'5c\'8e\'a6\'82\'b3\'82\'ea\'82\'c8\'82\'a2\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b \cf0 0.2 -\b0 (2008/03/10)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls22\ilvl0\cf0 new:\ - - \'83\'41\'83\'4e\'83\'56\'83\'87\'83\'93\'8b\'40\'94\'5c\'82\'f0\'8e\'c0\'91\'95\'81\'42\ - - \'8a\'c2\'8b\'ab\'90\'dd\'92\'e8\'89\'e6\'96\'ca\'82\'c9\'83\'63\'81\'5b\'83\'8b\'83\'6f\'81\'5b\'82\'f0\'93\'8b\'8d\'da\'81\'42\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'c9\'81\'41\'90\'94\'8e\'9a\'83\'4c\'81\'5b\'82\'cc\'83\'56\'83\'87\'81\'5b\'83\'67\'83\'4a\'83\'62\'83\'67\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - - \'97\'9a\'97\'f0\'82\'f0\'91\'53\'8f\'c1\'8b\'8e\'82\'c5\'82\'ab\'82\'e9\'81\'41\'83\'81\'83\'6a\'83\'85\'81\'5b\'8d\'80\'96\'da\'82\'f0\'92\'c7\'89\'c1\'81\'42\ - changed:\ - - \'93\'ae\'8d\'ec\'91\'ce\'8f\'dbOS\'82\'f0\'81\'41Mac OS X v10.4\'88\'c8\'8d\'7e\'82\'c9\'95\'cf\'8d\'58\'81\'42\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \ - -\b 0.1.1 -\b0 (2008/01/15)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls23\ilvl0\cf0 new:\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'83\'74\'83\'48\'83\'93\'83\'67\'83\'54\'83\'43\'83\'59\'95\'cf\'8d\'58\'82\'c9\'91\'ce\'89\'9e\'81\'42\ - changed:\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'c9\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'95\'b6\'8e\'9a\'97\'f1\'82\'f0\'81\'41\'83\'67\'83\'8a\'83\'80\'82\'b5\'82\'c4\'82\'a9\'82\'e7\'95\'5c\'8e\'a6\'82\'b7\'82\'e9\'82\'e6\'82\'a4\'82\'c9\'95\'cf\'8d\'58\'81\'42\ - fixed:\ - - \'83\'81\'83\'6a\'83\'85\'81\'5b\'82\'cc\'95\'5c\'8e\'a6\'95\'b6\'8e\'9a\'90\'94\'82\'c9\'81\'41\'8f\'ac\'82\'b3\'82\'b7\'82\'ac\'82\'e9\'92\'6c\'82\'f0\'93\'fc\'82\'ea\'82\'bd\'8d\'db\'82\'c9\'81\'41\'90\'b3\'8f\'ed\'82\'c9\'93\'ae\'8d\'ec\'82\'b5\'82\'c8\'82\'a2\'96\'e2\'91\'e8\'82\'f0\'8f\'43\'90\'b3\'81\'42\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \ - -\b 0.1 -\b0 (2008/01/03)\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls24\ilvl0\cf0 new:\ - - \'8d\'c5\'8f\'89\'82\'cc\'83\'8a\'83\'8a\'81\'5b\'83\'58\'81\'42 -\f2 \ -} \ No newline at end of file diff --git a/doc/archive_contents/ReadMe (Japanese).rtfd/ozmCP.tiff b/doc/archive_contents/ReadMe (Japanese).rtfd/ozmCP.tiff deleted file mode 100644 index d0c54f9..0000000 Binary files a/doc/archive_contents/ReadMe (Japanese).rtfd/ozmCP.tiff and /dev/null differ diff --git a/doc/archive_contents/ReadMe.rtfd/TXT.rtf b/doc/archive_contents/ReadMe.rtfd/TXT.rtf deleted file mode 100644 index 3269ff3..0000000 --- a/doc/archive_contents/ReadMe.rtfd/TXT.rtf +++ /dev/null @@ -1,506 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf110 -\readonlydoc1{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 LucidaGrande;\f2\fswiss\fcharset0 ArialMT; -\f3\fnil\fcharset128 HiraKakuPro-W3;\f4\fnil\fcharset0 Monaco;} -{\colortbl;\red255\green255\blue255;\red0\green0\blue128;\red35\green110\blue37;\red51\green51\blue51; -\red0\green0\blue255;\red88\green88\blue88;} -{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid1\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid1} -{\list\listtemplateid2\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid101\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid2} -{\list\listtemplateid3\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid201\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid3} -{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid301\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4} -{\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}\levelprepend{\leveltext\leveltemplateid401\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid5} -{\list\listtemplateid6\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid501\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid6} -{\list\listtemplateid7\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid601\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid602\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid7} -{\list\listtemplateid8\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid701\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid702\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid8} -{\list\listtemplateid9\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid801\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid802\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid9} -{\list\listtemplateid10\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid901\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid902\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid10} -{\list\listtemplateid11\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1001\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1002\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid11} -{\list\listtemplateid12\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid1101\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1102\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid12} -{\list\listtemplateid13\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1202\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid13} -{\list\listtemplateid14\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid1301\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1302\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid14} -{\list\listtemplateid15\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}\levelprepend{\leveltext\leveltemplateid1401\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1402\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid15} -{\list\listtemplateid16\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{circle\}}{\leveltext\leveltemplateid1501\'01\uc0\u9702 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{square\}}{\leveltext\leveltemplateid1502\'01\uc0\u9642 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid16}} -{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}{\listoverride\listid8\listoverridecount0\ls8}{\listoverride\listid9\listoverridecount0\ls9}{\listoverride\listid10\listoverridecount0\ls10}{\listoverride\listid11\listoverridecount0\ls11}{\listoverride\listid12\listoverridecount0\ls12}{\listoverride\listid13\listoverridecount0\ls13}{\listoverride\listid14\listoverridecount0\ls14}{\listoverride\listid15\listoverridecount0\ls15}{\listoverride\listid16\listoverridecount0\ls16}} -\paperw11900\paperh16840\vieww12380\viewh13400\viewkind0 -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\fs24 \cf0 {{\NeXTGraphic ozmCP.tiff \width640 \height640 \noorient -}}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural -\cf0 -\f1\b\fs48 \up6 ClipMenu -\f0\fs24 \up0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b0 \cf0 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs34 \cf2 About ClipMenu -\fs24 \cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\b0\fs26 \cf0 ClipMenu is a multiple clipboard history manager. It can record 8 different types of clipboard types, plain text, rich text, image and so on.\ -\ -Additionally, You can store some text snippets to easily reuse common phrases, Email addresses and so on. -\f3\fs24 \ -\ - -\f2\b\fs28 \up2 Features: -\f3\b0\fs24 \up0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\fs26 \cf0 \'95 Unlimited number of clipboard history.\ - \'95 User definable hot keys.\ - \'95 Showing icons indicate for clipboard type inside menu.\ - \'95 Showing image in menu.\ - \'95 Showing text content as tooltip.\ - \'95 An option to show/hide application icon in the status bar.\ - \'95 Text processing with JavaScript to clipboard history item.\ - \'95 Text snippets. -\f3\fs24 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf0 \up2 System Requirements -\b0\fs24 \up0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\fs26 \cf0 \'95 Mac OS X v10.5 or later.\ - \'95 Mac OS X v10.6 or later for 64-bit support.\ - \'95 ClipMenu is a Universal binary so it will run on Intel and PowerPC Macs. -\f3\fs24 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ - -\f2\b\fs28 \up2 Installation -\b0\fs24 \up0 \ - -\fs26 Place ClipMenu in the Applications folder. -\f3\fs24 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 Uninstallation -\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\fs26 \cf0 Move ClipMenu to Trash.\ -\ -If you want to delete all of data ClipMenu made, move following files to Trash, too.\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \'95 /Users//Library/Preferences/com.naotaka.ClipMenu.plist\ - \'95 /Users//Library/Application Support/ClipMenu -\fs24 \ -\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs34 \cf2 Usage -\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs28 \cf0 \up2 Start -\f3\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\fs26 \cf0 Double-click on the ClipMenu icon to launch it. If it is successfully launched, you could see the application icon on status bar. -\f3\fs24 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 How to show ClipMenu -\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\fs26 \cf0 There are two ways to access ClipMenu items.\ -\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls1\ilvl0\cf0 {\listtext 1. }Access from the status bar. -\f1 \uc0\u8232 -\f2 \ -{\listtext 2. }Access from the pop up menu by using hot key (keyboard shortcut). The menu will appear near the mouse pointer. The default hot key combination is -\b Command-Shift-V -\b0 .\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -Use the appropriate method for your choice. -\f3\fs24 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 Paste history item -\f3\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\fs26 \cf0 Select an clipboard history item you want to paste from the menu.\ -\ -You can navigate through the menu not by mouse but by keyboard. Pressing up/down key move selection vertically, left/right key show or hide sub menu items inside of lower level folder.\ -\ -If you show the menu and press a number key, the selection would jump to the position of a menu item starts with the number.\ -\ -When you select an item, ClipMenu copy the data to clipboard\ -\ -After your selection, ClipMenu:\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls2\ilvl0\cf0 {\listtext 1. }copy the data to the system clipboard.\ -{\listtext 2. }paste it.\ -{\listtext 3. }move the item to the top position in the menu. -\f3\fs24 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 Preferences -\f3\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\fs26 \cf0 You can alter various ClipMenu settings at Preferences panel. -\f3\fs24 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 Snippet -\f3\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\fs26 \cf0 It is convenient if you store reusable texts as snippets. You can register snippets at Preferences panel.\ -\ -Registered snippets are shown below (or above if you want) clipboard history items.\ -\ -If you want to display snippets only, use "snippet menu". It is called via hot key, the default is -\b Command-Shift-B -\b0 . You can also change this shortcut as you wish. -\f4\fs24 \cf3 \ul \ulc3 \CocoaLigature0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f3 \cf0 \ulnone \CocoaLigature1 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs28 \cf0 \up2 Action -\f3\b0\fs24 \up0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f2\fs26 \cf0 You can apply various Actions to history items. Action menu is popped up by -\b right mouse button click -\b0 , -\b Control-click -\b0 or -\b Control-Enter -\b0 key combination.\ -\ -There are two types of Actions. -\f3\fs24 \ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\cf0 \ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls3\ilvl0 -\f2\b\fs26 \cf0 \up2 {\listtext 1. }Built-in Actions -\f1\fs24 \cf4 \up0 \uc0\u8232 -\f2\b0\fs26 \cf0 They are not allowed to edit by user. -\f1 \uc0\u8232 -\f2 e.g.) "Paste as PlainText" or "Remove". -\f1\fs24 \uc0\u8232 -\f3 \ -\ls3\ilvl0 -\f2\b\fs26 \up2 {\listtext 2. }JavaScript Actions -\f1\fs24 \cf4 \up0 \uc0\u8232 -\f2\b0\fs26 \cf0 They are allowed to add and edit by user. They are written by JavaScript, well known scripting language. You can freely modify text in history items by them. -\f1 \uc0\u8232 \u8232 -\f2 e.g.) "Capitalize", "lowercase", "UPPERCASE" or "Title Case".\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -For more details about actions, please check help pages.\ -\ -\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural -\ls4\ilvl0\cf0 {\listtext \uc0\u9642 }{\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/en/help/builtin-action"}}{\fldrslt Built-in Action}}\ -{\listtext \uc0\u9642 }{\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/en/help/javascript-action"}}{\fldrslt JavaScript Action}}\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural -\cf0 \ -"How to write JavaScript Actions" is now written in Japanese only. It would be translated into English in a future release. Sorry for the inconvenience. -\f3\fs24 \ -\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs34 \cf2 Website -\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 URL: {\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/"}}{\fldrslt \cf5 http://www.clipmenu.com/}}\ -Twitter: {\field{\*\fldinst{HYPERLINK "http://twitter.com/clipmenu"}}{\fldrslt \cf5 http://twitter.com/clipmenu}}\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs34 \cf2 License -\b0\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\fs26 \cf0 This program is a freeware. You can use it freely.\ -You can also redistribute it freely without any modifications to the archive. -\f3\fs24 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f2\b \cf0 \ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\fs34 \cf2 Contact -\fs24 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\b0\fs26 \cf0 Name: Naotaka Morimoto\ -\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\fs24 \cf0 Email: \cf5 webmaster@naotaka.com\cf0 \ -Twitter: {\field{\*\fldinst{HYPERLINK "http://twitter.com/naotakaM"}}{\fldrslt \cf5 http://twitter.com/naotakaM}} -\f3 \ - -\f2 URL: {\field{\*\fldinst{HYPERLINK "http://www.clipmenu.com/"}}{\fldrslt \cf5 http://www.naotaka.com/}}\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\f3 \cf0 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural - -\f2 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\b\fs34 \cf2 Copyrights -\fs28 \cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural - -\b0\fs26 \cf0 Application Icons (ClipMenu.icns, StatusMenuIcon.png, StatusMenuIcon_pressed.png)\ -http://www.max.hi-ho.ne.jp/painter/\ -Copyright (c) 2008 K2DesignWorks. All rights reserved.\ -\ -Status Menubar Icons (StatusMenuIconByDaveUlrich*.png) \ -http://daveulrich.net/\ -Copyright (c) 2009 Dave Ulrich. All rights reserved.\ -\ -PTHotKey\ -http://www.rogueamoeba.com/utm/posts/Random/Homegrown_Developer_Tools-2004-07-14-12-00\ -Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.\ -\ -Shortcut Recorder\ -http://code.google.com/p/shortcutrecorder/\ -Copyright (c) 2006, contributors to ShortcutRecorder. (See the contributors listed in detail later in the file, or see .) All rights reserved.\ -\ -Sparkle\ -http://sparkle.andymatuschak.org/\ -Copyright (c) 2006 Andy Matuschak\ -\ -DBPrefsWindowController\ -http://www.mere-mortal-software.com/blog/sourcecode.php\ -Created by Dave Batton\ -Copyright 2007. Some rights reserved.\ -This work is licensed under a Creative Commons license:\ -http://creativecommons.org/licenses/by/3.0/\ -\ -Google Toolbox for Mac\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural -\cf0 http://code.google.com/p/google-toolbox-for-mac/\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 Copyright 2007-2008 Google Inc.\ -Licensed under the Apache License, Version 2.0 (the "License"); you may not\ -use this file except in compliance with the License. You may obtain a copy\ -of the License at\ -http://www.apache.org/licenses/LICENSE-2.0\ -Unless required by applicable law or agreed to in writing, software\ -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\ -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\ -License for the specific language governing permissions and limitations under\ -the License.\ -\ -inflection-js\ -http://code.google.com/p/inflection-js/\ -Copyright (c) 2007 Ryan Schuft (ryan.schuft@gmail.com)\ -\ -fhconvert.js\ -http://distraid.co.jp/demo/js_codeconv.html\ -copyright (c) 2008 distraid Inc. \ -This script is freely distributable under the terms of an MIT-style license.\ -\ -showdown.js\ -http://attacklab.net/showdown/\ -Copyright (c) 2007, John Fraser \ - \ -All rights reserved.\ -Original Markdown copyright (c) 2004, John Gruber \ - \ -All rights reserved.\ -\ -v8cgi\ -http://code.google.com/p/v8cgi/\ -Ond\uc0\u345 ej \'8e\'e1ra (ondras@zarovi.cz)\ -\ -JS-methods\ -http://js-methods.googlecode.com/\ -Copyright (c) 2007 Harald Hanek (http://js-methods.googlecode.com)\ -Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)\ -and GPL (http://www.gnu.org/licenses/gpl.html) licenses.\ - -\f3\fs24 \ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls5\ilvl0\cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs34 \cf2 Credits -\f3\b0\fs24 \cf0 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls6\ilvl0 -\f2\fs26 \cf0 {\listtext \'95 }Uses application icon by K2 of {\field{\*\fldinst{HYPERLINK "http://www.max.hi-ho.ne.jp/painter/"}}{\fldrslt K2DesignWorks}}.\ -{\listtext \'95 }Uses application status bar icons by {\field{\*\fldinst{HYPERLINK "http://daveulrich.net/"}}{\fldrslt Dave Ulrich}}.\ -{\listtext \'95 }Uses {\field{\*\fldinst{HYPERLINK "http://code.google.com/p/shortcutrecorder/"}}{\fldrslt Shortcut Recorder}} framework to register hot keys.\ -{\listtext \'95 }Uses {\field{\*\fldinst{HYPERLINK "http://www.rogueamoeba.com/utm/posts/Random/Homegrown_Developer_Tools-2004-07-14-12-00"}}{\fldrslt PTHotKey}} library by Rogue Amoeba Software to register hot keys.\ -{\listtext \'95 }Uses {\field{\*\fldinst{HYPERLINK "http://sparkle.andymatuschak.org/"}}{\fldrslt Sparkle}} framework to check updates automatically.\ -{\listtext \'95 }Uses {\field{\*\fldinst{HYPERLINK "http://www.mere-mortal-software.com/blog/sourcecode.php"}}{\fldrslt DBPrefsWindowController}} by Dave Batton to make Preferences panel.\ -{\listtext \'95 }Uses {\field{\*\fldinst{HYPERLINK "http://code.google.com/p/google-toolbox-for-mac/"}}{\fldrslt Google Toolbox for Mac}} by Google to register Login Items.\ -{\listtext \'95 }Referred {\field{\*\fldinst{HYPERLINK "http://cole.nitroy.com/projects.html"}}{\fldrslt Clipper}} by Coleman Nitroy to manage histories and time interval to observe Pasteboard Server.\ -{\listtext \'95 }Used {\field{\*\fldinst{HYPERLINK "http://homepage.mac.com/nsekine/SYW/SYWSoft/softOSXE.html#iLingual"}}{\fldrslt iLingual}} by Nobuatsu Sekine to make Japanese localization until ClipMenu v0.2.1.\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\tx7280\tx7840\tx8400\tx8960\tx9520\tx10080\tx10640\tx11200\tx11760\tx12320\tx12880\tx13440\tx14000\tx14560\tx15120\tx15680\tx16240\tx16800\tx17360\tx17920\tx18480\tx19040\tx19600\tx20160\tx20720\tx21280\tx21840\tx22400\tx22960\tx23520\tx24080\tx24640\tx25200\tx25760\tx26320\tx26880\tx27440\tx28000\tx28560\tx29120\tx29680\tx30240\tx30800\tx31360\tx31920\tx32480\tx33040\tx33600\tx34160\tx34720\tx35280\tx35840\tx36400\tx36960\tx37520\tx38080\tx38640\tx39200\tx39760\tx40320\tx40880\tx41440\tx42000\tx42560\tx43120\tx43680\tx44240\tx44800\tx45360\tx45920\tx46480\tx47040\tx47600\tx48160\tx48720\tx49280\tx49840\tx50400\tx50960\tx51520\tx52080\tx52640\tx53200\tx53760\tx54320\tx54880\tx55440\tx56000\ql\qnatural\pardirnatural -\cf0 \ -\pard\pardeftab720\sl400\sa360\ql\qnatural -\cf0 ClipMenu is heavily inspired by {\field{\*\fldinst{HYPERLINK "http://www.nakka.com/soft/clcl/index_eng.html"}}{\fldrslt CLCL}}. It is must-have clipboard utility when I use Windows. I appreciate the author, Nakashima Tomoaki. -\f3\fs24 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural -\cf0 \ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f2\b\fs34 \cf2 Version History\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls7\ilvl1 -\fs28 \cf0 0.4.3 -\b0 (November 9, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls8\ilvl0 -\f2\fs26 \cf0 fixed:\ - - Fix a bug where you couldn't edit snippets in version 0.4.2.\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls8\ilvl1 -\b\fs34 \cf2 \ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls9\ilvl1 -\fs28 \cf0 0.4.2 -\b0 (November 8, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls10\ilvl0 -\f2\fs26 \cf0 new:\ - - Add a feature to exclude applications from checking the clipboard.\ - - Add a feature to export clipboard history as text file(s).\ - - Add an option to check for pre-releases.\ - changed:\ - - Change how to manage clipboard history.\ - - Change how to check for duplicate of history items.\ - - Change how to sort history order.\ - - Change how to make thumbnail image in the menu.\ - - Change initialization process.\ - fixed:\ - - Fix a issue that always show status bar icon whether turned on/off.\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls10\ilvl1 -\f3\fs24 \cf0 \ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls11\ilvl1 -\f2\b\fs28 \cf0 0.4.1 -\b0 (October 21, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls12\ilvl0 -\f2\fs26 \cf0 new:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls12\ilvl1\cf0 {\listtext \uc0\u9642 }Fix a bug that causes force pasting regardless of the preference.\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls12\ilvl1 -\f3\fs24 \cf0 \ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls13\ilvl1 -\f2\b\fs28 \cf0 0.4.0 -\b0 (October 20, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls14\ilvl0 -\f2\fs26 \cf0 new:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls14\ilvl1\cf0 {\listtext \uc0\u9642 }64-bit support in Mac OS X 10.6 (Snow Leopard).\ -{\listtext \uc0\u9642 }Add autosave function to save clipboard history periodically.\ -{\listtext \uc0\u9642 }Automatic update support using Sparkle Framework.\ -{\listtext \uc0\u9642 }Add a dialog to ask you whether enable/disable "Launch on Login" option.\ -{\listtext \uc0\u9642 }Add an option to enable/disable re-ordering history when clipboard data is changed.\ -{\listtext \uc0\u9642 }Append the application's version number to a tooltip on the status menubar icon.\ - changed:\ -{\listtext \uc0\u9642 }Change default keyboard shortcut keys (command-shift-v, command-shift-b).\ -{\listtext \uc0\u9642 }Change folder icon when mouse over a folder menu item in a menu.\ -{\listtext \uc0\u9642 }Make status bar icon selectable.\ -{\listtext \uc0\u9642 }Add new status bar icons (by Dave Ulrich).\ -{\listtext \uc0\u9642 }Change the label of "Quit" menu item to "Quit ClipMenu".\ -{\listtext \uc0\u9642 }Add a suppression button to the dialog window to ask whether show it or not.\ -{\listtext \uc0\u9642 }Multi-thread start up operations.\ -{\listtext \uc0\u9642 }Update Shortcut Recorder framework.\ - fixed:\ -{\listtext \uc0\u9642 }Fix a glitch occurred when max history size is decreased.\ -{\listtext \uc0\u9642 }Fix an issue with preferences panel.\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls14\ilvl1 -\f3\fs24 \cf0 \ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls15\ilvl1 -\f2\b\fs28 \cf0 0.3.5 -\b0 (June 17, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl0 -\f2\fs26 \cf0 new:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }Added "Paste as File Path" action.\ -{\listtext \uc0\u9642 }Added "Paste as HFS File Path" action.\ -{\listtext \uc0\u9642 }Added Japanese hiragana <-> katakana converter actions.\ -{\listtext \uc0\u9642 }Added Japanese half-width katakana <-> full-width katakana converter actions.\ -{\listtext \uc0\u9642 }Added actions for surrounding selected item with parenthesizes or HTML tags.\ -{\listtext \uc0\u9642 }Added actions for calculating MD5/SHA-1 hash and Base64 encoding/decoding.\ -{\listtext \uc0\u9642 }Added actions for Markdown conversion, encoding/decoding URI component, escaping/unescaping HTML characters, removing HTML tags, collapsing spaces and converting characters to decimals.\ -{\listtext \uc0\u9642 }Included JavaScript libraries, fhconvert.js, showdown.js, v8cgi and JS-methods.\ -{\listtext \uc0\u9642 }Added activate() method for JavaScript action.\ -{\listtext \uc0\u9642 }Added a setting to limit the maximum length of tool tip string.\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl0\cf0 changed:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }You can now apply actions to snippets.\ -{\listtext \uc0\u9642 }Changed a behavior when you create a new snippet. If you forget to enter the content of the snippet, its title will be copied automatically to the content.\ -{\listtext \uc0\u9642 }Changed default action set.\ -{\listtext \uc0\u9642 }Improved the way to check duplication of history items.\ -{\listtext \uc0\u9642 }Changed serialization format of registered actions to Property List.\ -{\listtext \uc0\u9642 }Changed the way to load bundled JavaScript actions.\ -{\listtext \uc0\u9642 }Changed a JavaScript library for Japanese characters conversion "z2h_word.js" to "fhconvert.js".\ -{\listtext \uc0\u9642 }Updated inflection.js to the most recent version.\ -{\listtext \uc0\u9642 }Added Japanese localization for names of JavaScript actions at Preferences panel.\ -{\listtext \uc0\u9642 }Improved usability of preferences panel.\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl0\cf0 fixed:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }Fixed a glitch that an error dialog called in JavaScript actions is not the most front window.\ -\ -\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural -\ls16\ilvl1 -\b\fs28 \cf0 0.3.4 -\b0 (May 24, 2009) -\f3\fs24 \ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl1 -\f2\fs26 \cf0 new:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }Support Spaces on Leopard.\ -{\listtext \uc0\u9642 }New website.\ -{\listtext \uc0\u9642 }Add ReadMe file in English.\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl1\cf0 changed:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }Accept a shortcut key combination (Command-Option-V).\ -\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\ql\qnatural -\ls16\ilvl1\cf0 fixed:\ -\pard\tx940\tx1440\pardeftab720\li1440\fi-1440\sl400\ql\qnatural -\ls16\ilvl1\cf0 {\listtext \uc0\u9642 }Removed snippets remain in Snippets.xml file.\ -{\listtext \uc0\u9642 }Cannot close Preferences panel by shortcut key combination. -\f1\fs24 \cf6 \uc0\u8232 } \ No newline at end of file diff --git a/doc/archive_contents/ReadMe.rtfd/ozmCP.tiff b/doc/archive_contents/ReadMe.rtfd/ozmCP.tiff deleted file mode 100644 index d0c54f9..0000000 Binary files a/doc/archive_contents/ReadMe.rtfd/ozmCP.tiff and /dev/null differ diff --git a/doc/enhancements.md b/doc/enhancements.md new file mode 100644 index 0000000..de6fa99 --- /dev/null +++ b/doc/enhancements.md @@ -0,0 +1,645 @@ +# ClipMenu — Architecture Enhancement Proposals + +This document proposes concrete modernisation improvements for ClipMenu. Each enhancement describes the current problem, the modern alternative, migration strategy, and trade-offs. Proposals are ordered from highest to lowest impact. + +All proposals target **macOS 13 Ventura+** as the minimum deployment target and **Swift 5.9+** as the implementation language, unless noted otherwise. + +--- + +## 1. Clipboard Monitoring — Replace Polling with Change Notification + +### Current Design + +`ClipsController` uses a repeating `NSTimer` (default 0.75 s, max 1.0 s) that reads `[NSPasteboard generalPasteboard].changeCount` on every tick. This wakes the process ~80 times per minute even when the clipboard is idle. + +### Problem + +- Wastes CPU and battery on idle systems. +- Introduces latency: a copy made 1 ms after a tick won't be captured for up to 750 ms. +- The hard cap of 1.0 s is an arbitrary workaround, not a design principle. + +### Proposed Solution + +Use `NSPasteboard`'s KVO support via `addObserver(_:forKeyPath:options:context:)` on the `changeCount` property. On macOS 10.8+ this fires synchronously when the pasteboard changes, with zero polling overhead. + +```swift +// ClipboardMonitor.swift +import AppKit +import Combine + +final class ClipboardMonitor { + private let pasteboard = NSPasteboard.general + private var observation: NSKeyValueObservation? + let clipChanged = PassthroughSubject() + + func start() { + observation = pasteboard.observe(\.changeCount, options: [.new]) { [weak self] pb, _ in + self?.clipChanged.send(pb) + } + } + + func stop() { + observation = nil + } +} +``` + +The `ClipboardMonitor` publishes on `clipChanged`. `ClipsService` (replacement for `ClipsController`) subscribes and processes the new content. + +### Trade-offs + +- `NSPasteboard.changeCount` KVO is documented as reliable on macOS 10.8+, which is well below the new minimum target. +- Eliminates timer drift: two rapid copies in quick succession won't be coalesced by a polling window. +- If Apple ever restricts KVO on `NSPasteboard` (not currently the case), the fallback is a 250 ms timer — still faster than the current default and only needed as a safety net. + +--- + +## 2. Persistence — Replace NSKeyedArchiver + Core Data with SwiftData + +### Current Design + +| Data | Mechanism | File | +|---|---|---| +| Clip history | `NSKeyedArchiver` | `clips.data` | +| Action nodes | `NSPropertyListSerialization` | `actions.plist` | +| Snippets | Core Data XML store | `Snippets.xml` | + +Three separate persistence stacks, each with their own save/load paths, error handling, and migration stories. + +### Problems + +- `clips.data` is a monolithic binary blob; a single corrupt byte loses the entire history. +- Core Data requires a heavyweight coordinator/context/store stack for a simple two-entity model. +- No incremental writes: every save rewrites the whole clip array. +- NSKeyedArchiver format changes require manual backward-compat decoding (already present in `Clip.initWithCoder:`). + +### Proposed Solution + +Adopt **SwiftData** (macOS 14+) as a single persistence layer for all three data sets. + +#### Model + +```swift +import SwiftData + +@Model +final class ClipEntry { + var createdAt: Date + var lastUsedAt: Date + var types: [String] // pasteboard type UTI strings + var stringValue: String? + var rtfData: Data? + var pdfData: Data? + var filenames: [String]? + var urlStrings: [String]? + var imageData: Data? // TIFF representation + + init(createdAt: Date = .now) { + self.createdAt = createdAt + self.lastUsedAt = createdAt + self.types = [] + } +} + +@Model +final class SnippetFolder { + var title: String + var isEnabled: Bool + var sortIndex: Int + @Relationship(deleteRule: .cascade) var snippets: [Snippet] = [] +} + +@Model +final class Snippet { + var title: String + var content: String + var isEnabled: Bool + var sortIndex: Int + var folder: SnippetFolder? +} + +@Model +final class ActionNode { + var title: String + var isLeaf: Bool + var sortIndex: Int + var actionType: String? // "builtin" | "javaScript" + var actionName: String? + var scriptPath: String? + @Relationship(deleteRule: .cascade) var children: [ActionNode] = [] +} +``` + +#### Container Setup + +```swift +let schema = Schema([ClipEntry.self, SnippetFolder.self, Snippet.self, ActionNode.self]) +let config = ModelConfiguration("ClipMenu", schema: schema) +let container = try ModelContainer(for: schema, configurations: config) +``` + +SwiftData automatically places the store at `~/Library/Application Support/ClipMenu/default.store` (SQLite). + +#### Migration from Legacy Formats + +Write a one-time migration routine that runs on first launch after the update: + +1. Check for `clips.data`; if present, unarchive via `NSKeyedUnarchiver`, insert each clip into the SwiftData context, delete the file. +2. Check for `Snippets.xml`; if present, load the Core Data store using the old coordinator, read all objects, insert into SwiftData, delete the file. +3. Check for `actions.plist`; parse it, insert `ActionNode` objects, delete the file. + +Mark migration complete in `UserDefaults` with a version key so it never runs twice. + +### Benefits + +- Single SQLite file; SQLite is append-friendly and recovers from partial writes. +- Free incremental writes — only changed rows are written. +- Built-in versioned schema migration via `MigrationPlan`. +- `@Query` descriptor in SwiftUI views replaces `sortedClips` computed property. +- Automatic background context for saves; no manual thread management. + +--- + +## 3. Concurrency — Replace NSThread/NSOperationQueue with Swift Concurrency + +### Current Design + +- Startup uses `NSOperationQueue` to run clip load, action load, and hotkey registration concurrently. +- Autosave detaches a raw `NSThread` via `NSThread.detachNewThreadSelector:`. +- The rest of the app is single-threaded on the main thread with no formal actor boundary. + +### Proposed Solution + +Replace with `async/await` and `Actor`s. + +```swift +// ClipsService.swift +actor ClipsService { + private var clips: [ClipEntry] = [] + private let modelContext: ModelContext + + func loadClips() async throws { + let descriptor = FetchDescriptor(sortBy: [SortDescriptor(\.lastUsedAt, order: .reverse)]) + clips = try modelContext.fetch(descriptor) + } + + func addClip(_ entry: ClipEntry) async { + modelContext.insert(entry) + try? modelContext.save() + await MainActor.run { NotificationCenter.default.post(name: .clipsDidChange, object: nil) } + } +} +``` + +Startup becomes a single `async` block: + +```swift +func applicationDidFinishLaunching(_ notification: Notification) { + Task { + async let clips: () = clipsService.loadClips() + async let actions: () = actionService.loadActions() + async let hotkeys: () = hotkeyService.register() + try await (clips, actions, hotkeys) + } +} +``` + +Autosave uses `Task.sleep` instead of `NSTimer`: + +```swift +func startAutosave(interval: Duration) { + Task.detached(priority: .background) { [weak self] in + while true { + try await Task.sleep(for: interval) + await self?.saveIfNeeded() + } + } +} +``` + +--- + +## 4. Global Hotkeys — Replace PTHotKeys (Carbon) with ShortcutRecorder or EventKit + +### Current Design + +PTHotKeys registers hotkeys via legacy Carbon `RegisterEventHotKey` APIs. These APIs are available but deprecated and rely on the Carbon event loop, which is not guaranteed in future OS versions. + +### Problems + +- Carbon dependency (`Carbon/Carbon.h`). +- `PTKeyCombo` serialises as raw key-code + modifier integer, which is keyboard-layout-dependent. +- No support for non-ASCII key descriptions in modifier display. + +### Proposed Solution + +Use `MASShortcut` or `KeyboardShortcuts` (by Sindre Sorhus), both of which use CGEventTap internally: + +```swift +// Using the KeyboardShortcuts package +import KeyboardShortcuts + +extension KeyboardShortcuts.Name { + static let openClipMenu = Self("openClipMenu", default: .init(.v, modifiers: [.command, .shift])) + static let openHistory = Self("openHistory", default: .init(.v, modifiers: [.command, .control])) + static let openSnippets = Self("openSnippets", default: .init(.b, modifiers: [.command, .shift])) +} + +// Registration (replaces _registerHotKeys) +KeyboardShortcuts.onKeyUp(for: .openClipMenu) { [weak self] in self?.openClipMenu() } +KeyboardShortcuts.onKeyUp(for: .openHistory) { [weak self] in self?.openHistory() } +KeyboardShortcuts.onKeyUp(for: .openSnippets) { [weak self] in self?.openSnippets() } +``` + +Preferences UI uses `KeyboardShortcuts.Recorder` (SwiftUI view) instead of ShortcutRecorder XIB controls. + +Hotkey configurations are stored automatically in `UserDefaults` under the shortcut name, in a layout-independent format. + +--- + +## 5. UI — Replace NSMenu/XIB with SwiftUI MenuBarExtra + +### Current Design + +`MenuController` manually builds `NSMenu` and all `NSMenuItem` objects in code, including custom attributed strings, thumbnails, icons, and submenus. XIB files define the preferences window. + +### Proposed Solution + +macOS 13 introduced `MenuBarExtra` — a SwiftUI scene that renders a menu or popover directly in the menu bar. + +```swift +@main +struct ClipMenuApp: App { + var body: some Scene { + MenuBarExtra("ClipMenu", systemImage: "doc.on.clipboard") { + ClipMenuView() + } + .menuBarExtraStyle(.menu) // or .window for a popover + } +} +``` + +The content view uses `@Query` to fetch clips directly from SwiftData with live updates: + +```swift +struct ClipMenuView: View { + @Query(sort: \ClipEntry.lastUsedAt, order: .reverse) var clips: [ClipEntry] + @Query var snippetFolders: [SnippetFolder] + + var body: some View { + ForEach(clips) { clip in + ClipMenuItem(clip: clip) + } + Divider() + SnippetsSection(folders: snippetFolders) + Divider() + ControlsSection() + } +} +``` + +The preferences window becomes a `Settings` scene: + +```swift +Settings { + PreferencesView() + .frame(width: 500) +} +``` + +### Trade-offs + +- `MenuBarExtra` with `.menuBarExtraStyle(.menu)` renders identically to `NSMenu` in appearance. +- Custom menu item views (thumbnails, icons) are fully supported via `Label` and custom `View`s inside the menu. +- Keyboard shortcuts for menu items use SwiftUI's `.keyboardShortcut(_:modifiers:)` modifier. +- XIB files are eliminated entirely. + +--- + +## 6. JavaScript Engine — Replace WebView with JavaScriptCore + +### Current Design + +`ActionController` creates a hidden `WebView`, loads an empty HTML string, and uses `WebScriptObject` to evaluate JavaScript actions. `WebView` is deprecated as of macOS 10.14. + +### Problems + +- `WebView` (WebKit legacy) is deprecated and may be removed. +- Spinning up a `WebView` for script execution is heavyweight. +- `WebScriptObject` bridge is fragile and undocumented in modern SDKs. +- External resource access must be manually blocked via the policy delegate. + +### Proposed Solution + +Use `JavaScriptCore.framework` directly: + +```swift +import JavaScriptCore + +final class ScriptEngine { + private let context = JSContext()! + + init() { + // Inject ClipMenu namespace + let clipMenuObj = JSValue(newObjectIn: context) + context["ClipMenu"] = clipMenuObj + + // ClipMenu.require(path) — load a library script + let require: @convention(block) (String) -> Void = { [weak self] path in + guard let source = try? String(contentsOfFile: path) else { return } + self?.context.evaluateScript(source) + } + clipMenuObj?.setObject(require, forKeyedSubscript: "require" as NSString) + + // Error handler + context.exceptionHandler = { _, exception in + print("JS error: \(exception?.toString() ?? "unknown")") + } + } + + func run(script: String, clipText: String, clip: ScriptableClip) -> String? { + context["clipText"] = clipText + context["clip"] = clip + let wrapped = "function __wrapper(clipText, clip) { \(script) }" + context.evaluateScript(wrapped) + let result = context.evaluateScript("__wrapper(clipText, clip)") + guard let str = result?.toString(), result?.isUndefined == false else { return nil } + return str + } +} +``` + +`ScriptableClip` exposes its API via `@objc` and `JSExport`: + +```swift +@objc protocol ScriptableClipExport: JSExport { + func setStringAttributes(_ attrs: [String: Any]) + func addStringAttributes(_ attrs: [String: Any]) + var text: String? { get } +} +``` + +### Benefits + +- No hidden web view, no HTML loading, no deprecated APIs. +- `JSContext` is lightweight and can be created per invocation or pooled. +- Direct Swift bridging via `JSExport` is type-safe and documented. +- No network policy delegate needed: `JSContext` has no network access by default. + +--- + +## 7. Application Exclusion — Replace ProcessSerialNumber with Modern Process APIs + +### Current Design + +`ClipsController._frontProcessIsInExcludeList` calls `GetFrontProcess(&psn)` and `ProcessInformationCopyDictionary` — both Carbon APIs deprecated in macOS 10.9. + +### Proposed Solution + +Use `NSWorkspace` notifications and `NSRunningApplication`: + +```swift +extension NSWorkspace { + var frontmostBundleIdentifier: String? { + frontmostApplication?.bundleIdentifier + } +} + +// In ClipboardMonitor, before processing a change: +func shouldRecord() -> Bool { + guard let frontId = NSWorkspace.shared.frontmostBundleIdentifier else { return true } + return !excludedBundleIDs.contains(frontId) +} +``` + +For the exclude-list panel, enumerate running apps: + +```swift +let runningApps = NSWorkspace.shared.runningApplications + .filter { $0.activationPolicy == .regular } + .map { ExcludeEntry(name: $0.localizedName ?? "", bundleID: $0.bundleIdentifier ?? "") } +``` + +--- + +## 8. Login Items — Replace LSSharedFileList with SMAppService + +### Current Design + +`NMLoginItems` uses `LSSharedFileListCreate`, `LSSharedFileListInsertItemURL`, and `LSSharedFileListItemRemove` — all deprecated in macOS 10.11. + +### Proposed Solution + +```swift +import ServiceManagement + +func setLaunchAtLogin(_ enabled: Bool) throws { + if enabled { + try SMAppService.mainApp.register() + } else { + try SMAppService.mainApp.unregister() + } +} + +var isRegisteredAsLoginItem: Bool { + SMAppService.mainApp.status == .enabled +} +``` + +`SMAppService` requires no special entitlements and works in sandboxed apps. Available on macOS 13+. + +--- + +## 9. Paste Mechanism — Replace CGEvent Synthesis with Accessibility API + +### Current Design + +`CMUtilities.paste()` posts synthetic `Cmd+V` keyboard events via `CGEventCreateKeyboardEvent` and `CGEventPost`. It must dynamically scan all 128 keycodes to find the `V` key for the current keyboard layout. + +### Problems + +- Requires Accessibility permission if running unsandboxed; blocked entirely in sandbox. +- The keycode scan runs on first use and caches the result, but is brittle on layout changes. +- No feedback if the target app doesn't support `Cmd+V`. + +### Proposed Solution + +Use `NSPasteboard` write + a `CGEvent`-based approach but with the `kCGEventSourceStateHIDSystemState` source, which is more reliable: + +```swift +func paste() { + let src = CGEventSource(stateID: .hidSystemState) + let vKeyCode: CGKeyCode = 9 // 'V' in ANSI; stored as a constant after one-time lookup + let keyDown = CGEvent(keyboardEventSource: src, virtualKey: vKeyCode, keyDown: true) + let keyUp = CGEvent(keyboardEventSource: src, virtualKey: vKeyCode, keyDown: false) + keyDown?.flags = .maskCommand + keyUp?.flags = .maskCommand + keyDown?.post(tap: .cghidEventTap) + keyUp?.post(tap: .cghidEventTap) +} +``` + +For a sandboxed alternative, write the content to the pasteboard and ask the user to press `Cmd+V` manually — or use `NSAppleScript` targeting the frontmost app: + +```swift +let script = NSAppleScript(source: "tell application \"System Events\" to keystroke \"v\" using command down") +script?.executeAndReturnError(nil) +``` + +(The AppleScript approach requires Automation permission for the target app.) + +--- + +## 10. Settings — Replace NSUserDefaults Manual Keys with @AppStorage / Property Wrappers + +### Current Design + +Over 40 preference keys are scattered across multiple files as `#define` string constants. Defaults are registered manually in `+[AppController initialize]` via a large `NSMutableDictionary`. Preference observation is wired by hand with KVO. + +### Proposed Solution + +Define a typed settings container: + +```swift +struct ClipMenuSettings { + @AppStorage("maxHistorySize") var maxHistorySize: Int = 20 + @AppStorage("pollingInterval") var pollingInterval: Double = 0.75 + @AppStorage("reorderOnPaste") var reorderOnPaste: Bool = true + @AppStorage("autosaveDelay") var autosaveDelay: Int = 1800 + @AppStorage("saveOnQuit") var saveOnQuit: Bool = true + @AppStorage("showStatusItem") var showStatusItem: Bool = true + @AppStorage("enableActions") var enableActions: Bool = true + @AppStorage("positionOfSnippets") var positionOfSnippets: SnippetPosition = .belowClips + // …etc +} +``` + +SwiftUI views bind directly to these with `@AppStorage` in the view, or observe via `Combine.Publisher`: + +```swift +NotificationCenter.default + .publisher(for: UserDefaults.didChangeNotification) + .map { _ in UserDefaults.standard.integer(forKey: "maxHistorySize") } + .removeDuplicates() + .sink { [weak self] newSize in self?.clipsService.applyMaxSize(newSize) } + .store(in: &cancellables) +``` + +Eliminates all manual KVO setup in `ClipsController` and `AppController`. + +--- + +## 11. Bundled Script Actions — Replace File-System Script Discovery with Swift Plugin Protocol + +### Current Design + +Action scripts are discovered by walking the file system (`script/action/` directories). The tree is rebuilt at startup and saved to `actions.plist`. Users add custom scripts by dropping files into an Application Support directory. + +### Problems + +- No type safety, no capability declaration per script. +- Discovery is fragile if the directory layout changes. +- No way to validate a script before it appears in the menu. + +### Proposed Solution + +Define a `ClipMenuAction` protocol that built-in Swift actions can conform to. Retain the JavaScript engine for user scripts but give it a formal registration API: + +```swift +protocol ClipMenuAction: Sendable { + var id: String { get } + var title: String { get } + var applicableTypes: [ClipType] { get } + func perform(on clip: ClipEntry) async throws -> ClipEntry? +} +``` + +Built-in actions become Swift structs: + +```swift +struct PasteAsPlainTextAction: ClipMenuAction { + let id = "pasteAsPlainText" + let title = NSLocalizedString("Paste as Plain Text", comment: "") + let applicableTypes: [ClipType] = [.string] + + func perform(on clip: ClipEntry) async throws -> ClipEntry? { + guard let text = clip.stringValue else { return nil } + return ClipEntry(string: text) + } +} +``` + +The JavaScript engine registers user scripts as actions conforming to the same protocol, with the script evaluated at invocation time. + +--- + +## 12. Architecture Pattern — Migrate from Singletons + KVO to MVVM + Combine + +### Current Design + +All coordination flows through mutable singletons (`AppController`, `ClipsController`, `MenuController`, `ActionController`). Communication uses KVO and `NSNotificationCenter`. There are no formal ownership boundaries. + +### Proposed Solution + +Adopt a layered MVVM architecture: + +``` +View Layer (SwiftUI) + ClipMenuView, PreferencesView, SnippetEditorView + ↕ @Observable / @Query + +ViewModel Layer + ClipMenuViewModel — mediates between views and services + SnippetEditorViewModel + +Service Layer (Actors) + ClipsService — pasteboard monitoring, clip CRUD + ActionService — action node tree, script execution + SnippetService — snippet CRUD + +Infrastructure Layer + ClipboardMonitor — NSPasteboard KVO → publisher + HotkeyService — KeyboardShortcuts registration + PasteService — CGEvent paste + SettingsStore — @AppStorage wrappers +``` + +Services communicate via `AsyncStream` or `Combine` publishers. The view layer never touches services directly; it goes through ViewModels. This makes each layer independently testable. + +### Testing Impact + +- `ClipsService` can be tested with an in-memory `ModelContainer` (`isStoredInMemoryOnly: true`). +- `ClipboardMonitor` can be injected with a mock that publishes synthetic changes. +- Action scripts can be run in isolation against a stub `JSContext`. +- No globals means tests run in parallel without interference. + +--- + +## Summary Table + +| # | Area | Current | Proposed | Min macOS | +|---|---|---|---|---| +| 1 | Clipboard monitoring | NSTimer polling (0.75 s) | NSPasteboard KVO | 10.8 | +| 2 | Clip persistence | NSKeyedArchiver | SwiftData (SQLite) | 14.0 | +| 2 | Snippet persistence | Core Data XML | SwiftData (shared container) | 14.0 | +| 3 | Concurrency | NSThread / NSOperationQueue | async/await + Actor | 13.0 | +| 4 | Global hotkeys | PTHotKeys (Carbon) | KeyboardShortcuts (CGEventTap) | 12.0 | +| 5 | UI | NSMenu + XIB | SwiftUI MenuBarExtra | 13.0 | +| 6 | JS engine | WebView (deprecated) | JavaScriptCore JSContext | 10.5 | +| 7 | App exclusion | GetFrontProcess (Carbon) | NSWorkspace.frontmostApplication | 10.7 | +| 8 | Login items | LSSharedFileList (deprecated) | SMAppService | 13.0 | +| 9 | Paste | CGEvent keycode scan | CGEvent with cached keycode | — | +| 10 | Settings | Manual NSUserDefaults + KVO | @AppStorage + Combine | 14.0 | +| 11 | Script actions | Filesystem walk + plist | Swift protocol + JS plugin | — | +| 12 | Architecture | Singletons + KVO | MVVM + Combine + Actors | 13.0 | + +### Recommended Phasing + +**Phase 1 — Drop in, no UI changes:** +Items 1, 6, 7, 8, 9 — replace deprecated/polling APIs. These are self-contained and do not require architecture changes. + +**Phase 2 — Data layer:** +Items 2, 3, 10 — replace persistence with SwiftData and adopt async/await. Write migration routines for existing user data. + +**Phase 3 — Full modernisation:** +Items 4, 5, 11, 12 — SwiftUI, hotkey package, protocol-based actions. This is a full rewrite of the UI and coordination layers. diff --git a/doc/features.md b/doc/features.md new file mode 100644 index 0000000..f87455b --- /dev/null +++ b/doc/features.md @@ -0,0 +1,712 @@ +# ClipMenu — Feature & Architecture Reference + +This document is intended to give an LLM (or a developer) enough context to understand, extend, or reconstruct the application from the existing source code. It covers every major feature, the data model, the component wiring, key algorithms, preference keys, and file formats. + +--- + +## Overview + +ClipMenu is a macOS clipboard manager written in Objective-C (manual reference counting, targeting Mac OS X 10.5+). It runs as a background process that never appears in the Dock. Its only persistent UI element is a status-bar icon. The user interacts through pop-up menus triggered by global hotkeys or by clicking the status item. + +Bundle ID: `com.naotaka.ClipMenu` +Version: 0.4.4a13 +License: MIT + +--- + +## High-Level Architecture + +``` +AppController (main controller — owns hotkeys, actions, preference panel) +├── ClipsController (singleton — pasteboard monitoring, clip storage) +├── MenuController (singleton — status item, all pop-up menus) +├── ActionController (singleton — JavaScript engine, built-in actions) +│ └── BuiltInActionController +└── SnippetsController (singleton — Core Data store for snippets) + └── SnippetEditorController +``` + +All singletons use `+initialize`/`+sharedInstance` with a module-level static variable. They are NOT thread-safe; all mutations run on the main thread except autosave which detaches a new thread via `NSThread detachNewThreadSelector:`. + +### Startup Sequence (`applicationDidFinishLaunching:`) + +1. Create an `NSOperationQueue` and enqueue three concurrent operations: + - `[ClipsController loadClips]` — deserialise `clips.data` + - `[ActionController loadActions]` — parse `actions.plist` + - `[AppController _registerHotKeys]` — register global hotkeys via PTHotKeyCenter +2. Prompt user to add login item (once, suppressed by `CMPrefSuppressAlertForLoginItemKey`). +3. Configure Sparkle updater (feed URL, auto-check flag, interval). +4. Wait for all operations to finish. + +### Shutdown Sequence (`applicationWillTerminate:`) + +1. If `CMPrefSaveHistoryOnQuitKey` is YES, call `[ClipsController saveClips]`; else call `[ClipsController removeClips]` (deletes the file). +2. Call `[ActionController saveActions]`. +3. Unregister all hotkeys. + +### KVO Wiring + +`AppController` observes: +- `CMPrefHotKeysKey` → re-registers all hotkeys +- `CMEnableAutomaticCheckPreReleaseKey` → switches Sparkle feed URL + +`ClipsController` observes: +- `CMPrefMaxHistorySizeKey` → trims history +- `CMPrefAutosaveDelayKey` → restarts autosave timer +- `CMPrefTimeIntervalKey` → restarts pasteboard polling timer +- `CMPrefStoreTypesKey` → reloads which types to capture +- `CMPrefExcludeAppsKey` → reloads exclude bundle-ID set + +`AppController` also observes `ClipsController.clips` (KVO key `"clips"`). Any change triggers `[MenuController updateStatusMenu]` so the menu stays current. + +--- + +## Data Model: `Clip` + +`Clip` (`Source/Clip.m`) is an `NSObject` that implements `NSCoding` and `NSCopying`. + +### Properties + +| Property | Type | NSCoder key | +|---|---|---| +| `types` | `NSArray *` (of pasteboard type strings) | `"types"` | +| `createdDate` | `NSDate *` | `"createdDate"` | +| `lastUsedDate` | `NSDate *` | `"lastUsedDate"` | +| `stringValue` | `NSString *` | `"stringValue"` | +| `RTFData` | `NSData *` | `"RTFData"` | +| `PDF` | `NSData *` | `"PDF"` | +| `filenames` | `NSArray *` (of `NSString`) | `"filenames"` | +| `URL` | `NSArray *` (of `NSString`) | `"URL"` | +| `image` | `NSImage *` | `"image"` | +| `thumbnail` | `NSImage *` (transient, not encoded) | — | + +**Backward-compat decoding:** `lastUsedDate` falls back to key `"lastAccessedDate"` (used in v0.4.2a2–a4). `RTFData` falls back to keys `"RTFD"` then `"RTF"`. + +### Identity / Equality + +`hash` is computed from the `types` array string, then XOR-ed with: +- Image: TIFF byte length +- Filenames: XOR of each filename's hash +- URL: XOR of each URL string hash +- PDF: byte length +- stringValue: `NSString` hash +- RTFData: byte length (if present) + +`isEqual:` delegates entirely to `hash` comparison. + +### Supported Pasteboard Types + +Defined in `+availableTypes` (order matters for `primaryPboardType`): + +``` +NSStringPboardType, NSRTFPboardType, NSRTFDPboardType, NSPDFPboardType, +NSFilenamesPboardType, NSURLPboardType, NSTIFFPboardType, NSPICTPboardType +``` + +Human-readable names from `+availableTypeNames`: +`String, RTF, RTFD, PDF, Filenames, URL, TIFF, PICT` + +Both lists are parallel arrays; `+availableTypeDictionary` returns a dict mapping pasteboard type → name. + +### Thumbnail + +`-thumbnailOfSize:(NSSize)size` scales the image to fit within the given bounding box while preserving aspect ratio. The result is cached (invalidated if requested size differs). Uses `bestRepresentationForRect:context:hints:` on 10.6+, falls back to a manual `NSBitmapImageRep` draw into a new `NSImage`. + +--- + +## ClipsController + +`Source/ClipsController.m` — singleton. + +### State + +- `clips` — `NSMutableSet` of `Clip` objects (KVO-observable) +- `storeTypes` — `NSDictionary` mapping type-name → `NSNumber(BOOL)` +- `excludeIdentifiers` — `NSSet` of bundle-identifier strings to ignore +- `maxClipsSize` — `NSUInteger` +- `cachedChangeCount` — `NSInteger`; mirrors `[NSPasteboard generalPasteboard].changeCount` +- `lastClipsUpdated`, `lastSaved` — `NSDate` used by autosave logic + +### Pasteboard Polling + +`_startPasteboardObservingTimer` creates a repeating `NSTimer` at the configured interval (max capped at 1.0 s). On each tick, `_updateClips:` runs: + +1. Read `[NSPasteboard generalPasteboard].changeCount`. If unchanged, return. +2. Cache the new change count. +3. Check `_frontProcessIsInExcludeList` via `GetFrontProcess` + `ProcessInformationCopyDictionary`. If excluded, return. +4. Call `_makeClipFromPasteboard:` to build a new `Clip`. +5. If the set already contains an equal clip (by hash), update its `lastUsedDate` and return. +6. Add the new clip via `mutableSetValueForKey:@"clips"` (triggers KVO). +7. Call `_trimHistorySize`. + +`_makeClipFromPasteboard:` first calls `_makeTypesFromPasteboard:` to build the list of types to store (filtered by `storeTypes`; TIFF and PICT are collapsed to TIFF). It then reads each type's data from the pasteboard. + +### History Trimming + +`_trimHistorySize` sorts clips by `sortedClips` (newest first), then removes the tail items that exceed `maxClipsSize`. + +### Sorted View + +`sortedClips` (dynamic property) sorts by `lastUsedDate` descending when `CMPrefReorderClipsAfterPasting` is YES, or by `createdDate` descending otherwise. + +### Persistence + +- **File:** `~/Library/Application Support/ClipMenu/clips.data` +- **Format:** `NSKeyedArchiver` archive of the `sortedClips` array +- **Save:** `saveClips` — writes via `NSKeyedArchiver archiveRootObject:toFile:` +- **Load:** `loadClips` — unarchives, sets `clips`, trims to max size +- **Delete:** `removeClips` — removes the file from disk (called on quit when save-on-quit is off) + +### Autosave + +A second repeating timer fires at `CMPrefAutosaveDelayKey` seconds (min 15 s). `_autosave` compares `lastSaved` vs `lastClipsUpdated`. If clips have been updated since last save, it detaches a new thread to call `_fireSaveClips`, which calls `saveClips` and updates `lastSaved` on success. On failure, it shows an alert and restarts the timer. + +### Export + +- `exportHistoryStringsAsSingleFile:path` — concatenates all text clips with a configurable separator (newline, CRLF, CR, tab, space, or empty). Uses `NSFileHandle` to append each clip. +- `exportHistoryStringsAsMultipleFiles:path` — writes each text clip to a numbered `.txt` file (e.g. `1.txt`, `2.txt`, …) in the given directory. + +Only clips containing `NSStringPboardType` are exported. Non-text clips are silently skipped. + +### Public Mutation API + +- `copyClipToPasteboard:(Clip *)clip` — writes all of the clip's types back to `[NSPasteboard generalPasteboard]` +- `copyClipToPasteboardAtIndex:(NSUInteger)index` — index into `sortedClips` +- `copyStringToPasteboard:(NSString *)aString` — writes a plain string +- `removeClip:(Clip *)` / `removeClipAtIndex:` — remove from the set (KVO-notified) +- `clearAll` — removes all objects (KVO-notified) + +--- + +## MenuController + +`Source/MenuController.m` — singleton. + +### Menu Types + +```objc +typedef enum { + CMPopUpMenuTypeMain, + CMPopUpMenuTypeHistory, + CMPopUpMenuTypeSnippets, + CMPopUpMenuTypeActions +} CMPopUpMenuType; +``` + +`popUpMenuForType:` constructs the appropriate menu and pops it up near the mouse cursor. + +### Status Item + +`createStatusItem` creates an `NSStatusItem` with icon `StatusMenuIcon.png` (normal) / `StatusMenuIcon_pressed.png` (highlighted). The menu is rebuilt on each open via `updateStatusMenu`. + +### Menu Construction + +`_buildClipMenu` produces the main clip menu: + +1. Add "Open Snippet Editor" and "Preferences" items. +2. Add a separator. +3. Optionally add snippets **above** clips (`CMPositionOfSnippetsAboveClips`). +4. Add clips via `_addClipsToMenu:`. +5. Optionally add snippets **below** clips (`CMPositionOfSnippetsBelowClips`). +6. Optionally add a "Clear History" item. + +`_addClipsToMenu:` iterates `[ClipsController sortedClips]`. For each clip it calls `_makeMenuItemForClip:withCount:andListNumber:`. + +**Inline vs. folder display:** +- `CMPrefNumberOfItemsPlaceInlineKey` clips appear directly in the menu. +- Remaining clips are grouped into submenus of size `CMPrefNumberOfItemsPlaceInsideFolderKey`, with a title like "11-20". +- If both prefs are 0, all clips appear inline. + +### Menu Item Construction (`_makeMenuItemForClip:`) + +1. Determine title: + - `trimTitle()` — strips leading/trailing whitespace, extracts first line, truncates to `CMPrefMaxMenuItemTitleLengthKey` chars with `"..."` suffix. + - If `CMPrefMenuItemsAreMarkedWithNumbersKey`, prefix with `". "` (number starts at 0 or 1 per `CMPrefMenuItemsTitleStartWithZeroKey`, wraps 10→0 when starting from 1). +2. If `CMPrefShowLabelsInMenuKey`, append the primary pasteboard type label. +3. For image clips, if `CMPrefShowImageInTheMenuKey`, use a thumbnail (`CMPrefThumbnailWidthKey` × `CMPrefThumbnailHeightKey`) as the menu item image. +4. If `CMPrefShowIconInTheMenuKey`, use `[Clip fileTypeIconForPboardType:]` scaled to `CMPrefMenuIconSizeKey` pixels as a leading icon. +5. If `CMPrefChangeFontSizeKey`, wrap the title in an `NSAttributedString` with the configured font size (auto: match icon size; manual: `CMPrefSelectedFontSizeKey`). +6. If `CMPrefShowToolTipOnMenuItemKey`, set a tooltip to the first `CMPrefMaxLengthOfToolTipKey` characters. +7. If `CMPrefAddNumericKeyEquivalentsKey`, set key equivalent to `"1"`…`"9"`, `"0"` for items 1–10. +8. Set `tag` = clip index in `sortedClips`. Set `action = @selector(selectMenuItem:)`, `target = AppController`. + +### Snippet Items + +Each enabled snippet in an enabled folder gets a menu item with `action = @selector(selectSnippetMenuItem:)` and `representedObject = NSManagedObject`. + +### Action Menu + +Built from `[ActionController actionNodes]` (a flat/tree list of `ActionNode`). Each leaf node becomes a menu item; container nodes become submenus. Items are filtered through `CMIsPerformableAction()` before being shown. `CMIsPerformableAction` checks the selected clip's types against the action's declared applicable types. + +### `trimTitle()` — title trimming function + +``` +1. NSString *strip — calls [clipString strip] (whitespace trim, defined in NSString+NaoAdditions) +2. getLineStart:end:contentsEnd:forRange: to find first line +3. If multi-line, truncate to contentsEnd +4. If length > maxMenuItemTitleLength, truncate to (max - 3) and append "..." +``` + +--- + +## AppController + +`Source/AppController.m` — loaded from MainMenu.xib. + +### Menu Item Selection + +**`selectMenuItem:sender`** (clips): +1. Call `_applyActionToTarget:sender`. If an action was applied, return. +2. Otherwise call `[ClipsController copyClipToPasteboardAtIndex:[sender tag]]`. +3. Call `[CMUtilities paste]`. + +**`selectSnippetMenuItem:sender`** (snippets): +1. Call `_applyActionToTarget:sender`. If an action was applied, return. +2. `copyStringToPasteboard:` the snippet's `content`. +3. `[CMUtilities paste]`. + +**`selectActionMenuItem:sender`**: +1. Get `NSDictionary *action` from `representedObject`. +2. Call `_invokeAction:`. + +### Modified-Click Detection (`_applyActionToTarget:`) + +Reads `[NSApp currentEvent]` modifier flags at the moment of selection: + +| Condition | Preference key | +|---|---| +| Right-click or Ctrl held | `CMPrefContorlClickBehaviorKey` | +| Shift held | `CMPrefShiftClickBehaviorKey` | +| Option held | `CMPrefOptionClickBehaviorKey` | +| Cmd held | `CMPrefCommandClickBehaviorKey` | + +The preference value is either: +- `kEmptyString` — no override +- `kPopUpActionMenu` — pop up the action selection menu +- `NSDictionary` (an action descriptor) — invoke that action directly + +### Action Invocation Flow + +`_invokeAction:action toIndex:index`: +- `index < 0` → target is `[ActionController selectedSnippet]` (a snippet `NSManagedObject`) +- `index >= 0` → target is `[ClipsController clipAtIndex:index]` +- Dispatches to `_invokeBuiltinAction:toTarget:` or `_invokeJavaScriptAction:atIndex:` + +`_invokeBuiltinAction:toTarget:` looks up the selector from `BuiltInActionController.actions[name]["actionName"]` and calls it via `performSelector:withObject:`. + +`_invokeJavaScriptAction:atIndex:`: +1. Gets the script path from the action dict. +2. Wraps the clip in a `ScriptableClip`. +3. Calls `[ActionController invokeScript:toClip:]`. +4. The result `Clip` is written back to the pasteboard. +5. `[CMUtilities paste]` is called. + +### Paste Implementation (`CMUtilities +paste`) + +Checks `CMPrefInputPasteCommandKey`. If YES, calls `postCommandV()`: +1. First call: scans all key codes 0–127 via `UCKeyTranslate` (TIS) to build a `string→keyCode` map and cache the keyCode for "V". +2. Creates `CGEventRef` key-down and key-up with `kCGEventFlagMaskCommand`. +3. Posts both to `kCGSessionEventTap`. + +### Process Management + +Before popping a menu, `keepCurrentFrontProcessAndActivate` records `GetFrontProcess(&frontPSN)` and brings ClipMenu to the front. After the menu closes (or after a paste), `restorePreviousFrontProcess` calls `SetFrontProcess(&frontPSN)` to give focus back to the original app. + +--- + +## ActionController + +`Source/ActionController.m` — singleton. + +### Initialization + +On `_init`, creates a hidden `WebView` (no frame, loads empty HTML string) used as the JavaScript execution engine. Also creates `ActionNodeFactory` and `BuiltInActionController`. + +The `WebView`'s policy delegate returns `[listener ignore]` for all navigation actions (prevents external resource access). + +### Action Node Tree + +Actions are stored as a flat `NSMutableArray` of `ActionNode` objects. Each node has: +- `title` — display name +- `isLeaf` — YES for executable actions, NO for folders/groups +- `children` — sub-nodes for folders +- `action` — `NSDictionary` for leaf nodes + +Action `NSDictionary` structure: +``` +{ + "type": "builtin" | "javaScript", + "name": "", // for builtins + "path": "