Commit cd4b838a authored by Pedro Castro's avatar Pedro Castro

Fix #140: Allow to save UTF-8 files with or without a BOM

The BOM is written by default
parent 70e81d14
/*
* This file is part of Gnome Subtitles.
* Copyright (C) 2006-2018 Pedro Castro
* Copyright (C) 2006-2019 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -261,14 +261,14 @@ public class Document {
private Encoding GetFallbackEncoding () {
ConfigFileOpenFallbackEncoding fallbackEncodingConfig = Base.Config.FileOpenFallbackEncoding;
if (fallbackEncodingConfig == ConfigFileOpenFallbackEncoding.CurrentLocale)
if (fallbackEncodingConfig == ConfigFileOpenFallbackEncoding.CurrentLocale) {
return Encodings.GetEncoding(Encodings.SystemDefault.CodePage);
else {
string encodingName = Base.Config.FileOpenFallbackEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
return Encodings.GetEncoding(encodingDescription.CodePage);
}
string encodingCode = Base.Config.FileOpenFallbackEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingCode, ref encodingDescription);
return Encodings.GetEncoding(encodingDescription.CodePage);
}
private FileProperties CreateNewTextFileProperties () {
......
/*
* This file is part of Gnome Subtitles.
* Copyright (C) 2007-2010 Pedro Castro
* Copyright (C) 2007-2019 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -23,39 +23,51 @@ namespace GnomeSubtitles.Core {
public struct EncodingDescription : IComparable {
private int codePage;
private string code;
private string name;
private string description;
private string region;
private static EncodingDescription emptyEncodingDescription = new EncodingDescription(-1, "-1", "-1");
public EncodingDescription (int codePage, string name, string description) {
public EncodingDescription (int codePage, string code, string region, string name) {
this.codePage = codePage;
this.code = code;
this.region = region;
this.name = name;
this.description = description;
}
//Use the code as name too
public EncodingDescription (int codePage, string code, string region)
: this(codePage, code, region, code) {
}
public int CodePage {
get { return codePage; }
}
public string Code {
get { return code; }
}
public string Region {
get { return region; }
}
public string Name {
get { return name; }
}
public string Description {
get { return description; }
}
public int CompareTo (object obj) {
if (obj is EncodingDescription) {
EncodingDescription obj2 = (EncodingDescription)obj;
int descComparison = this.description.CompareTo(obj2.description);
if (descComparison != 0)
return descComparison;
else
return this.name.CompareTo(obj2.name);
}
else
if (!(obj is EncodingDescription)) {
throw new ArgumentException("Object is not EncodingDescription");
}
EncodingDescription obj2 = (EncodingDescription)obj;
int result = this.region.CompareTo(obj2.region);
if (result != 0) {
return result;
}
return this.name.CompareTo(obj2.name);
}
/* Static members */
......
/*
* This file is part of Gnome Subtitles.
* Copyright (C) 2007-2018 Pedro Castro
* Copyright (C) 2007-2019 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -27,7 +27,9 @@ public class Encodings {
/* UTF8 encoding is constructed in a different manner in order to disable the BOM. */
private static int CODEPAGE_UTF8 = 65001;
private static int CODEPAGE_UTF8_WITHOUT_BOM = 650010; //Unofficial codepage, for internal use only
private static Encoding encodingUTF8 = null;
private static Encoding encodingUTF8WithoutBOM = null;
/* The original versions of the following tables were taken from gedit
* which on the other hand took them from profterm
......@@ -51,6 +53,8 @@ public class Encodings {
/* ISO-8859-8-I not used */
new EncodingDescription(CODEPAGE_UTF8, "UTF-8", Catalog.GetString("Unicode")), /* Added */
new EncodingDescription(CODEPAGE_UTF8_WITHOUT_BOM, "UTF-8-NO-BOM", Catalog.GetString("Unicode"), Catalog.GetString("UTF-8 without BOM")), /* Added */
new EncodingDescription(65000, "UTF-7", Catalog.GetString("Unicode")),
new EncodingDescription(1200, "UTF-16", Catalog.GetString("Unicode")), //Little endian
new EncodingDescription(1201, "UTF-16BE", Catalog.GetString("Unicode")),
......@@ -119,35 +123,40 @@ public class Encodings {
public static EncodingDescription SystemDefault {
get {
string description = Catalog.GetString("Current Locale");
string region = Catalog.GetString("Current Locale");
Encoding defaultEncoding = Encoding.Default;
int codePage = defaultEncoding.CodePage;
string code = String.Empty;
string name = String.Empty;
EncodingDescription tempDesc = EncodingDescription.Empty;
if (Find(codePage, ref tempDesc))
if (Find(codePage, ref tempDesc)) {
code = tempDesc.Code;
name = tempDesc.Name;
else
} else {
name = defaultEncoding.WebName.ToUpper();
code = name;
}
return new EncodingDescription(codePage, name, description);
return new EncodingDescription(codePage, code, region, name);
}
}
/* Public methods */
/// <summary>Finds the description for the encoding with the specified name.</summary>
/// <param name="name">The encoding's name.</param>
/// <param name="code">The encoding's code.</param>
/// <param name="description">The encoding's description that was found.</param>
/// <returns>Whether the description was found.</returns>
public static bool Find (string name, ref EncodingDescription description) {
public static bool Find (string code, ref EncodingDescription description) {
foreach (EncodingDescription desc in descriptions) {
if (desc.Name == name) {
if (desc.Code == code) {
description = desc;
return true;
}
}
return false;
}
......@@ -178,12 +187,22 @@ public class Encodings {
}
public static Encoding GetEncoding (int codePage) {
//We output UTF-8 with BOM by default
if (codePage == CODEPAGE_UTF8) {
if (encodingUTF8 == null) {
encodingUTF8 = new UTF8Encoding(false);
encodingUTF8 = new UTF8Encoding(true);
}
return encodingUTF8;
}
//UTF-8 without BOM
if (codePage == CODEPAGE_UTF8_WITHOUT_BOM) {
if (encodingUTF8WithoutBOM == null) {
encodingUTF8WithoutBOM = new UTF8Encoding(false);
}
return encodingUTF8WithoutBOM;
}
return Encoding.GetEncoding(codePage);
}
......
......@@ -26,11 +26,12 @@ using System;
namespace GnomeSubtitles.Dialog {
public class EncodingsDialog : BaseDialog {
private string[] chosenNames = new string[0];
private string[] chosenCodes = new string[0];
/* Constant integers */
const int descColumnNum = 0; //The number of the Description column
const int nameColumnNum = 1; //The number of the Name column
const int RegionColumnNum = 0; //The number of the Region column
const int NameColumnNum = 1; //The number of the Name column
const int CodeColumnNum = 2; //The number of the hidden Code column
/* Widgets */
......@@ -45,8 +46,8 @@ public class EncodingsDialog : BaseDialog {
/* Public properties */
public string[] ChosenNames {
get { return chosenNames; }
public string[] ChosenCodes {
get { return chosenCodes; }
}
/* Private members */
......@@ -111,9 +112,9 @@ public class EncodingsDialog : BaseDialog {
private void FillAvailableEncodings () {
SetColumns(availableTreeView);
ListStore store = new ListStore(typeof(string), typeof(string));
ListStore store = new ListStore(typeof(string), typeof(string), typeof(string));
foreach (EncodingDescription desc in Encodings.All) {
store.AppendValues(desc.Description, desc.Name);
store.AppendValues(desc.Region, desc.Name, desc.Code);
}
SetModel(availableTreeView, store);
......@@ -122,31 +123,36 @@ public class EncodingsDialog : BaseDialog {
private void FillShownEncodings () {
SetColumns(shownTreeView);
chosenNames = Base.Config.FileEncodingsShownInMenu;
chosenCodes = Base.Config.FileEncodingsShownInMenu;
ListStore store = new ListStore(typeof(string), typeof(string));
foreach (string shownEncoding in chosenNames) {
ListStore store = new ListStore(typeof(string), typeof(string), typeof(string));
foreach (string shownEncodingCode in chosenCodes) {
EncodingDescription desc = EncodingDescription.Empty;
if (Encodings.Find(shownEncoding, ref desc))
store.AppendValues(desc.Description, desc.Name);
if (Encodings.Find(shownEncodingCode, ref desc)) {
store.AppendValues(desc.Region, desc.Name, desc.Code);
}
}
SetModel(shownTreeView, store);
}
private void SetColumns (TreeView tree) {
TreeViewColumn descriptionColumn = new TreeViewColumn(Catalog.GetString("Description"), new CellRendererText(), "text", descColumnNum);
descriptionColumn.SortColumnId = descColumnNum;
TreeViewColumn descriptionColumn = new TreeViewColumn(Catalog.GetString("Description"), new CellRendererText(), "text", RegionColumnNum);
descriptionColumn.SortColumnId = RegionColumnNum;
tree.AppendColumn(descriptionColumn);
TreeViewColumn nameColumn = new TreeViewColumn(Catalog.GetString("Encoding"), new CellRendererText(), "text", nameColumnNum);
nameColumn.SortColumnId = nameColumnNum;
TreeViewColumn nameColumn = new TreeViewColumn(Catalog.GetString("Encoding"), new CellRendererText(), "text", NameColumnNum);
nameColumn.SortColumnId = NameColumnNum;
tree.AppendColumn(nameColumn);
TreeViewColumn codeColumn = new TreeViewColumn("-", new CellRendererText(), "text", CodeColumnNum);
codeColumn.Visible = false;
tree.AppendColumn(codeColumn);
}
private void SetModel (TreeView tree, ListStore store) {
TreeModelSort storeSort = new TreeModelSort(store);
storeSort.SetSortColumnId(descColumnNum, SortType.Ascending);
storeSort.SetSortColumnId(RegionColumnNum, SortType.Ascending);
tree.Model = storeSort;
}
......@@ -170,34 +176,36 @@ public class EncodingsDialog : BaseDialog {
}
private void AddToShownEncodings (EncodingDescription desc) {
if (!IsAlreadyShown(desc.Name)) {
GetListStore(shownTreeView).AppendValues(desc.Description, desc.Name);
if (!IsAlreadyShown(desc.Code)) {
GetListStore(shownTreeView).AppendValues(desc.Region, desc.Name, desc.Code);
UpdateShownEncodingsPrefs();
}
}
private string[] GetShownNames () {
private string[] GetShownCodes () {
ListStore store = GetListStore(shownTreeView);
int count = store.IterNChildren();
string[] names = new string[count];
string[] codes = new string[count];
int rowNumber = 0;
foreach (object[] row in store) {
names[rowNumber] = row[nameColumnNum] as string;
codes[rowNumber] = row[CodeColumnNum] as string;
rowNumber++;
}
return names;
return codes;
}
private bool IsAlreadyShown (string name) {
private bool IsAlreadyShown (string code) {
ListStore store = GetListStore(shownTreeView);
foreach (object[] row in store) {
if ((row == null) || (row.Length != 2))
if ((row == null) || (row.Length < CodeColumnNum + 1)) {
continue;
}
string rowName = row[nameColumnNum] as string;
if (rowName == name)
string rowCode = row[CodeColumnNum] as string;
if (rowCode == code) {
return true;
}
}
return false;
}
......@@ -224,8 +232,8 @@ public class EncodingsDialog : BaseDialog {
}
private void UpdateShownEncodingsPrefs () {
chosenNames = GetShownNames();
Base.Config.FileEncodingsShownInMenu = chosenNames;
chosenCodes = GetShownCodes();
Base.Config.FileEncodingsShownInMenu = chosenCodes;
}
......@@ -269,4 +277,4 @@ public class EncodingsDialog : BaseDialog {
}
}
}
\ No newline at end of file
......@@ -149,9 +149,9 @@ public class FileOpenDialog : BaseDialog {
int fixedEncoding = -1;
ConfigFileOpenEncoding encodingConfig = Base.Config.FileOpenEncoding;
if (encodingConfig == ConfigFileOpenEncoding.Fixed) {
string encodingName = Base.Config.FileOpenEncodingFixed;
string encodingCode = Base.Config.FileOpenEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
fixedEncoding = encodingDescription.CodePage;
}
......@@ -315,7 +315,7 @@ public class FileOpenDialog : BaseDialog {
int activeAction = encodingComboBox.ActiveSelection;
ConfigFileOpenEncoding activeOption = (ConfigFileOpenEncoding)Enum.ToObject(typeof(ConfigFileOpenEncoding), activeAction);
if (((int)activeOption) >= ((int)ConfigFileOpenEncoding.Fixed))
Base.Config.FileOpenEncodingFixed = chosenEncoding.Name;
Base.Config.FileOpenEncodingFixed = chosenEncoding.Code;
else
Base.Config.FileOpenEncoding = activeOption;
}
......
/*
* This file is part of Gnome Subtitles.
* Copyright (C) 2006-2018 Pedro Castro
* Copyright (C) 2006-2019 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -148,9 +148,9 @@ public class FileSaveDialog : BaseDialog {
int fixedEncoding = GetFixedEncoding();
ConfigFileSaveEncoding encodingConfig = Base.Config.FileSaveEncoding;
if (encodingConfig == ConfigFileSaveEncoding.Fixed) {
string encodingName = Base.Config.FileSaveEncodingFixed;
string encodingCode = Base.Config.FileSaveEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
fixedEncoding = encodingDescription.CodePage;
}
......@@ -243,7 +243,7 @@ public class FileSaveDialog : BaseDialog {
int activeAction = encodingComboBox.ActiveSelection;
ConfigFileSaveEncoding activeOption = (ConfigFileSaveEncoding)Enum.ToObject(typeof(ConfigFileSaveEncoding), activeAction);
if (((int)activeOption) >= ((int)ConfigFileSaveEncoding.Fixed)) {
Base.Config.FileSaveEncodingFixed = chosenEncoding.Name;
Base.Config.FileSaveEncodingFixed = chosenEncoding.Code;
}
else {
Base.Config.FileSaveEncoding = activeOption;
......
......@@ -213,9 +213,9 @@ public class PreferencesDialog : BaseDialog {
int fixedEncoding = -1;
ConfigFileOpenEncodingOption fileOpenEncodingOption = Base.Config.FileOpenEncodingOption;
if (fileOpenEncodingOption == ConfigFileOpenEncodingOption.Specific) {
string encodingName = Base.Config.FileOpenEncodingFixed;
string encodingCode = Base.Config.FileOpenEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
fixedEncoding = encodingDescription.CodePage;
}
......@@ -232,9 +232,9 @@ public class PreferencesDialog : BaseDialog {
int fixedEncoding = -1;
ConfigFileOpenFallbackEncoding fileOpenFallbackEncodingConfig = Base.Config.FileOpenFallbackEncoding;
if (fileOpenFallbackEncodingConfig == ConfigFileOpenFallbackEncoding.Fixed) {
string encodingName = Base.Config.FileOpenFallbackEncodingFixed;
string encodingCode = Base.Config.FileOpenFallbackEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
fixedEncoding = encodingDescription.CodePage;
}
......@@ -248,9 +248,9 @@ public class PreferencesDialog : BaseDialog {
int fixedEncoding = -1;
ConfigFileSaveEncodingOption fileSaveEncodingOption = Base.Config.FileSaveEncodingOption;
if (fileSaveEncodingOption == ConfigFileSaveEncodingOption.Specific) {
string encodingName = Base.Config.FileSaveEncodingFixed;
string encodingCode = Base.Config.FileSaveEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
fixedEncoding = encodingDescription.CodePage;
}
......@@ -308,7 +308,7 @@ public class PreferencesDialog : BaseDialog {
if (activeOption == ConfigFileOpenEncodingOption.Specific) {
EncodingDescription chosenEncoding = fileOpenEncoding.ChosenEncoding;
if (!chosenEncoding.Equals(EncodingDescription.Empty)) {
Base.Config.FileOpenEncodingFixed = chosenEncoding.Name;
Base.Config.FileOpenEncodingFixed = chosenEncoding.Code;
}
}
else {
......@@ -327,7 +327,7 @@ public class PreferencesDialog : BaseDialog {
else {
EncodingDescription chosenEncoding = fileOpenFallbackEncoding.ChosenEncoding;
if (!chosenEncoding.Equals(EncodingDescription.Empty)) {
Base.Config.FileOpenFallbackEncodingFixed = chosenEncoding.Name;
Base.Config.FileOpenFallbackEncodingFixed = chosenEncoding.Code;
}
}
}
......@@ -343,7 +343,7 @@ public class PreferencesDialog : BaseDialog {
if (activeOption == ConfigFileSaveEncodingOption.Specific) {
EncodingDescription chosenEncoding = fileSaveEncoding.ChosenEncoding;
if (!chosenEncoding.Equals(EncodingDescription.Empty)) {
Base.Config.FileSaveEncodingFixed = chosenEncoding.Name;
Base.Config.FileSaveEncodingFixed = chosenEncoding.Code;
}
}
else {
......
/*
* This file is part of Gnome Subtitles.
* Copyright (C) 2006-2017 Pedro Castro
* Copyright (C) 2006-2019 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -103,8 +103,8 @@ public class EncodingComboBox {
this.actionCount = (hasAutoDetect ? 1 : 0) + (additionalActions != null ? additionalActions.Length : 0);
}
private void SetComboBox (string[] names) {
configShownEncodings = new ArrayList(names);
private void SetComboBox (string[] codes) {
configShownEncodings = new ArrayList(codes);
LoadEncodings();
FillComboBox();
}
......@@ -113,9 +113,9 @@ public class EncodingComboBox {
bool toAddFixedEncoding = (fixedEncoding != -1);
ArrayList encodings = new ArrayList();
foreach (string name in configShownEncodings) {
foreach (string code in configShownEncodings) {
EncodingDescription description = EncodingDescription.Empty;
if (Encodings.Find(name, ref description)) {
if (Encodings.Find(code, ref description)) {
encodings.Add(description);
if (toAddFixedEncoding && (description.CodePage == fixedEncoding))
toAddFixedEncoding = false;
......@@ -163,7 +163,7 @@ public class EncodingComboBox {
/* Add encodings */
foreach (EncodingDescription encoding in encodings) {
comboBox.AppendText(encoding.Description + " (" + encoding.Name + ")");
comboBox.AppendText(encoding.Region + " (" + encoding.Name + ")");
if (encoding.CodePage == fixedEncoding) {
activeItem = currentItem;
}
......@@ -221,8 +221,7 @@ public class EncodingComboBox {
EncodingsDialog dialog = Base.Dialogs.Get(typeof(EncodingsDialog), comboBox.Toplevel) as EncodingsDialog;
dialog.Show();
dialog.WaitForResponse();
SetComboBox(dialog.ChosenNames);
//SetActiveItem(comboBoxActiveItem, true);
SetComboBox(dialog.ChosenCodes);
}
else {
comboBoxActiveItem = selectedItem;
......
......@@ -469,9 +469,9 @@ public class MainUi {
switch (Base.Config.FileOpenEncoding) {
case ConfigFileOpenEncoding.CurrentLocale: return Encodings.SystemDefault.CodePage;
case ConfigFileOpenEncoding.Fixed:
string encodingName = Base.Config.FileOpenEncodingFixed;
string encodingCode = Base.Config.FileOpenEncodingFixed;
EncodingDescription encodingDescription = EncodingDescription.Empty;
Encodings.Find(encodingName, ref encodingDescription);
Encodings.Find(encodingCode, ref encodingDescription);
return encodingDescription.CodePage;
default: return -1; //Also accounts for Auto Detect
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment