123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- //
- // KMDocumentController.swift
- // PDF Reader Pro
- //
- // Created by wanjun on 2022/12/5.
- //
- import Cocoa
- let KMPDFDocumentType: String = "com.adobe.pdf"
- let KMPDFBundleDocumentType: String = "net.sourceforge.skim-app.pdfd"
- let KMNotesDocumentType: String = "net.sourceforge.skim-app.skimnotes"
- let KMNotesTextDocumentType: String = "public.plain-text"
- let KMNotesRTFDocumentType: String = "public.rtf"
- let KMNotesRTFDDocumentType: String = "com.apple.rtfd"
- let KMNotesFDFDocumentType: String = "com.adobe.fdf"
- let KMPostScriptDocumentType: String = "com.adobe.postscript"
- let KMEncapsulatedPostScriptDocumentType: String = "com.adobe.encapsulated-postscript"
- let KMDVIDocumentType: String = "org.tug.tex.dvi"
- let KMXDVDocumentType: String = "org.tug.tex.xdv"
- let KMFolderDocumentType: String = "public.folder"
- let KMDocumentSetupAliasKey: String = "_BDAlias"
- let KMDocumentSetupFileNameKey: String = "fileName"
- class KMDocumentController: NSDocumentController {
-
- func fetchUniquePath(_ originalPath: String) -> String {
- var path = originalPath
- let dManager = FileManager.default
- if !dManager.fileExists(atPath: path) {
- if path.extension.count < 1 {
- path = path.stringByAppendingPathExtension("pdf")
- }
- return path
- } else {
- let originalFullFileName = path.lastPathComponent
- let originalFileName = path.lastPathComponent.deletingPathExtension.lastPathComponent
- let originalExtension = path.extension
- let startIndex: Int = 0
- let endIndex: Int = startIndex + originalPath.count - originalFullFileName.count - 1
- let fileLocatePath = originalPath.substring(to: endIndex)
- var i = 1
- while (1 != 0) {
- var newName = String(format: "%@%ld", originalFileName, i)
- newName = String(format: "%@%@", newName, originalExtension)
- let newPath = fileLocatePath.stringByAppendingPathComponent(newName)
- if !dManager.fileExists(atPath: newPath) {
- return newPath
- } else {
- i+=1
- continue
- }
- }
- }
- }
-
- func kNewDocumentTempSavePath(_ fileName: String) -> String {
- let searchPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last
- let append1 = searchPath?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!)
- let append2 = append1!.stringByAppendingPathComponent(String(format: "%@", fileName))
- return append2
- }
-
- func savePdf(_ filePath: String) -> Void {
- let pdfData = try! Data(contentsOf: URL(fileURLWithPath: filePath))
- let document = try! self.makeUntitledDocument(ofType: KMPDFDocumentType) as NSDocument
- if ((try? document.read(from: pdfData, ofType: KMPDFDocumentType)) != nil) {
- self.addDocument(document)
- document.makeWindowControllers()
- document.showWindows()
- }
-
- }
-
- // MARK: Action
-
- @IBAction func importFromFile(_ sender: Any) {
-
- }
-
- @IBAction func openBlankPage(_ sender: Any) {
- let fileName = String(format: "%@.pdf", NSLocalizedString("Untitled", comment: ""))
- let savePath = fetchUniquePath(kNewDocumentTempSavePath(fileName))
- let pdfDocument = CPDFDocument()
- pdfDocument?.insertPage(CGSize(width: 595, height: 842), at: 0)
- pdfDocument?.write(to: URL(fileURLWithPath: savePath))
- NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePath), display: true) { document, documentWasAlreadyOpen, error in
- if error != nil {
- NSApp.presentError(error!)
- return
- }
- if document is KMMainDocument {
- let newDocument = document
- (newDocument as! KMMainDocument).isNewCreated = false
- }
- }
- }
- @IBAction func newDocumentFromImage(_ sender: Any) {
- // let openPanel = NSOpenPanel()
- // openPanel.allowedFileTypes = KMImageAccessoryController.supportedImageTypes()
- // openPanel.allowsMultipleSelection = true
- // openPanel.message = NSLocalizedString("Select images to create a new document. To select multiple files press cmd ⌘ button on keyboard and click on the target files one by one.", comment: "")
- // openPanel.beginSheetModal(for: NSApp.mainWindow!) { response in
- // let savePath = self.kNewDocumentTempSavePath("convertToPDF.pdf")
- // if response == .OK {
- // KMConvertPDFManager.convertImages(openPanel.urls, savePath: savePath) { success, errorDic in
- // if !success || !FileManager.default.fileExists(atPath: savePath) {
- // if FileManager.default.fileExists(atPath: savePath) {
- // try? FileManager.default.removeItem(atPath: savePath)
- // }
- //
- // let alert = NSAlert()
- // alert.alertStyle = .critical
- // alert.messageText = NSLocalizedString("Conversion Failed", comment: "")
- // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
- // alert.runModal()
- // return
- // }
- // self.savePdf(savePath)
- // try? FileManager.default.removeItem(atPath: savePath)
- // }
- // }
- // }
- }
-
- @IBAction func importFromWebPage(_ sender: Any) {
-
- }
-
- @IBAction func importFromScanner(_ sender: Any) {
-
- }
- }
- extension NSDocumentController {
- func openDocumentWithURLFromPasteboard(_ pboard: NSPasteboard, showNotes: Bool, outError: NSErrorPointer) -> Any? {
- guard let theURLs = NSURL.readURLs(from: pboard), let theURL = theURLs.first else {
- if showNotes == false {
- outError?.pointee = NSError.readPasteboardError(withLocalizedDescription: NSLocalizedString("Unable to load data from clipboard", comment: "Error description"))
- }
- return nil
- }
-
- // guard (theURL as AnyObject).isFileURL else {
- // if showNotes == false {
- // return SKDownloadController.shared.addDownload(for: theURL)
- // }
- // return nil
- // }
-
- var document: Any?
- do {
- let type = try self.typeForContents(of: theURL as! URL)
- // if showNotes == false || KMNotesDocument.readableTypes.contains(type) {
- // document = try self.openDocument(withContentsOf: theURL as! URL, display: true)
- // } else
- if KMMainDocument.readableTypes.contains(type) {
- for doc in self.documents {
- if let sourceURL = (doc as? NSObject)?.value(forKey: "sourceFileURL") as? URL, sourceURL == theURL as! URL {
- document = doc
- break
- }
- }
- if let existingDoc = document as? NSDocument {
- existingDoc.showWindows()
- } else {
- var error: NSError?
- var data: Data?
-
- if NSWorkspace.shared.type(type, conformsToType: KMPDFBundleDocumentType) {
- let skimFileURL = try self.bundledFileURLWithExtension("skim", inPDFBundleAtURL: theURL as! URL)
- data = try Data(contentsOf: skimFileURL)
-
- }
- // else {
- // data = try SKNExtendedAttributeManager.shared().extendedAttributeNamed(SKIM_NOTES_KEY, atPath: theURL.path, traverseLink: true)
- // }
-
- // let newDocument = try makeUntitledDocument(ofType: KMNotesDocumentType)
- // newDocument.sourceFileURL = theURL
- //
- // if data == nil || newDocument.read(from: data ?? Data(), ofType: KMNotesDocumentType) {
- // self.addDocument(newDocument)
- // newDocument.makeWindowControllers()
- // newDocument.showWindows()
- // } else {
- // document = nil
- // outError?.pointee = error
- // }
- }
- }
- } catch {
- outError?.pointee = error as NSError
- }
-
- return document
- }
-
- func bundledFileURLWithExtension(_ extension: String, inPDFBundleAtURL theURL: URL) throws -> URL {
- let bundleContents = try FileManager.default.contentsOfDirectory(at: theURL, includingPropertiesForKeys: nil, options: [])
- for fileURL in bundleContents {
- if fileURL.pathExtension == `extension` {
- return fileURL
- }
- }
- throw NSError(domain: "YourDomain", code: 404, userInfo: [NSLocalizedDescriptionKey: "File with extension not found in PDF bundle"])
- }
-
- func openDocumentWithImageFromPasteboard(_ pboard: NSPasteboard, error outError: NSErrorPointer) -> Any? {
- var document: NSDocument?
- var data: Data?
- var type: String?
-
- if pboard.canReadItem(withDataConformingToTypes: [NSPasteboard.PasteboardType.pdf.rawValue]) {
- pboard.types
- data = pboard.data(forType: NSPasteboard.PasteboardType.pdf)
- type = KMPDFDocumentType
- } else if pboard.canReadItem(withDataConformingToTypes: [KMEncapsulatedPostScriptDocumentType]) {
- pboard.types
- data = pboard.data(forType: NSPasteboard.PasteboardType(rawValue: KMEncapsulatedPostScriptDocumentType))
- type = isEncapsulatedPostScriptData(data!) ? KMEncapsulatedPostScriptDocumentType : KMPostScriptDocumentType
- } else if pboard.canReadItem(withDataConformingToTypes: [NSPasteboard.PasteboardType.tiff.rawValue]) {
- pboard.types
- data = convertTIFFDataToPDF(pboard.data(forType: NSPasteboard.PasteboardType.tiff)!)
- type = KMPDFDocumentType
- } else {
- let images = pboard.readObjects(forClasses: [NSImage.self], options: [:]) as? [NSImage]
- let strings = pboard.readObjects(forClasses: [NSAttributedString.self], options: [:]) as? [NSAttributedString]
- if let images = images, images.count > 0 {
- data = convertTIFFDataToPDF(images[0].tiffRepresentation!)
- type = KMPDFDocumentType
- } else if let strings = strings, strings.count > 0 {
- data = KMOCTool.convertStringsToPDF(withString: strings) // convertStringsToPDF(strings!)
- type = KMPDFDocumentType
- }
- }
-
- if let data = data, let type = type {
- var error: NSError?
-
- document = try?makeUntitledDocument(ofType: type)
-
- if ((try?document?.read(from: data, ofType:type)) != nil) {
- addDocument(document!)
- document?.makeWindowControllers()
- document?.showWindows()
- } else {
- document = nil
- if let outError = outError {
- outError.pointee = error
- }
- }
- } else if let outError = outError {
- outError.pointee = NSError.readPasteboardError(withLocalizedDescription: NSLocalizedString("Unable to load data from clipboard", comment: "Error description"))
- }
-
- return document
- }
-
- func isEncapsulatedPostScriptData(_ data: Data) -> Bool {
- let epsHeaderData = Data(bytes: [69, 80, 83, 70, 45], count: 5)
- let rg: Range = (14..<20)
- return (data.count >= 20 && (data.range(of: epsHeaderData, options: .anchored, in: rg) != nil))
- }
-
- func convertTIFFDataToPDF(_ tiffData: Data) -> Data? {
- guard let imsrc = CGImageSourceCreateWithData(tiffData as CFData, [kCGImageSourceTypeIdentifierHint: kUTTypeTIFF] as CFDictionary), CGImageSourceGetCount(imsrc) > 0, let cgImage = CGImageSourceCreateImageAtIndex(imsrc, 0, nil) else { return nil }
- let pdfData = NSMutableData(capacity: tiffData.count)
- let consumer = CGDataConsumer(data: pdfData! as CFMutableData)!
-
- var rect = CGRect(x: 0, y: 0, width: CGFloat(cgImage.width), height: CGFloat(cgImage.height))
- let ctxt = CGContext(consumer: consumer, mediaBox: &rect, nil)
- ctxt!.beginPDFPage(nil)
- ctxt!.draw(cgImage, in: rect)
- ctxt!.endPDFPage()
- ctxt!.closePDF()
-
- return pdfData as? Data
- }
- }
|