SubtitleEdit/libse/SubtitleFormats/Cavena890.cs
2016-06-08 20:08:30 +02:00

1010 lines
41 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
{
public class Cavena890 : SubtitleFormat
{
public const int LanguageIdDanish = 0x07;
public const int LanguageIdEnglish = 0x09;
public const int LanguageIdRussian = 0x56;
public const int LanguageIdArabic = 0x80;
public const int LanguageIdHebrew = 0x8f;
public const int LanguageIdChineseTraditional = 0x90;
public const int LanguageIdChineseSimplified = 0x91;
private static readonly List<int> HebrewCodes = new List<int> {
0x40, // א
0x41, // ב
0x42, // ג
0x43, // ד
0x44, // ה
0x45, // ו
0x46, // ז
0x47, // ח
0x49, // י
0x4c, // ל
0x4d, // ם
0x4e, // מ
0x4f, // ן
0x50, // נ
0x51, // ס
0x52, // ע
0x54, // פ
0x56, // צ
0x57, // ק
0x58, // ר
0x59, // ש
0x5A, // ת
0x4b, // כ
0x4a, // ך
0x48, // ט
0x53, // ף
0x55, // ץ
};
private static readonly List<string> HebrewLetters = new List<string> {
"א",
"ב",
"ג",
"ד",
"ה",
"ו",
"ז",
"ח",
"י",
"ל",
"ם",
"מ",
"ן",
"נ",
"ס",
"ע",
"פ",
"צ",
"ק",
"ר",
"ש",
"ת",
"כ",
"ך",
"ט",
"ף",
"ץ",
};
private static readonly List<int> RussianCodes = new List<int> {
0x42, // Б
0x45, // Е
0x5A, // З
0x56, // В
0x49, // И
0x4E, // Н
0x58, // Ы
0x51, // Я
0x56, // V
0x53, // С
0x72, // р
0x69, // и
0x71, // я
0x6E, // н
0x74, // т
0x5C, // Э
0x77, // ю
0x46, // Ф
0x5E, // Ч
0x44, // Д
0x62, // б
0x73, // с
0x75, // у
0x64, // д
0x60, // ж
0x6A, // й
0x6C, // л
0x47, // Г
0x78, // ы
0x7A, // з
0x7E, // ч
0x6D, // м
0x67, // г
0x79, // ь
0x70, // п
0x76, // в
0x55, // У
0x7D, // щ
0x66, // ф
0x7C, // э
0x7B, // ш
0x50, // П
0x52, // П
0x68, // П
};
private static readonly List<string> RussianLetters = new List<string> {
"Б",
"Е",
"З",
"В",
"И",
"Н",
"Ы",
"Я",
"V",
"С",
"р",
"и",
"я",
"н",
"т",
"Э",
"ю",
"Ф",
"Ч",
"Д",
"б",
"с",
"у",
"д",
"ж",
"й",
"л",
"Г",
"ы",
"з",
"ч",
"м",
"г",
"ь",
"п",
"в",
"У",
"щ",
"ф",
"э",
"ш",
"П",
"Р",
"х",
};
public override string Extension
{
get { return ".890"; }
}
public const string NameOfFormat = "Cavena 890";
public override string Name
{
get { return NameOfFormat; }
}
public override bool IsTimeBased
{
get { return false; }
}
private int _languageIdLine1 = LanguageIdEnglish;
private int _languageIdLine2 = LanguageIdEnglish;
public void Save(string fileName, Subtitle subtitle)
{
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
int russianCount = 0;
char[] logoGrams = { '的', '是', '啊', '吧', '好', '吧', '亲', '爱', '的', '早', '上' };
char[] russianChars = { 'я', 'д', 'й', 'л', 'щ', 'ж', 'ц', 'ф', 'ы' };
foreach (Paragraph p in subtitle.Paragraphs)
{
if (p.Text.Contains(logoGrams))
{
_languageIdLine1 = LanguageIdChineseSimplified;
_languageIdLine2 = LanguageIdChineseSimplified;
break;
}
if (p.Text.Contains(russianChars))
{
russianCount++;
if (russianCount > 10)
{
_languageIdLine1 = LanguageIdRussian;
_languageIdLine2 = LanguageIdRussian; // or 0x09?
break;
}
}
}
if (Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId > 0)
{
_languageIdLine1 = Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId;
_languageIdLine2 = Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId;
}
else
{
var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle);
switch (language)
{
case "he":
_languageIdLine1 = LanguageIdHebrew;
_languageIdLine2 = LanguageIdHebrew; // or 0x09
break;
case "ru":
_languageIdLine1 = LanguageIdRussian;
_languageIdLine2 = LanguageIdRussian; // or 0x09?
break;
case "zh":
_languageIdLine1 = LanguageIdChineseSimplified;
_languageIdLine2 = LanguageIdChineseSimplified;
break;
case "da":
_languageIdLine1 = LanguageIdDanish;
_languageIdLine2 = LanguageIdDanish;
break;
}
}
// prompt???
//if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1 >= 0)
// _languageIdLine1 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1;
//if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2 >= 0)
// _languageIdLine2 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2;
// write file header (some fields are known, some are not...)
fs.WriteByte(0); // ?
fs.WriteByte(0); // ?
// tape number (20 bytes)
for (int i = 0; i < 20; i++)
fs.WriteByte(0);
// ?
for (int i = 0; i < 18; i++)
fs.WriteByte(0);
// translated programme title (28 bytes)
string title = Path.GetFileNameWithoutExtension(fileName) ?? string.Empty;
if (title.Length > 28)
title = title.Substring(0, 28);
if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena89Title) && Configuration.Settings.SubtitleSettings.CurrentCavena89Title.Length <= 28)
title = Configuration.Settings.SubtitleSettings.CurrentCavena89Title;
var buffer = Encoding.ASCII.GetBytes(title);
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 28 - buffer.Length; i++)
fs.WriteByte(0);
// translator (28 bytes)
if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena890Translator) && Configuration.Settings.SubtitleSettings.CurrentCavena890Translator.Length <= 28)
{
buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena890Translator);
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 28 - buffer.Length; i++)
fs.WriteByte(0);
}
else
{
for (int i = 0; i < 28; i++)
fs.WriteByte(0);
}
// ?
for (int i = 0; i < 9; i++)
fs.WriteByte(0);
// translated episode title (11 bytes)
for (int i = 0; i < 11; i++)
fs.WriteByte(0);
// ?
for (int i = 0; i < 18; i++)
fs.WriteByte(0);
// ? + language codes
buffer = new byte[] { 0xA0, 0x05, 0x04, 0x03, 0x06, 0x06, 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, (byte)_languageIdLine1, (byte)_languageIdLine2 };
fs.Write(buffer, 0, buffer.Length);
// comments (24 bytes)
buffer = Encoding.ASCII.GetBytes("");
if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena89Comment) && Configuration.Settings.SubtitleSettings.CurrentCavena89Comment.Length <= 24)
buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena89Comment);
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 24 - buffer.Length; i++)
fs.WriteByte(0);
// ??
buffer = new byte[] { 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00 };
fs.Write(buffer, 0, buffer.Length);
// number of subtitles
fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256));
fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256));
// write font - prefix with binary zeroes
buffer = GetFontBytesFromLanguageId(_languageIdLine1); // also TBX308VFONTL.V for english...
for (int i = 0; i < 14 - buffer.Length; i++)
fs.WriteByte(0);
fs.Write(buffer, 0, buffer.Length);
// ?
for (int i = 0; i < 13; i++)
fs.WriteByte(0);
// number of subtitles again
fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256));
fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256));
// number of subtitles again again
fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256));
fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256));
// ?
for (int i = 0; i < 6; i++)
fs.WriteByte(0);
// original programme title (28 chars)
if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle) && Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle.Length <= 28)
{
buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle);
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 28 - buffer.Length; i++)
fs.WriteByte(0);
}
else
{
for (int i = 0; i < 28; i++)
fs.WriteByte(0);
}
// write font (use same font id from line 1)
buffer = GetFontBytesFromLanguageId(_languageIdLine1);
fs.Write(buffer, 0, buffer.Length);
// ?
fs.WriteByte(0x3d);
fs.WriteByte(0x8d);
// start of message time
string startOfMessage = "10:00:00:00";
if (Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage != null &&
Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage.Length == startOfMessage.Length)
startOfMessage = Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage;
buffer = Encoding.ASCII.GetBytes(startOfMessage);
fs.Write(buffer, 0, buffer.Length);
buffer = new byte[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x44
};
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 92; i++)
fs.WriteByte(0);
// paragraphs
int number = 16;
foreach (Paragraph p in subtitle.Paragraphs)
{
// number
fs.WriteByte((byte)(number / 256));
fs.WriteByte((byte)(number % 256));
WriteTime(fs, p.StartTime);
WriteTime(fs, p.EndTime);
if (p.Text.StartsWith("{\\an1}"))
fs.WriteByte(0x50); // left
else if (p.Text.StartsWith("{\\an3}"))
fs.WriteByte(0x52); // left
else
fs.WriteByte(0x54); // center
buffer = new byte[] { 0, 0, 0, 0, 0, 0, 0 }; // 0x16 }; -- the last two bytes might be something with vertical alignment...
fs.Write(buffer, 0, buffer.Length);
bool hasBox = Utilities.RemoveSsaTags(p.Text).StartsWith("<box>");
var text = p.Text.Replace("<box>", string.Empty).Replace("</box>", string.Empty);
text = HtmlUtil.RemoveOpenCloseTags(Utilities.RemoveSsaTags(text), HtmlUtil.TagBold, HtmlUtil.TagFont, HtmlUtil.TagBold);
WriteText(fs, text, p == subtitle.Paragraphs[subtitle.Paragraphs.Count - 1], _languageIdLine1, hasBox);
number += 16;
}
}
}
private static byte[] GetFontBytesFromLanguageId(int languageId)
{
var buffer = Encoding.ASCII.GetBytes("HLV23N.V");
if (languageId == LanguageIdChineseTraditional || languageId == LanguageIdChineseSimplified)
buffer = Encoding.ASCII.GetBytes("CCKM44.V");
else if (languageId == LanguageIdArabic)
buffer = Encoding.ASCII.GetBytes("ARA19N.V");
else if (languageId == LanguageIdRussian)
buffer = Encoding.ASCII.GetBytes("KYRIL4.V");
else if (languageId == LanguageIdHebrew)
buffer = Encoding.ASCII.GetBytes("HEBNOA.V");
else if (languageId == LanguageIdDanish)
buffer = Encoding.ASCII.GetBytes("VFONTL.V");
return buffer;
}
private static void WriteText(Stream fs, string text, bool isLast, int languageIdLine, bool useBox)
{
string line1 = string.Empty;
string line2 = string.Empty;
var lines = text.SplitToLines();
if (lines.Length > 2)
lines = Utilities.AutoBreakLine(text).SplitToLines();
if (lines.Length > 1)
{
line1 = lines[0];
line2 = lines[1];
}
else if (lines.Length == 1)
{
line2 = lines[0];
}
var buffer = GetTextAsBytes(line1, languageIdLine);
fs.Write(buffer, 0, buffer.Length);
buffer = new byte[] { 00, 00, 00, 00, 00, 00 };
if (useBox)
buffer[3] = 0xa0;
fs.Write(buffer, 0, buffer.Length);
buffer = GetTextAsBytes(line2, languageIdLine);
fs.Write(buffer, 0, buffer.Length);
buffer = new byte[] { 00, 00, 00, 00 };
if (!isLast)
fs.Write(buffer, 0, buffer.Length);
}
private static byte[] GetTextAsBytes(string text, int languageId)
{
var buffer = new byte[51];
int skipCount = 0;
for (int i = 0; i < buffer.Length; i++)
buffer[i] = 0x7F;
if (languageId == LanguageIdChineseTraditional || languageId == LanguageIdChineseSimplified)
{
for (int i = 0; i < buffer.Length; i++)
buffer[i] = 0;
}
else if (languageId == LanguageIdHebrew)
{
text = Utilities.ReverseNumbers(text);
if (!Configuration.Settings.General.RightToLeftMode)
text = Utilities.ReverseStartAndEndingForRightToLeft(text);
}
var encoding = Encoding.Default;
int index = 0;
for (int i = 0; i < text.Length; i++)
{
var current = text[i];
if (skipCount > 0)
{
skipCount--;
}
else if (languageId == LanguageIdHebrew)
{
int letterIndex = HebrewLetters.IndexOf(current.ToString(CultureInfo.InvariantCulture));
if (letterIndex >= 0)
{
buffer[index] = (byte)HebrewCodes[letterIndex];
}
else if (i + 3 < text.Length && text.Substring(i, 3) == "<i>")
{
buffer[index] = 0x88;
skipCount = 2;
}
else if (i + 4 <= text.Length && text.Substring(i, 4) == "</i>")
{
buffer[index] = 0x98;
skipCount = 2;
}
else
{
buffer[index] = encoding.GetBytes(new[] { current })[0];
}
index++;
}
else if (languageId == LanguageIdChineseTraditional || languageId == LanguageIdChineseSimplified)
{
encoding = Encoding.GetEncoding(1201);
if (index < 49)
{
if (i + 3 < text.Length && text.Substring(i, 3) == "<i>")
{
buffer[index] = 0x88;
skipCount = 2;
}
else if (i + 4 <= text.Length && text.Substring(i, 4) == "</i>")
{
buffer[index] = 0x98;
skipCount = 3;
}
else
{
buffer[index] = encoding.GetBytes(new[] { current })[0];
index++;
}
}
}
else
{
if (index < 50)
{
if (current == 'æ')
buffer[index] = 0x1B;
else if (current == 'ø')
buffer[index] = 0x1C;
else if (current == 'å')
buffer[index] = 0x1D;
else if (current == 'Æ')
buffer[index] = 0x5B;
else if (current == 'Ø')
buffer[index] = 0x5C;
else if (current == 'Å')
buffer[index] = 0x5D;
else if (current == 'Ä')
AddTwo(buffer, ref index, 0x86, 0x41);
else if (current == 'ä')
AddTwo(buffer, ref index, 0x86, 0x61);
else if (current == 'Ö')
AddTwo(buffer, ref index, 0x86, 0x4F);
else if (current == 'ö')
AddTwo(buffer, ref index, 0x86, 0x6F);
else if (current == 'Ë')
AddTwo(buffer, ref index, 0x86, 0x45);
else if (current == 'ë')
AddTwo(buffer, ref index, 0x86, 0x65);
else if (current == 'Ï')
AddTwo(buffer, ref index, 0x86, 0x49);
else if (current == 'ï')
AddTwo(buffer, ref index, 0x86, 0x69);
else if (current == 'Ü')
AddTwo(buffer, ref index, 0x86, 0x55);
else if (current == 'ü')
AddTwo(buffer, ref index, 0x86, 0x75);
// different language setting?
//else if (current == 'å')
//{
// buffer[index] = 0x8C;
// index++;
// buffer[index] = 0x61;
//}
//else if (current == 'Å')
//{
// buffer[index] = 0x8C;
// index++;
// buffer[index] = 0x41;
//}
// ăĂ îÎ şŞ ţŢ â (romanian)
else if (current == 'ă')
AddTwo(buffer, ref index, 0x89, 0x61);
else if (current == 'Ă')
AddTwo(buffer, ref index, 0x89, 0x41);
else if (current == 'î')
AddTwo(buffer, ref index, 0x83, 0x69);
else if (current == 'Î')
AddTwo(buffer, ref index, 0x83, 0x49);
else if (current == 'ş')
AddTwo(buffer, ref index, 0x87, 0x73);
else if (current == 'Ş')
AddTwo(buffer, ref index, 0x87, 0x53);
else if (current == 'ţ')
AddTwo(buffer, ref index, 0x87, 0x74);
else if (current == 'Ţ')
AddTwo(buffer, ref index, 0x87, 0x54);
else if (current == 'â')
AddTwo(buffer, ref index, 0x83, 0x61);
else if (current == 'Â')
AddTwo(buffer, ref index, 0x83, 0x41);
else if (current == 'è')
AddTwo(buffer, ref index, 0x81, 0x65);
else if (current == 'é')
AddTwo(buffer, ref index, 0x82, 0x65);
else if (current == 'É')
AddTwo(buffer, ref index, 0x82, 0x45);
else if (current == 'È')
AddTwo(buffer, ref index, 0x81, 0x45);
else if (i + 3 < text.Length && text.Substring(i, 3) == "<i>")
{
buffer[index] = 0x88;
skipCount = 2;
}
else if (i + 4 <= text.Length && text.Substring(i, 4) == "</i>")
{
buffer[index] = 0x98;
skipCount = 3;
}
else
{
buffer[index] = encoding.GetBytes(new[] { current })[0];
}
index++;
}
}
}
return buffer;
}
private static void AddTwo(byte[] buffer, ref int index, byte b1, byte b2)
{
buffer[index] = b1;
index++;
buffer[index] = b2;
}
private static void WriteTime(FileStream fs, TimeCode timeCode)
{
double totalMilliseconds = timeCode.TotalMilliseconds;
int frames = (int)Math.Round(totalMilliseconds / (TimeCode.BaseUnit / Configuration.Settings.General.CurrentFrameRate));
fs.WriteByte((byte)(frames / 256 / 256));
fs.WriteByte((byte)(frames / 256));
fs.WriteByte((byte)(frames % 256));
}
public override bool IsMine(List<string> lines, string fileName)
{
if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
{
var fi = new FileInfo(fileName);
if (fi.Length >= 640 && fi.Length < 1024000) // not too small or too big
{
if (!fileName.EndsWith(".890", StringComparison.Ordinal))
return false;
var sub = new Subtitle();
LoadSubtitle(sub, lines, fileName);
return sub.Paragraphs.Count > 0;
}
}
return false;
}
public override string ToText(Subtitle subtitle, string title)
{
return "Not supported!";
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
const int textLength = 51;
subtitle.Paragraphs.Clear();
subtitle.Header = null;
byte[] buffer = FileUtil.ReadAllBytesShared(fileName);
_languageIdLine1 = buffer[146];
if (_languageIdLine1 == 0)
_languageIdLine1 = LanguageIdEnglish;
Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1 = _languageIdLine1;
_languageIdLine2 = buffer[147];
if (_languageIdLine2 == 0)
_languageIdLine2 = LanguageIdEnglish;
Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2 = _languageIdLine2;
var fontNameLine1 = Encoding.ASCII.GetString(buffer, 187, 6);
var fontNameLine2 = Encoding.ASCII.GetString(buffer, 246, 6);
// Hebrew
if (_languageIdLine1 == LanguageIdHebrew || fontNameLine1 == "HEBNOA" || fontNameLine2 == "HEBNOA")
{
_languageIdLine1 = LanguageIdHebrew;
_languageIdLine2 = LanguageIdHebrew;
}
// Russian
else if (_languageIdLine1 == LanguageIdRussian || fontNameLine1.StartsWith("KYRIL", StringComparison.Ordinal) || fontNameLine2.StartsWith("KYRIL", StringComparison.Ordinal))
{
_languageIdLine1 = LanguageIdRussian;
_languageIdLine2 = LanguageIdRussian;
}
// Chinese
else if (_languageIdLine1 == LanguageIdChineseSimplified)
{
_languageIdLine1 = LanguageIdChineseSimplified;
_languageIdLine2 = LanguageIdChineseSimplified;
}
else if (_languageIdLine1 == LanguageIdChineseTraditional || fontNameLine1 == "CCKM44" || fontNameLine2 == "CCKM44")
{
_languageIdLine1 = LanguageIdChineseTraditional;
_languageIdLine2 = LanguageIdChineseTraditional;
}
int i = 455;
int lastNumber = -1;
while (i < buffer.Length - 20)
{
int start = i - textLength;
int number = buffer[start - 16] * 256 + buffer[start - 15];
var p = new Paragraph();
double startFrame = buffer[start - 14] * 256 * 256 + buffer[start - 13] * 256 + buffer[start - 12];
double endFrame = buffer[start - 11] * 256 * 256 + buffer[start - 10] * 256 + buffer[start - 9];
byte boxType = buffer[start + textLength + 3];
string line1 = FixText(buffer, start, textLength, _languageIdLine1);
string line2 = FixText(buffer, start + textLength + 6, textLength, _languageIdLine2);
if (lastNumber == number)
{
p = subtitle.Paragraphs[subtitle.Paragraphs.Count - 1];
string temp = (line1.TrimEnd() + Environment.NewLine + line2).TrimEnd();
if (temp.Length > 0)
p.Text = temp;
}
else
{
subtitle.Paragraphs.Add(p);
p.StartTime.TotalMilliseconds = (TimeCode.BaseUnit / Configuration.Settings.General.CurrentFrameRate) * startFrame;
p.EndTime.TotalMilliseconds = (TimeCode.BaseUnit / Configuration.Settings.General.CurrentFrameRate) * endFrame;
p.Text = (line1.TrimEnd() + Environment.NewLine + line2).TrimEnd();
}
if (boxType >= 0xa0 && boxType <= 0xa9 && !string.IsNullOrEmpty(p.Text)) // box
{
if (p.Text.StartsWith("{\\") && p.Text.Contains("}"))
{
p.Text = p.Text.Insert(p.Text.IndexOf('}', 3) + 1, "<box>") + "</box>";
}
else
{
p.Text = "<box>" + p.Text + "</box>";
}
}
lastNumber = number;
i += 128;
}
subtitle.Renumber();
}
private static string FixText(byte[] buffer, int start, int textLength, int languageId)
{
string text;
if (languageId == LanguageIdRussian)
{
var encoding = Encoding.GetEncoding(1252);
var sb = new StringBuilder();
for (int i = 0; i < textLength; i++)
{
int b = buffer[start + i];
int idx = RussianCodes.IndexOf(b);
if (idx >= 0)
sb.Append(RussianLetters[idx]);
else
sb.Append(encoding.GetString(buffer, start + i, 1));
}
text = sb.ToString();
text = text.Replace(encoding.GetString(new byte[] { 0x7F }), string.Empty); // Used to fill empty space upto 51 bytes
text = text.Replace(encoding.GetString(new byte[] { 0xBE }), string.Empty); // Unknown?
text = FixColors(text);
if (text.Contains("<i></i>"))
text = text.Replace("<i></i>", "<i>");
if (text.Contains("<i>") && !text.Contains("</i>"))
text += "</i>";
}
else if (languageId == LanguageIdHebrew) // (_language == "HEBNOA")
{
var encoding = Encoding.GetEncoding(1252);
var sb = new StringBuilder();
for (int i = 0; i < textLength; i++)
{
int b = buffer[start + i];
int idx = HebrewCodes.IndexOf(b);
if (idx >= 0)
sb.Append(HebrewLetters[idx]);
else
sb.Append(encoding.GetString(buffer, start + i, 1));
}
text = sb.ToString();
text = text.Replace(encoding.GetString(new byte[] { 0x7F }), string.Empty); // Used to fill empty space upto 51 bytes
text = text.Replace(encoding.GetString(new byte[] { 0xBE }), string.Empty); // Unknown?
text = FixColors(text);
if (!Configuration.Settings.General.RightToLeftMode)
text = Utilities.ReverseStartAndEndingForRightToLeft(text);
text = Utilities.ReverseNumbers(text);
}
else if (languageId == LanguageIdChineseTraditional || languageId == LanguageIdChineseSimplified) // (_language == "CCKM44" || _language == "TVB000")
{
int index = start;
while (textLength >= 1 && index + textLength < buffer.Length && (buffer[index + textLength - 1] == 0))
textLength--;
if (textLength > 0)
{
text = Encoding.GetEncoding(1201).GetString(buffer, index, textLength).Replace("\0", string.Empty);
}
else
{
text = string.Empty;
}
var encoding = Encoding.Default; // which encoding?? Encoding.GetEncoding("ISO-8859-5")
text = text.Replace(encoding.GetString(new byte[] { 0x7F }), string.Empty); // Used to fill empty space upto 51 bytes
text = text.Replace(encoding.GetString(new byte[] { 0xBE }), string.Empty); // Unknown?
text = FixColors(text);
text = text.Replace(encoding.GetString(new byte[] { 0x88 }), "<i>");
text = text.Replace(encoding.GetString(new byte[] { 0x98 }), "</i>");
if (text.Contains("<i></i>"))
text = text.Replace("<i></i>", "<i>");
if (text.Contains("<i>") && !text.Contains("</i>"))
text += "</i>";
}
else
{
var encoding = Encoding.GetEncoding(1252);
text = encoding.GetString(buffer, start, textLength).Replace("\0", string.Empty);
text = text.Replace(encoding.GetString(new byte[] { 0x7F }), string.Empty); // Used to fill empty space upto 51 bytes
text = text.Replace(encoding.GetString(new byte[] { 0xBE }), string.Empty); // Unknown?
text = FixColors(text);
text = text.Replace(encoding.GetString(new byte[] { 0x1B }), "æ");
text = text.Replace(encoding.GetString(new byte[] { 0x1C }), "ø");
text = text.Replace(encoding.GetString(new byte[] { 0x1D }), "å");
text = text.Replace(encoding.GetString(new byte[] { 0x1E }), "Æ");
text = text.Replace(encoding.GetString(new byte[] { 0x1F }), "Ø");
text = text.Replace(encoding.GetString(new byte[] { 0x5B }), "Æ");
text = text.Replace(encoding.GetString(new byte[] { 0x5C }), "Ø");
text = text.Replace(encoding.GetString(new byte[] { 0x5D }), "Å");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x41 }), "Ä");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x61 }), "ä");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x4F }), "Ö");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x6F }), "ö");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x45 }), "Ë");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x65 }), "ë");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x49 }), "Ï");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x69 }), "ï");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x55 }), "Ü");
text = text.Replace(encoding.GetString(new byte[] { 0x86, 0x75 }), "ü");
text = text.Replace(encoding.GetString(new byte[] { 0x8C, 0x61 }), "å");
text = text.Replace(encoding.GetString(new byte[] { 0x8C, 0x41 }), "Å");
text = text.Replace(encoding.GetString(new byte[] { 0x81, 0x65 }), "è");
text = text.Replace(encoding.GetString(new byte[] { 0x82, 0x65 }), "é");
text = text.Replace(encoding.GetString(new byte[] { 0x82, 0x45 }), "É");
text = text.Replace(encoding.GetString(new byte[] { 0x81, 0x65 }), "È");
text = text.Replace(encoding.GetString(new byte[] { 0x88 }), "<i>");
text = text.Replace(encoding.GetString(new byte[] { 0x98 }), "</i>");
//ăĂ îÎ şŞ ţŢ â (romanian)
text = text.Replace(encoding.GetString(new byte[] { 0x89, 0x61 }), "ă");
text = text.Replace(encoding.GetString(new byte[] { 0x89, 0x41 }), "Ă");
text = text.Replace(encoding.GetString(new byte[] { 0x83, 0x69 }), "î");
text = text.Replace(encoding.GetString(new byte[] { 0x83, 0x49 }), "Î");
text = text.Replace(encoding.GetString(new byte[] { 0x87, 0x73 }), "ş");
text = text.Replace(encoding.GetString(new byte[] { 0x87, 0x53 }), "Ş");
text = text.Replace(encoding.GetString(new byte[] { 0x87, 0x74 }), "ţ");
text = text.Replace(encoding.GetString(new byte[] { 0x87, 0x54 }), "Ţ");
text = text.Replace(encoding.GetString(new byte[] { 0x83, 0x61 }), "â");
text = text.Replace(encoding.GetString(new byte[] { 0x83, 0x41 }), "Â");
if (text.Contains("<i></i>"))
text = text.Replace("<i></i>", "<i>");
if (text.Contains("<i>") && !text.Contains("</i>"))
text += "</i>";
}
return text;
}
private static string FixColors(string text)
{
Encoding encoding = Encoding.GetEncoding(1252);
bool fontColorOn = false;
var sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
var s = text.Substring(i, 1);
if (s == encoding.GetString(new byte[] { 0xf1 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#FF797D\">"); // red
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf2 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#AAEF9E\">"); // green
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf3 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#FAFAA8\">"); // yellow
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf4 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#9999FF\">"); // purple
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf5 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#FFABFB\">"); // magenta
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf6 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
}
sb.Append("<font color=\"#A2FEFE\">"); // cyan
fontColorOn = true;
}
else if (s == encoding.GetString(new byte[] { 0xf7 }))
{
if (fontColorOn)
{
sb.Append("</font>"); // white
fontColorOn = false;
}
}
else if (s == encoding.GetString(new byte[] { 0xf8 }))
{
sb.Append("<font color=\"#FCC786\">"); // orange
fontColorOn = true;
}
else
{
sb.Append(s);
}
}
if (fontColorOn)
{
sb.Append("</font>"); // white
}
return sb.ToString();
}
}
}