             
         case .none:
             return nil
+        }
+    }
+    
+}
+
+
+
+// MARK: -
+
+private enum HeaderFooterLocation {
+    
+    case header
+    case footer
+    
+    
+    struct Keys {
+        
+        var needsDraw: NSPrintInfo.AttributeKey
+        var primaryContent: NSPrintInfo.AttributeKey
+        var primaryAlignment: NSPrintInfo.AttributeKey
+        var secondaryContent: NSPrintInfo.AttributeKey
+        var secondaryAlignment: NSPrintInfo.AttributeKey
+    }
+    
+    
+    var keys: Keys {
+        
+        switch self {
+        case .header:
+            return Keys(needsDraw: .printsHeader,
+                        primaryContent: .primaryHeaderContent,
+                        primaryAlignment: .primaryHeaderAlignment,
+                        secondaryContent: .secondaryHeaderContent,
+                        secondaryAlignment: .secondaryHeaderAlignment)
+            
+        case .footer:
+            return Keys(needsDraw: .printsFooter,
+                        primaryContent: .primaryFooterContent,
+                        primaryAlignment: .primaryFooterAlignment,
+                        secondaryContent: .secondaryFooterContent,
+                        secondaryAlignment: .secondaryFooterAlignment)
         }
     }
     

    
    
    /// return attributed string for header/footer
    private func headerFooter(primaryString: String?, primaryAlignment: AlignmentType, secondaryString: String?, secondaryAlignment: AlignmentType) -> NSAttributedString {
        
        // case: empty
        guard primaryString != nil || secondaryString != nil else { return NSAttributedString() }
        
        // case: single content
        if let string = primaryString, secondaryString == nil {
            return NSAttributedString(string: string, attributes: self.headerFooterAttributes(for: primaryAlignment))
        }
        if let string = secondaryString, primaryString == nil {
            return NSAttributedString(string: string, attributes: self.headerFooterAttributes(for: secondaryAlignment))
        }
        guard let primaryString = primaryString, let secondaryString = secondaryString else { fatalError() }
        
        // case: double-sided
        if primaryAlignment == .left, secondaryAlignment == .right {
            return NSAttributedString(string: primaryString + "\t\t" + secondaryString, attributes: self.headerFooterAttributes(for: .left))
        }
        if primaryAlignment == .right, secondaryAlignment == .left {
            return NSAttributedString(string: secondaryString + "\t\t" + primaryString, attributes: self.headerFooterAttributes(for: .left))
        }
        
        // case: two lines
        let primaryAttrString = NSAttributedString(string: primaryString, attributes: self.headerFooterAttributes(for: primaryAlignment))
        let secondaryAttrString = NSAttributedString(string: secondaryString, attributes: self.headerFooterAttributes(for: secondaryAlignment))
        
        return primaryAttrString + NSAttributedString(string: "\n") + secondaryAttrString
    }
    
    

    /// return page header attributed string
    override var pageHeader: NSAttributedString {
        
        return self.headerFooter(for: .header)
    }
    
    
    /// return page footer attributed string
    override var pageFooter: NSAttributedString {
        
        return self.headerFooter(for: .footer)
    }
    
    
