fileEncoding
authorClaus Gittinger <cg@exept.de>
Tue, 17 Feb 2004 13:08:05 +0100
changeset 5528 54e3fbee2822
parent 5527 bbff3dc4085b
child 5529 f17c0b2a936d
fileEncoding
AbstractFileApplicationNoteBookComponent.st
AbstractFileBrowser.st
FileApplicationNoteBook.st
FileBrowser.st
FileBrowserV2.st
--- a/AbstractFileApplicationNoteBookComponent.st	Tue Feb 17 12:08:22 2004 +0100
+++ b/AbstractFileApplicationNoteBookComponent.st	Tue Feb 17 13:08:05 2004 +0100
@@ -115,6 +115,10 @@
     ^ ''
 !
 
+fileEncodingHolder
+    ^ #'ascii'
+!
+
 modeLabelHolder
     ^ ''
 ! !
@@ -240,5 +244,5 @@
 !AbstractFileApplicationNoteBookComponent class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileApplicationNoteBookComponent.st,v 1.10 2004-01-28 13:13:02 penk Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileApplicationNoteBookComponent.st,v 1.11 2004-02-17 12:08:05 cg Exp $'
 ! !
--- a/AbstractFileBrowser.st	Tue Feb 17 12:08:22 2004 +0100
+++ b/AbstractFileBrowser.st	Tue Feb 17 13:08:05 2004 +0100
@@ -1269,6 +1269,113 @@
     ^ ToolbarIconLibrary shell20x20Icon
 ! !
 
+!AbstractFileBrowser class methodsFor:'interface specs'!
+
+encodingDialogSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:AbstractFileBrowser andSelector:#encodingDialogSpec
+     AbstractFileBrowser new openInterface:#encodingDialogSpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(FullSpec
+        name: encodingDialogSpec
+        window: 
+       (WindowSpec
+          label: 'File Encoding'
+          name: 'File Encoding'
+          min: (Point 10 10)
+          bounds: (Rectangle 0 0 367 568)
+        )
+        component: 
+       (SpecCollection
+          collection: (
+           (LabelSpec
+              label: 'Label'
+              name: 'Select the Character Encoding'
+              layout: (LayoutFrame 0 0 0 0 0 1 30 0)
+              translateLabel: true
+              adjust: left
+            )
+           (DataSetSpec
+              name: 'Table1'
+              layout: (LayoutFrame 0 0 30 0 0 1 -30 1)
+              model: selectedEncoding
+              hasHorizontalScrollBar: true
+              hasVerticalScrollBar: true
+              dataList: encodingList
+              has3Dsepartors: true
+              has3Dseparators: true
+              doubleClickSelector: accept
+              columns: 
+             (OrderedCollection
+                
+               (DataSetColumnSpec
+                  label: 'Encoding'
+                  translateLabel: true
+                  labelButtonType: Button
+                  model: at:
+                  canSelect: false
+                  isResizeable: false
+                  showRowSeparator: false
+                  showColSeparator: false
+                ) 
+               (DataSetColumnSpec
+                  label: 'Description'
+                  translateLabel: true
+                  labelButtonType: Button
+                  model: at:
+                  canSelect: false
+                  isResizeable: false
+                  showRowSeparator: false
+                  showColSeparator: false
+                )
+              )
+            )
+           (HorizontalPanelViewSpec
+              name: 'HorizontalPanel1'
+              layout: (LayoutFrame 0 0 -30 1 0 1 0 1)
+              horizontalLayout: fitSpace
+              verticalLayout: center
+              horizontalSpace: 3
+              verticalSpace: 3
+              reverseOrderIfOKAtLeft: true
+              component: 
+             (SpecCollection
+                collection: (
+                 (ActionButtonSpec
+                    label: 'Cancel'
+                    name: 'Button2'
+                    translateLabel: true
+                    model: cancel
+                    extent: (Point 171 22)
+                  )
+                 (ActionButtonSpec
+                    label: 'OK'
+                    name: 'Button1'
+                    translateLabel: true
+                    model: accept
+                    isDefault: true
+                    extent: (Point 171 22)
+                  )
+                 )
+               
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
 !AbstractFileBrowser class methodsFor:'menu specs'!
 
 baseBookmarksMenuSpec
@@ -1360,6 +1467,11 @@
             translateLabel: true
           )
          (MenuItem
+            label: 'Encoding...'
+            itemValue: fileEncodingDialog
+            translateLabel: true
+          )
+         (MenuItem
             label: '-'
           )
          (MenuItem
@@ -2496,6 +2608,34 @@
     self fileGetInfo:true
 !
 
+fileEncodingDialog
+    "open a dialog to allow change of the files character encoding.
+     Files are converted to internal encoding when read, and converted back
+     to this encoding when saved.
+     The default encoding is nil, which means that files are already in
+     the internal encoding (which is iso8859).
+     Notice: currently, not too many encodings are supported by the system."
+
+    |bindings encodings encodingDescr idx selectedEncoding|
+
+    encodingDescr := CharacterEncoder supportedExternalEncodings.
+    encodings := encodingDescr collect:[:d | d isNil ifTrue:[nil] ifFalse:[d first]].
+
+    bindings := IdentityDictionary new.
+    bindings at:#encodingList put:encodingDescr.
+    bindings at:#selectedEncoding put:(encodings indexOf:self fileEncoding ifAbsent:1) asValue.
+    (self openDialogInterface:#encodingDialogSpec withBindings:bindings)
+    ifTrue:[
+        idx := (bindings at:#selectedEncoding) value.
+        selectedEncoding := encodings at:idx.
+        selectedEncoding notNil ifTrue:[
+            self fileEncoding:selectedEncoding.
+        ].
+    ].
+
+    "Modified: 30.6.1997 / 14:41:12 / cg"
+!
+
 fileGetInfo:longInfo 
     "get info on selected file - show it in a box"
 
@@ -2794,6 +2934,10 @@
         ]
 !
 
+defaultFileEncoding
+    ^ #'iso8859-1' "/ #'utf-8'
+!
+
 enableDirectoryUp
 
     ^ self aspectFor:#enableDirectoryUp ifAbsent:[false asValue]
@@ -2814,6 +2958,14 @@
     ^ self aspectFor:#enableViewNoteBookApplication ifAbsent:[false asValue]
 !
 
+fileEncoding
+    ^ self fileEncodingHolder value
+!
+
+fileEncoding:newEncoding
+    self fileEncodingHolder value:newEncoding
+!
+
 hasFileSelection
 
     ^ self aspectFor:#hasFileSelection ifAbsent:[ false asValue ].
@@ -6455,5 +6607,5 @@
 !AbstractFileBrowser class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileBrowser.st,v 1.202 2004-02-06 18:02:42 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileBrowser.st,v 1.203 2004-02-17 12:08:00 cg Exp $'
 ! !
--- a/FileApplicationNoteBook.st	Tue Feb 17 12:08:22 2004 +0100
+++ b/FileApplicationNoteBook.st	Tue Feb 17 13:08:05 2004 +0100
@@ -73,7 +73,7 @@
 		semaChangeItem wantToPrintAsHexDump printAsHexDump itemChanged
 		itemRemoved enableHexToggle md5CheckSum
 		md5HashValueComputationProcess viewModifiedChannel
-		textEditorModificationTime checkModifiedBlock fileEncoding'
+		textEditorModificationTime checkModifiedBlock fileEncodingHolder'
 	classVariableNames:''
 	poolDictionaries:''
 	privateIn:FileApplicationNoteBook
@@ -810,6 +810,14 @@
         ]
 !
 
+fileEncodingHolder
+    ^ self 
+        aspectFor:#fileEncodingHolder 
+        ifAbsent:[
+            IndirectValue for:('ascii' asValue)
+        ]
+!
+
 modeLabelHolder
     ^ self 
         aspectFor:#modeLabelHolder 
@@ -863,6 +871,7 @@
     self cursorLineLabelHolder valueHolder: (app cursorLineLabelHolder).
     self cursorColLabelHolder valueHolder: (app cursorColLabelHolder).
     self modeLabelHolder valueHolder: (app modeLabelHolder).
+    self fileEncodingHolder valueHolder: (app fileEncodingHolder).
 !
 
 update:something with:aParameter from:changedObject
@@ -4057,6 +4066,18 @@
 
 !FileApplicationNoteBook::TextEditor methodsFor:'accessing'!
 
+fileEncoding
+    ^ self fileEncodingHolder value
+!
+
+fileEncoding:fileEncodingArg
+    self fileEncodingHolder value:fileEncodingArg.
+
+    editView notNil ifTrue:[
+        editView externalEncoding:fileEncodingArg
+    ].
+!
+
 item:aDirContentsItem
 
     self releaseCheckModify.
@@ -4066,6 +4087,9 @@
     super item:aDirContentsItem.
     self printAsHexDump value:(self presentation == #hexDump) withoutNotifying:self.
     self setContents ifFalse:[ ^ false].
+
+    self setUpTextView.
+
     checkModifiedBlock isNil ifTrue:[
         checkModifiedBlock := [
             self enqueueMessage:#checkItemForChangesWithNewSetup 
@@ -4229,7 +4253,7 @@
         ] do:[
             present := self presentation.
             present == #asText ifTrue:[
-                contents := file contents.
+                contents := self getContentsAsText.
             ] ifFalse:[
                 present == #hexDump ifTrue:[
                     self withWaitCursorDo:[
@@ -4242,6 +4266,54 @@
     ^ contents.
 !
 
+getContentsAsText
+    |text guessedEncoding preferredFontEncoding fontsEncoding doNotShowFontDialog action
+     s|
+
+    guessedEncoding := FileBrowser guessEncodingOfFile:item fileName asFilename.
+    guessedEncoding := guessedEncoding ? (self fileEncoding).
+
+    editView notNil ifTrue:[
+        fontsEncoding := editView font encoding ? 'ascii'.
+
+        preferredFontEncoding := FontDescription preferredFontEncodingFor:guessedEncoding.
+        (CharacterEncoder isEncoding:preferredFontEncoding subSetOf:fontsEncoding) ifFalse:[
+                doNotShowFontDialog == true ifTrue:[
+                    action := #show
+                ] ifFalse:[
+                    action := Dialog choose:(resources string:'''%1'' seems to require a %2 font (file encoding is %3).' 
+                                                         with:self fileName baseName 
+                                                         with:preferredFontEncoding allBold 
+                                                         with:guessedEncoding)
+                                   labels:(resources array:#('Cancel' 'Show' 'Don''t Ask Again' 'Change Font'))
+                                   values:#(nil #show #showAlways #encoding)
+                                   default:#encoding.
+                ].
+                action == #showAlways ifTrue:[
+                    doNotShowFontDialog := true.
+                    action := #show.
+                ].
+                action isNil ifTrue:[
+                    AbortSignal raise
+                ].
+                action == #encoding ifTrue:[
+                    self fileEncoding:(guessedEncoding asSymbol).
+                    editView validateFontEncodingFor:self fileEncoding ask:false.
+                ] ifFalse:[
+"/                    doNotShowFontDialog ~~ true ifTrue:[
+"/                        self information:(resources string:'Individual characters may be invisible/wrong in this font.')
+"/                    ]
+                ].
+        ].
+        editView externalEncoding:self fileEncoding.
+    ].
+    self fileEncoding:(guessedEncoding asSymbol).
+
+    s := self fileName readStream.
+    text := self readStream:s lineDelimiter:(Character cr) encoding:self fileEncoding.
+    ^ text
+!
+
 getHashForContents:contents
     | hashStream|
 
@@ -4273,6 +4345,49 @@
     diffView topView label:'File ' , self fileName baseName , ' vs. Editor Contents'.
 !
 
+readStream:aStream lineDelimiter:aCharacter encoding:fileEncodingArg 
+    "read from aStream, answer its contents as StringCollection. 
+     The files lines are delimited by aCharacter.
+     If encoding is nonNil, the file is assumed to be coded according to
+     that symbol, and #decodeString: should be able to convert it."
+
+    |text line fileEncoding editorsEncoding encoder|
+
+    editView isNil ifTrue:[
+        editorsEncoding := #'iso8859-1'.
+    ] ifFalse:[
+        editorsEncoding := editView characterEncoding ? #'iso8859-1'.
+    ].
+    fileEncoding := fileEncodingArg ? #'iso8859-1'.
+    encoder := CharacterEncoder encoderToEncodeFrom:editorsEncoding into:fileEncoding.
+
+    text := StringCollection new.
+
+DecodingFailedError handle:[:ex|self halt]
+do:[
+    aCharacter == Character cr ifTrue:[
+        FileStream lineTooLongErrorSignal handle:[:ex |
+            |s partialLine|
+
+            s := ex parameter at:1.
+            partialLine := ex parameter at:2.
+            ex proceedWith:(partialLine , s upTo:aCharacter)
+        ] do:[
+            [aStream atEnd] whileFalse:[
+                line := aStream nextLine withTabsExpanded.
+                text add:(encoder decodeString:line)
+            ].
+        ].
+    ] ifFalse:[
+        [aStream atEnd] whileFalse:[
+            line := (aStream upTo:aCharacter) withTabsExpanded.
+            text add:(encoder decodeString:line)
+        ].
+    ].
+].
+    ^ text
+!
+
 reload
 
     textEditorModificationTime := self fileName modificationTime.
@@ -4335,12 +4450,15 @@
 !
 
 setContents
-    | text|
+    |text|
 
     text := self getContents.
     text isNil ifTrue:[ ^ false].
+
     self setContentsFor:text.
     ^ true
+
+
 !
 
 setContentsFor:aText
@@ -4459,6 +4577,13 @@
     ^ fileContentsModel.
 !
 
+fileEncodingHolder
+    fileEncodingHolder isNil ifTrue:[
+        fileEncodingHolder := #'utf-8' asValue
+    ].
+    ^ fileEncodingHolder
+!
+
 itemChanged
 
     itemChanged isNil ifTrue:[
@@ -4694,6 +4819,8 @@
     editView saveAction:[ self doSaveAs ].
 
     aWidget modifiedChannel:self viewModifiedChannel.
+
+    editView externalEncoding:self fileEncoding.
 !
 
 postBuildWith:aBuilder
@@ -4744,6 +4871,9 @@
                 editView parenthesisSpecification:parenthesis
             ].
         ].
+    ].
+    editView notNil ifTrue:[
+        editView externalEncoding:self fileEncoding.
     ]
 ! !
 
@@ -5238,5 +5368,5 @@
 !FileApplicationNoteBook class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/FileApplicationNoteBook.st,v 1.145 2004-02-12 13:20:12 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/FileApplicationNoteBook.st,v 1.146 2004-02-17 12:07:52 cg Exp $'
 ! !
--- a/FileBrowser.st	Tue Feb 17 12:08:22 2004 +0100
+++ b/FileBrowser.st	Tue Feb 17 13:08:05 2004 +0100
@@ -1467,17 +1467,17 @@
      If thats not found, use heuristics (in CharacterArray) to guess."
 
     |s buffer n "{Class: SmallInteger }"
-     binary idx w withoutQuotes isHTML lcBuffer|
+     binary idx w withoutQuotes isHTML lcBuffer enc|
 
     s := aFilename readStreamOrNil.
     s isNil ifTrue:[^ nil].
 
-    buffer := String new:4096.
-    n := s nextBytes:4096 into:buffer.
+    buffer := String new:2048.
+    n := buffer size.
+    n := s nextBytes:n into:buffer.
     s close.
 
     binary := false.
-    n := buffer size.
 
     withoutQuotes := 
         [ 
@@ -1504,7 +1504,13 @@
             s skipSeparators. 
             w := s upToSeparator.
             w notNil ifTrue:[
-                ^ (withoutQuotes value) asSymbol
+                enc := withoutQuotes value asSymbolIfInterned.
+                enc notNil ifTrue:[
+                    (CharacterEncoder unicodeEncoderFor:enc ifAbsent:nil) notNil ifTrue:[
+                        ^ enc
+                    ].
+                ].
+                Transcript showCR:'Unknown encoding: ' , withoutQuotes value.
             ].
         ].
     ].
@@ -2266,9 +2272,9 @@
 
     list := SelectionInList new.
 
-    descr := CharacterArray supportedExternalEncodings.
-    encodings := descr at:2.
-    encodingNames := descr at:1.
+    descr := CharacterEncoder supportedExternalEncodings.
+    encodings := descr map:#first.
+    encodingNames := descr map:#second.
 
     list list:encodingNames.
     list selectionIndex:(encodings indexOf:fileEncoding ifAbsent:1).
@@ -7500,5 +7506,5 @@
 !FileBrowser class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/FileBrowser.st,v 1.577 2004-02-16 16:56:14 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowser.st,v 1.578 2004-02-17 12:07:44 cg Exp $'
 ! !
--- a/FileBrowserV2.st	Tue Feb 17 12:08:22 2004 +0100
+++ b/FileBrowserV2.st	Tue Feb 17 13:08:05 2004 +0100
@@ -502,7 +502,7 @@
           label: FileBrowser
           name: FileBrowser
           min: (Point 10 10)
-          bounds: (Rectangle 0 0 800 700)
+          bounds: (Rectangle 0 0 920 1598)
           menu: mainMenu
           icon: applicationIcon
         )
@@ -674,6 +674,15 @@
                     labelChannel: notifyChannel
                     adjust: left
                   )
+                 (LabelSpec
+                    label: 'encoding'
+                    name: 'EncodingLabel'
+                    layout: (LayoutFrame -307 1 2 0.0 -221 1 0 1.0)
+                    level: 0
+                    labelChannel: fileEncodingHolder
+                    adjust: right
+                    menu: encodingMenu
+                  )
                  (ProgressIndicatorSpec
                     name: 'ProgressIndicator1'
                     layout: (LayoutFrame -260 1 4 0 -220 1 -4 1)
@@ -775,6 +784,34 @@
 
 !FileBrowserV2 class methodsFor:'menu specs'!
 
+encodingMenu
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:FileBrowserV2 andSelector:#encodingMenu
+     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 encodingMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(Menu
+        (
+         (MenuItem
+            label: 'Encoding...'
+            itemValue: fileEncodingDialog
+            translateLabel: true
+          )
+         )
+        nil
+        nil
+      )
+!
+
 mainMenu
     "This resource specification was automatically generated
      by the MenuEditor of ST/X."
@@ -1208,6 +1245,16 @@
         ]
 !
 
+fileEncodingHolder
+    ^ self 
+        aspectFor:#fileEncodingHolder 
+        ifAbsent:[
+            self 
+                applicationNamed:#FileApplicationNoteBook
+                ifPresentDo:[:appl | appl fileEncodingHolder].
+        ]
+!
+
 fileEntryFieldHolder
 
     fileEntryFieldHolder isNil ifTrue:[
@@ -1650,7 +1697,7 @@
 !FileBrowserV2 class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2.st,v 1.105 2004-02-02 17:11:53 penk Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2.st,v 1.106 2004-02-17 12:07:37 cg Exp $'
 ! !
 
 FileBrowserV2 initialize!