- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# STS.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include "STS.h"
    00024 #include <atlbase.h>
    00025
    00026 // gathered from http://www.netwave.or.jp/~shikai/shikai/shcolor.htm
    00027
    00028 struct htmlcolor {TCHAR* name; DWORD color;} hmtlcolors[] =
    00029 {
    00030         {_T("white"), 0xffffff},
    00031         {_T("whitesmoke"), 0xf5f5f5},
    00032         {_T("ghostwhite"), 0xf8f8ff},
    00033         {_T("snow"), 0xfffafa},
    00034         {_T("gainsboro"), 0xdcdcdc},
    00035         {_T("lightgrey"), 0xd3d3d3},
    00036         {_T("silver"), 0xc0c0c0},
    00037         {_T("darkgray"), 0xa9a9a9},
    00038         {_T("gray"), 0x808080},
    00039         {_T("dimgray"), 0x696969},
    00040         {_T("lightslategray"), 0x778899},
    00041         {_T("slategray"), 0x708090},
    00042         {_T("darkslategray"), 0x2f4f4f},
    00043         {_T("black"), 0x000000},
    00044
    00045         {_T("azure"), 0xf0ffff},
    00046         {_T("aliceblue"), 0xf0f8ff},
    00047         {_T("mintcream"), 0xf5fffa},
    00048         {_T("honeydew"), 0xf0fff0},
    00049         {_T("lightcyan"), 0xe0ffff},
    00050         {_T("paleturqoise"), 0xafeeee},
    00051         {_T("powderblue"), 0xb0e0e6},
    00052         {_T("lightblue"), 0xadd8ed},
    00053         {_T("lightsteelblue"), 0xb0c4de},
    00054         {_T("skyblue"), 0x87ceeb},
    00055         {_T("lightskyblue"), 0x87cefa},
    00056         {_T("cyan"), 0x00ffff},
    00057         {_T("aqua"), 0x00ff80},
    00058         {_T("deepskyblue"), 0x00bfff},
    00059         {_T("aquamarine"), 0x7fffd4},
    00060         {_T("turquoise"), 0x40e0d0},
    00061         {_T("darkturquoise"), 0x00ced1},
    00062         {_T("lightseagreen"), 0x20b2aa},
    00063         {_T("mediumturquoise"), 0x40e0dd},
    00064         {_T("mediumaquamarine"), 0x66cdaa},
    00065         {_T("cadetblue"), 0x5f9ea0},
    00066         {_T("teal"), 0x008080},
    00067         {_T("darkcyan"), 0x008b8b},
    00068         {_T("comflowerblue"), 0x6495ed},
    00069         {_T("dodgerblue"), 0x1e90ff},
    00070         {_T("steelblue"), 0x4682b4},
    00071         {_T("royalblue"), 0x4169e1},
    00072         {_T("blue"), 0x0000ff},
    00073         {_T("mediumblue"), 0x0000cd},
    00074         {_T("mediumslateblue"), 0x7b68ee},
    00075         {_T("slateblue"), 0x6a5acd},
    00076         {_T("darkslateblue"), 0x483d8b},
    00077         {_T("darkblue"), 0x00008b},
    00078         {_T("midnightblue"), 0x191970},
    00079         {_T("navy"), 0x000080},
    00080
    00081         {_T("palegreen"), 0x98fb98},
    00082         {_T("lightgreen"), 0x90ee90},
    00083         {_T("mediumspringgreen"), 0x00fa9a},
    00084         {_T("springgreen"), 0x00ff7f},
    00085         {_T("chartreuse"), 0x7fff00},
    00086         {_T("lawngreen"), 0x7cfc00},
    00087         {_T("lime"), 0x00ff00},
    00088         {_T("limegreen"), 0x32cd32},
    00089         {_T("greenyellow"), 0xadff2f},
    00090         {_T("yellowgreen"), 0x9acd32},
    00091         {_T("darkseagreen"), 0x8fbc8f},
    00092         {_T("mediumseagreen"), 0x3cb371},
    00093         {_T("seagreen"), 0x2e8b57},
    00094         {_T("olivedrab"), 0x6b8e23},
    00095         {_T("forestgreen"), 0x228b22},
    00096         {_T("green"), 0x008000},
    00097         {_T("darkkhaki"), 0xbdb76b},
    00098         {_T("olive"), 0x808000},
    00099         {_T("darkolivegreen"), 0x556b2f},
    00100         {_T("darkgreen"), 0x006400},
    00101
    00102         {_T("floralwhite"), 0xfffaf0},
    00103         {_T("seashell"), 0xfff5ee},
    00104         {_T("ivory"), 0xfffff0},
    00105         {_T("beige"), 0xf5f5dc},
    00106         {_T("cornsilk"), 0xfff8dc},
    00107         {_T("lemonchiffon"), 0xfffacd},
    00108         {_T("lightyellow"), 0xffffe0},
    00109         {_T("lightgoldenrodyellow"), 0xfafad2},
    00110         {_T("papayawhip"), 0xffefd5},
    00111         {_T("blanchedalmond"), 0xffedcd},
    00112         {_T("palegoldenrod"), 0xeee8aa},
    00113         {_T("khaki"), 0xf0eb8c},
    00114         {_T("bisque"), 0xffe4c4},
    00115         {_T("moccasin"), 0xffe4b5},
    00116         {_T("navajowhite"), 0xffdead},
    00117         {_T("peachpuff"), 0xffdab9},
    00118         {_T("yellow"), 0xffff00},
    00119         {_T("gold"), 0xffd700},
    00120         {_T("wheat"), 0xf5deb3},
    00121         {_T("orange"), 0xffa500},
    00122         {_T("darkorange"), 0xff8c00},
    00123
    00124         {_T("oldlace"), 0xfdf5e6},
    00125         {_T("linen"), 0xfaf0e6},
    00126         {_T("antiquewhite"), 0xfaebd7},
    00127         {_T("lightsalmon"), 0xffa07a},
    00128         {_T("darksalmon"), 0xe9967a},
    00129         {_T("salmon"), 0xfa8072},
    00130         {_T("lightcoral"), 0xf08080},
    00131         {_T("indianred"), 0xcd5c5c},
    00132         {_T("coral"), 0xff7f50},
    00133         {_T("tomato"), 0xff6347},
    00134         {_T("orangered"), 0xff4500},
    00135         {_T("red"), 0xff0000},
    00136         {_T("crimson"), 0xdc143c},
    00137         {_T("firebrick"), 0xb22222},
    00138         {_T("maroon"), 0x800000},
    00139         {_T("darkred"), 0x8b0000},
    00140
    00141         {_T("lavender"), 0xe6e6fe},
    00142         {_T("lavenderblush"), 0xfff0f5},
    00143         {_T("mistyrose"), 0xffe4e1},
    00144         {_T("thistle"), 0xd8bfd8},
    00145         {_T("pink"), 0xffc0cb},
    00146         {_T("lightpink"), 0xffb6c1},
    00147         {_T("palevioletred"), 0xdb7093},
    00148         {_T("hotpink"), 0xff69b4},
    00149         {_T("fuchsia"), 0xff00ee},
    00150         {_T("magenta"), 0xff00ff},
    00151         {_T("mediumvioletred"), 0xc71585},
    00152         {_T("deeppink"), 0xff1493},
    00153         {_T("plum"), 0xdda0dd},
    00154         {_T("violet"), 0xee82ee},
    00155         {_T("orchid"), 0xda70d6},
    00156         {_T("mediumorchid"), 0xba55d3},
    00157         {_T("mediumpurple"), 0x9370db},
    00158         {_T("purple"), 0x9370db},
    00159         {_T("blueviolet"), 0x8a2be2},
    00160         {_T("darkviolet"), 0x9400d3},
    00161         {_T("darkorchid"), 0x9932cc},
    00162
    00163         {_T("tan"), 0xd2b48c},
    00164         {_T("burlywood"), 0xdeb887},
    00165         {_T("sandybrown"), 0xf4a460},
    00166         {_T("peru"), 0xcd853f},
    00167         {_T("goldenrod"), 0xdaa520},
    00168         {_T("darkgoldenrod"), 0xb8860b},
    00169         {_T("chocolate"), 0xd2691e},
    00170         {_T("rosybrown"), 0xbc8f8f},
    00171         {_T("sienna"), 0xa0522d},
    00172         {_T("saddlebrown"), 0x8b4513},
    00173         {_T("brown"), 0xa52a2a},
    00174 };
    00175
    00176 CHtmlColorMap::CHtmlColorMap()
    00177 {
    00178         for(int i = 0; i < countof(hmtlcolors); i++)
    00179                 SetAt(hmtlcolors[i].name, (void*)hmtlcolors[i].color);
    00180 }
    00181
    00182 CHtmlColorMap g_colors;
    00183
    00184 //
    00185
    00186 BYTE CharSetList[] =
    00187 {
    00188         ANSI_CHARSET,
    00189         DEFAULT_CHARSET,
    00190         SYMBOL_CHARSET,
    00191         SHIFTJIS_CHARSET,
    00192         HANGEUL_CHARSET,
    00193         HANGUL_CHARSET,
    00194         GB2312_CHARSET,
    00195         CHINESEBIG5_CHARSET,
    00196         OEM_CHARSET,
    00197         JOHAB_CHARSET,
    00198         HEBREW_CHARSET,
    00199         ARABIC_CHARSET,
    00200         GREEK_CHARSET,
    00201         TURKISH_CHARSET,
    00202         VIETNAMESE_CHARSET,
    00203         THAI_CHARSET,
    00204         EASTEUROPE_CHARSET,
    00205         RUSSIAN_CHARSET,
    00206         MAC_CHARSET,
    00207         BALTIC_CHARSET
    00208 };
    00209
    00210 TCHAR* CharSetNames[] =
    00211 {
    00212         _T("ANSI"),
    00213         _T("DEFAULT"),
    00214         _T("SYMBOL"),
    00215         _T("SHIFTJIS"),
    00216         _T("HANGEUL"),
    00217         _T("HANGUL"),
    00218         _T("GB2312"),
    00219         _T("CHINESEBIG5"),
    00220         _T("OEM"),
    00221         _T("JOHAB"),
    00222         _T("HEBREW"),
    00223         _T("ARABIC"),
    00224         _T("GREEK"),
    00225         _T("TURKISH"),
    00226         _T("VIETNAMESE"),
    00227         _T("THAI"),
    00228         _T("EASTEUROPE"),
    00229         _T("RUSSIAN"),
    00230         _T("MAC"),
    00231         _T("BALTIC"),
    00232 };
    00233
    00234 int CharSetLen = countof(CharSetList);
    00235
    00236 //
    00237
    00238 static DWORD CharSetToCodePage(DWORD dwCharSet)
    00239 {
    00240         CHARSETINFO cs={0};
    00241         ::TranslateCharsetInfo((DWORD *)dwCharSet, &cs, TCI_SRCCHARSET);
    00242         return cs.ciACP;
    00243 }
    00244
    00245 int FindChar(CStringW str, WCHAR c, int pos, bool fUnicode, int CharSet)
    00246 {
    00247         if(fUnicode) return(str.Find(c, pos));
    00248
    00249         int fStyleMod = 0;
    00250
    00251         DWORD cp = CharSetToCodePage(CharSet);
    00252         int OrgCharSet = CharSet;
    00253
    00254         for(int i = 0, j = str.GetLength(), k; i < j; i++)
    00255         {
    00256                 WCHAR c2 = str[i];
    00257
    00258                 if(IsDBCSLeadByteEx(cp, (BYTE)c2)) i++;
    00259                 else if(i >= pos)
    00260                 {
    00261                         if(c2 == c) return(i);
    00262                 }
    00263
    00264                 if(c2 == '{') fStyleMod++;
    00265                 else if(fStyleMod > 0)
    00266                 {
    00267                         if(c2 == '}') fStyleMod--;
    00268                         else if(c2 == 'e' && i >= 3 && i < j-1 && str.Mid(i-2, 3) == L"\\fe")
    00269                         {
    00270                                 CharSet = 0;
    00271                                 for(k = i+1; _istdigit(str[k]); k++) CharSet = CharSet*10 + (str[k] - '0');
    00272                                 if(k == i+1) CharSet = OrgCharSet;
    00273
    00274                                 cp = CharSetToCodePage(CharSet);
    00275                         }
    00276                 }
    00277         }
    00278
    00279         return(-1);
    00280 }
    00281 /*
    00282 int FindChar(CStringA str, char c, int pos, bool fUnicode, int CharSet)
    00283 {
    00284         ASSERT(!fUnicode);
    00285
    00286         return(FindChar(AToW(str), c, pos, false, CharSet));
    00287 }
    00288 */
    00289 static CStringW ToMBCS(CStringW str, DWORD CharSet)
    00290 {
    00291         CStringW ret;
    00292
    00293         DWORD cp = CharSetToCodePage(CharSet);
    00294
    00295         for(int i = 0, j = str.GetLength(); i < j; i++)
    00296         {
    00297                 WCHAR wc = str.GetAt(i);
    00298                 char c[8];
    00299
    00300                 int len;
    00301                 if((len = WideCharToMultiByte(cp, 0, &wc, 1, c, 8, NULL, NULL)) > 0)
    00302                 {
    00303                         for(int k = 0; k < len; k++)
    00304                                 ret += (WCHAR)(BYTE)c[k];
    00305                 }
    00306                 else
    00307                 {
    00308                         ret += '?';
    00309                 }
    00310         }
    00311
    00312         return(ret);
    00313 }
    00314
    00315 static CStringW UnicodeSSAToMBCS(CStringW str, DWORD CharSet)
    00316 {
    00317         CStringW ret;
    00318
    00319         int OrgCharSet = CharSet;
    00320
    00321         for(int j = 0; j < str.GetLength(); )
    00322         {
    00323                 j = str.Find('{', j);
    00324                 if(j >= 0)
    00325                 {
    00326                         ret += ToMBCS(str.Left(j), CharSet);
    00327                         str = str.Mid(j);
    00328
    00329                         j = str.Find('}');
    00330                         if(j < 0)
    00331                         {
    00332                                 ret += ToMBCS(str, CharSet);
    00333                                 break;
    00334                         }
    00335                         else
    00336                         {
    00337                                 int k = str.Find(L"\\fe");
    00338                                 if(k >= 0 && k < j)
    00339                                 {
    00340                                         CharSet = 0;
    00341                                         int l = k+3;
    00342                                         for(; _istdigit(str[l]); l++) CharSet = CharSet*10 + (str[l] - '0');
    00343                                         if(l == k+3) CharSet = OrgCharSet;
    00344                                 }
    00345
    00346                                 j++;
    00347
    00348                                 ret += ToMBCS(str.Left(j), OrgCharSet);
    00349                                 str = str.Mid(j);
    00350                                 j = 0;
    00351                         }
    00352                 }
    00353                 else
    00354                 {
    00355                         ret += ToMBCS(str, CharSet);
    00356                         break;
    00357                 }
    00358         }
    00359
    00360         return(ret);
    00361 }
    00362
    00363 static CStringW ToUnicode(CStringW str, DWORD CharSet)
    00364 {
    00365         CStringW ret;
    00366
    00367         DWORD cp = CharSetToCodePage(CharSet);
    00368
    00369         for(int i = 0, j = str.GetLength(); i < j; i++)
    00370         {
    00371                 WCHAR wc = str.GetAt(i);
    00372                 char c = wc&0xff;
    00373
    00374                 if(IsDBCSLeadByteEx(cp, (BYTE)wc))
    00375                 {
    00376                         i++;
    00377
    00378                         if(i < j)
    00379                         {
    00380                                 char cc[2];
    00381                                 cc[0] = c;
    00382                                 cc[1] = (char)str.GetAt(i);
    00383
    00384                                 MultiByteToWideChar(cp, 0, cc, 2, &wc, 1);
    00385                         }
    00386                 }
    00387                 else
    00388                 {
    00389                         MultiByteToWideChar(cp, 0, &c, 1, &wc, 1);
    00390                 }
    00391
    00392                 ret += wc;
    00393         }
    00394
    00395         return(ret);
    00396 }
    00397
    00398 static CStringW MBCSSSAToUnicode(CStringW str, int CharSet)
    00399 {
    00400         CStringW ret;
    00401
    00402         int OrgCharSet = CharSet;
    00403
    00404         for(int j = 0; j < str.GetLength(); )
    00405         {
    00406                 j = FindChar(str, '{', 0, false, CharSet);
    00407
    00408                 if(j >= 0)
    00409                 {
    00410                         ret += ToUnicode(str.Left(j), CharSet);
    00411                         str = str.Mid(j);
    00412
    00413                         j = FindChar(str, '}', 0, false, CharSet);
    00414
    00415                         if(j < 0)
    00416                         {
    00417                                 ret += ToUnicode(str, CharSet);
    00418                                 break;
    00419                         }
    00420                         else
    00421                         {
    00422                                 int k = str.Find(L"\\fe");
    00423                                 if(k >= 0 && k < j)
    00424                                 {
    00425                                         CharSet = 0;
    00426                                         int l = k+3;
    00427                                         for(; _istdigit(str[l]); l++) CharSet = CharSet*10 + (str[l] - '0');
    00428                                         if(l == k+3) CharSet = OrgCharSet;
    00429                                 }
    00430
    00431                                 j++;
    00432
    00433                                 ret += ToUnicode(str.Left(j), OrgCharSet);
    00434                                 str = str.Mid(j);
    00435                                 j = 0;
    00436                         }
    00437                 }
    00438                 else
    00439                 {
    00440                         ret += ToUnicode(str, CharSet);
    00441                         break;
    00442                 }
    00443         }
    00444
    00445         return(ret);
    00446 }
    00447
    00448 CStringW RemoveSSATags(CStringW str, bool fUnicode, int CharSet)
    00449 {
    00450         for(int i = 0, j; i < str.GetLength(); )
    00451         {
    00452                 if((i = FindChar(str, '{', i, fUnicode, CharSet)) < 0) break;
    00453                 if((j = FindChar(str, '}', i, fUnicode, CharSet)) < 0) break;
    00454                 str.Delete(i, j-i+1);
    00455         }
    00456
    00457         str.Replace(L"\\N", L"\n");
    00458         str.Replace(L"\\n", L"\n");
    00459         str.Replace(L"\\h", L" ");
    00460
    00461         return(str);
    00462 }
    00463
    00464 //
    00465
    00466 static CStringW SubRipper2SSA(CStringW str, int CharSet)
    00467 {
    00468         str.Replace(L"<i>", L"{\\i1}");
    00469         str.Replace(L"</i>", L"{\\i}");
    00470         str.Replace(L"<b>", L"{\\b1}");
    00471         str.Replace(L"</b>", L"{\\b}");
    00472         str.Replace(L"<u>", L"{\\u1}");
    00473         str.Replace(L"</u>", L"{\\u}");
    00474
    00475         return(str);
    00476 }
    00477
    00478 static bool OpenSubRipper(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    00479 {
    00480         int num = 0;
    00481
    00482         CStringW buff;
    00483         while(file->ReadString(buff))
    00484         {
    00485                 buff.Trim();
    00486                 if(buff.IsEmpty()) continue;
    00487
    00488                 WCHAR sep;
    00489                 int hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2;
    00490                 int c = swscanf(buff, L"%d%c%d%c%d%c%d --> %d%c%d%c%d%c%d\n",
    00491                         &hh1, &sep, &mm1, &sep, &ss1, &sep, &ms1,
    00492                         &hh2, &sep, &mm2, &sep, &ss2, &sep, &ms2);
    00493
    00494                 if(c == 1) // numbering
    00495                 {
    00496                         num = hh1;
    00497                 }
    00498                 else if(c == 14) // time info
    00499                 {
    00500                         CStringW str, tmp;
    00501
    00502                         bool fFoundEmpty = false;
    00503
    00504                         while(file->ReadString(tmp))
    00505                         {
    00506                                 tmp.Trim();
    00507                                 if(tmp.IsEmpty()) fFoundEmpty = true;
    00508
    00509                                 int num2;
    00510                                 WCHAR c;
    00511                                 if(swscanf(tmp, L"%d%c", &num2, &c) == 1 && fFoundEmpty)
    00512                                 {
    00513                                         num = num2;
    00514                                         break;
    00515                                 }
    00516
    00517                                 str += tmp + '\n';
    00518                         }
    00519
    00520                         ret.Add(
    00521                                 SubRipper2SSA(str, CharSet),
    00522                                 file->IsUnicode(),
    00523                                 (((hh1*60 + mm1)*60) + ss1)*1000 + ms1,
    00524                                 (((hh2*60 + mm2)*60) + ss2)*1000 + ms2);
    00525                 }
    00526                 else if(c != EOF) // might be another format
    00527                 {
    00528                         return(false);
    00529                 }
    00530         }
    00531
    00532         return(ret.GetCount() > 0);
    00533 }
    00534
    00535 static bool OpenOldSubRipper(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    00536 {
    00537         CStringW buff;
    00538         while(file->ReadString(buff))
    00539         {
    00540                 buff.Trim();
    00541                 if(buff.IsEmpty()) continue;
    00542
    00543                 for(int i = 0; i < buff.GetLength(); i++)
    00544                 {
    00545                         if((i = FindChar(buff, '|', i, file->IsUnicode(), CharSet)) < 0) break;
    00546                         buff.SetAt(i, '\n');
    00547                 }
    00548
    00549                 int hh1, mm1, ss1, hh2, mm2, ss2;
    00550                 int c = swscanf(buff, L"{%d:%d:%d}{%d:%d:%d}", &hh1, &mm1, &ss1, &hh2, &mm2, &ss2);
    00551
    00552                 if(c == 6)
    00553                 {
    00554                         ret.Add(
    00555                                 buff.Mid(buff.Find('}', buff.Find('}')+1)+1),
    00556                                 file->IsUnicode(),
    00557                                 (((hh1*60 + mm1)*60) + ss1)*1000,
    00558                                 (((hh2*60 + mm2)*60) + ss2)*1000);
    00559                 }
    00560                 else if(c != EOF) // might be another format
    00561                 {
    00562                         return(false);
    00563                 }
    00564         }
    00565
    00566         return(ret.GetCount() > 0);
    00567 }
    00568
    00569 static bool OpenSubViewer(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    00570 {
    00571         STSStyle def;
    00572         CStringW font, color, size;
    00573         bool fBold, fItalic, fStriked, fUnderline;
    00574
    00575         CStringW buff;
    00576         while(file->ReadString(buff))
    00577         {
    00578                 buff.Trim();
    00579                 if(buff.IsEmpty()) continue;
    00580
    00581                 if(buff[0] == '[')
    00582                 {
    00583                         for(int i = 0; i < buff.GetLength() && buff[i]== '['; )
    00584                         {
    00585                                 int j = buff.Find(']', ++i);
    00586                                 if(j < i) break;
    00587
    00588                                 CStringW tag = buff.Mid(i,j-i);
    00589                                 tag.Trim();
    00590                                 tag.MakeLower();
    00591
    00592                                 i += j-i;
    00593
    00594                                 j = buff.Find('[', ++i);
    00595                                 if(j < 0) j = buff.GetLength();
    00596
    00597                                 CStringW param = buff.Mid(i,j-i);
    00598                                 param.Trim(L" \\t,");
    00599
    00600                                 i = j;
    00601
    00602                                 if(tag == L"font")
    00603                                         font = def.fontName.CompareNoCase(WToT(param)) ? param : L"";
    00604                                 else if(tag == L"colf")
    00605                                         color = def.colors[0] != wcstol(((LPCWSTR)param)+2, 0, 16) ? param : L"";
    00606                                 else if(tag == L"size")
    00607                                         size = def.fontSize != wcstol(param, 0, 10) ? param : L"";
    00608                                 else if(tag == L"style")
    00609                                 {
    00610                                         if(param.Find(L"no") >= 0)
    00611                                         {
    00612                                                 fBold = fItalic = fStriked = fUnderline = false;
    00613                                         }
    00614                                         else
    00615                                         {
    00616                                                 fBold = def.fontWeight < FW_BOLD && param.Find(L"bd") >= 0;
    00617                                                 fItalic = def.fItalic && param.Find(L"it") >= 0;
    00618                                                 fStriked = def.fStrikeOut && param.Find(L"st") >= 0;
    00619                                                 fUnderline = def.fUnderline && param.Find(L"ud") >= 0;
    00620                                         }
    00621                                 }
    00622                         }
    00623
    00624                         continue;
    00625                 }
    00626
    00627                 WCHAR sep;
    00628                 int hh1, mm1, ss1, hs1, hh2, mm2, ss2, hs2;
    00629                 int c = swscanf(buff, L"%d:%d:%d%c%d,%d:%d:%d%c%d\n",
    00630                         &hh1, &mm1, &ss1, &sep, &hs1, &hh2, &mm2, &ss2, &sep, &hs2);
    00631
    00632                 if(c == 10)
    00633                 {
    00634                         CStringW str;
    00635                         file->ReadString(str);
    00636
    00637                         str.Replace(L"[br]", L"\\N");
    00638
    00639                         CStringW prefix;
    00640                         if(!font.IsEmpty()) prefix += L"\\fn" + font;
    00641                         if(!color.IsEmpty()) prefix += L"\\c" + color;
    00642                         if(!size.IsEmpty()) prefix += L"\\fs" + size;
    00643                         if(fBold) prefix += L"\\b1";
    00644                         if(fItalic) prefix += L"\\i1";
    00645                         if(fStriked) prefix += L"\\s1";
    00646                         if(fUnderline) prefix += L"\\u1";
    00647                         if(!prefix.IsEmpty()) str = L"{" + prefix + L"}" + str;
    00648
    00649                         ret.Add(str,
    00650                                 file->IsUnicode(),
    00651                                 (((hh1*60 + mm1)*60) + ss1)*1000 + hs1*10,
    00652                                 (((hh2*60 + mm2)*60) + ss2)*1000 + hs2*10);
    00653                 }
    00654                 else if(c != EOF) // might be another format
    00655                 {
    00656                         return(false);
    00657                 }
    00658         }
    00659
    00660         return(ret.GetCount() > 0);
    00661 }
    00662
    00663 static STSStyle* GetMicroDVDStyle(CString str, int CharSet)
    00664 {
    00665         STSStyle* ret = new STSStyle();
    00666         if(!ret) return(NULL);
    00667
    00668         for(int i = 0, len = str.GetLength(); i < len; i++)
    00669         {
    00670                 int j = str.Find('{', i);
    00671                 if(j < 0) j = len;
    00672
    00673                 if(j >= len) break;
    00674
    00675                 int k = str.Find('}', j);
    00676                 if(k < 0) k = len;
    00677
    00678                 CString code = str.Mid(j, k-j);
    00679                 if(code.GetLength() > 2) code.SetAt(1, (TCHAR)towlower(code[1]));
    00680
    00681                 if(!_tcsnicmp(code, _T("{c:$"), 4))
    00682                 {
    00683                         _stscanf(code, _T("{c:$%x"), &ret->colors[0]);
    00684                 }
    00685                 else if(!_tcsnicmp(code, _T("{f:"), 3))
    00686                 {
    00687                         ret->fontName = code.Mid(3);
    00688                 }
    00689                 else if(!_tcsnicmp(code, _T("{s:"), 3))
    00690                 {
    00691                         float f;
    00692                         if(1 == _stscanf(code, _T("{s:%f"), &f))
    00693                                 ret->fontSize = f;
    00694                 }
    00695                 else if(!_tcsnicmp(code, _T("{h:"), 3))
    00696                 {
    00697                         _stscanf(code, _T("{h:%d"), &ret->charSet);
    00698                 }
    00699                 else if(!_tcsnicmp(code, _T("{y:"), 3))
    00700                 {
    00701                         code.MakeLower();
    00702                         if(code.Find('b') >= 0) ret->fontWeight = FW_BOLD;
    00703                         if(code.Find('i') >= 0) ret->fItalic = true;
    00704                         if(code.Find('u') >= 0) ret->fUnderline = true;
    00705                         if(code.Find('s') >= 0) ret->fStrikeOut = true;
    00706                 }
    00707                 else if(!_tcsnicmp(code, _T("{p:"), 3))
    00708                 {
    00709                         int p;
    00710                         _stscanf(code, _T("{p:%d"), &p);
    00711                         ret->scrAlignment = (p == 0) ? 8 : 2;
    00712                 }
    00713
    00714                 i = k;
    00715         }
    00716
    00717         return(ret);
    00718 }
    00719
    00720 static CStringW MicroDVD2SSA(CStringW str, bool fUnicode, int CharSet)
    00721 {
    00722         CStringW ret;
    00723
    00724         enum {COLOR=0, FONTNAME, FONTSIZE, FONTCHARSET, BOLD, ITALIC, UNDERLINE, STRIKEOUT};
    00725         bool fRestore[8];
    00726         int fRestoreLen = 8;
    00727         memset(fRestore, 0, sizeof(bool)*fRestoreLen);
    00728
    00729         for(int pos = 0, eol; pos < str.GetLength(); pos++)
    00730         {
    00731                 if((eol = FindChar(str, '|', pos, fUnicode, CharSet)) < 0) eol = str.GetLength();
    00732
    00733                 CStringW line = str.Mid(pos, eol-pos);
    00734
    00735                 pos = eol;
    00736
    00737                 for(int i = 0, j, k, len = line.GetLength(); i < len; i++)
    00738                 {
    00739                         if((j = FindChar(line, '{', i, fUnicode, CharSet)) < 0) j = str.GetLength();
    00740
    00741                         ret += line.Mid(i, j-i);
    00742
    00743                         if(j >= len) break;
    00744
    00745                         if((k = FindChar(line, '}', j, fUnicode, CharSet)) < 0) k = len;
    00746
    00747                         {
    00748                                 CStringW code = line.Mid(j, k-j);
    00749
    00750                                 if(!wcsnicmp(code, L"{c:$", 4))
    00751                                 {
    00752                                         fRestore[COLOR] = (iswupper(code[1]) == 0);
    00753                                         code.MakeLower();
    00754
    00755                                         int color;
    00756                                         swscanf(code, L"{c:$%x", &color);
    00757                                         code.Format(L"{\\c&H%x&}", color);
    00758                                         ret += code;
    00759                                 }
    00760                                 else if(!wcsnicmp(code, L"{f:", 3))
    00761                                 {
    00762                                         fRestore[FONTNAME] = (iswupper(code[1]) == 0);
    00763
    00764                                         code.Format(L"{\\fn%s}", code.Mid(3));
    00765                                         ret += code;
    00766                                 }
    00767                                 else if(!wcsnicmp(code, L"{s:", 3))
    00768                                 {
    00769                                         fRestore[FONTSIZE] = (iswupper(code[1]) == 0);
    00770                                         code.MakeLower();
    00771
    00772                                         float size;
    00773                                         swscanf(code, L"{s:%f", &size);
    00774                                         code.Format(L"{\\fs%f}", size);
    00775                                         ret += code;
    00776                                 }
    00777                                 else if(!wcsnicmp(code, L"{h:", 3))
    00778                                 {
    00779                                         fRestore[COLOR] = (_istupper(code[1]) == 0);
    00780                                         code.MakeLower();
    00781
    00782                                         int CharSet;
    00783                                         swscanf(code, L"{h:%d", &CharSet);
    00784                                         code.Format(L"{\\fe%d}", CharSet);
    00785                                         ret += code;
    00786                                 }
    00787                                 else if(!wcsnicmp(code, L"{y:", 3))
    00788                                 {
    00789                                         bool f = (_istupper(code[1]) == 0);
    00790
    00791                                         code.MakeLower();
    00792
    00793                                         ret += '{';
    00794                                         if(code.Find('b') >= 0) {ret += L"\\b1"; fRestore[BOLD] = f;}
    00795                                         if(code.Find('i') >= 0) {ret += L"\\i1"; fRestore[ITALIC] = f;}
    00796                                         if(code.Find('u') >= 0) {ret += L"\\u1"; fRestore[UNDERLINE] = f;}
    00797                                         if(code.Find('s') >= 0) {ret += L"\\s1"; fRestore[STRIKEOUT] = f;}
    00798                                         ret += '}';
    00799                                 }
    00800                                 else if(!wcsnicmp(code, L"{o:", 3))
    00801                                 {
    00802                                         code.MakeLower();
    00803
    00804                                         int x, y;
    00805                                         TCHAR c;
    00806                                         swscanf(code, L"{o:%d%c%d", &x, &c, &y);
    00807                                         code.Format(L"{\\move(%d,%d,0,0,0,0)}", x, y);
    00808                                         ret += code;
    00809                                 }
    00810                                 else ret += code;
    00811                         }
    00812
    00813                         i = k;
    00814                 }
    00815
    00816                 if(pos >= str.GetLength()) break;
    00817
    00818                 for(int i = 0; i < fRestoreLen; i++)
    00819                 {
    00820                         if(fRestore[i])
    00821                         {
    00822                                 switch(i)
    00823                                 {
    00824                                 case COLOR: ret += L"{\\c}"; break;
    00825                                 case FONTNAME: ret += L"{\\fn}"; break;
    00826                                 case FONTSIZE: ret += L"{\\fs}"; break;
    00827                                 case FONTCHARSET: ret += L"{\\fe}"; break;
    00828                                 case BOLD: ret += L"{\\b}"; break;
    00829                                 case ITALIC: ret += L"{\\i}"; break;
    00830                                 case UNDERLINE: ret += L"{\\u}"; break;
    00831                                 case STRIKEOUT: ret += L"{\\s}"; break;
    00832                                 default: break;
    00833                                 }
    00834                         }
    00835                 }
    00836
    00837                 memset(fRestore, 0, sizeof(bool)*fRestoreLen);
    00838
    00839                 ret += L"\\N";
    00840         }
    00841
    00842         return(ret);
    00843 }
    00844
    00845 static bool OpenMicroDVD(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    00846 {
    00847         bool fCheck = false, fCheck2 = false;
    00848
    00849         CString style(_T("Default"));
    00850
    00851         CStringW buff;;
    00852         while(file->ReadString(buff))
    00853         {
    00854                 buff.Trim();
    00855                 if(buff.IsEmpty()) continue;
    00856
    00857                 int start, end;
    00858                 int c = swscanf(buff, L"{%d}{%d}", &start, &end);
    00859
    00860                 if(c != 2) {c = swscanf(buff, L"{%d}{}", &start)+1; end = start + 60; fCheck = true;}
    00861
    00862                 if(c != 2)
    00863                 {
    00864                         int i;
    00865                         if(buff.Find('{') == 0 && (i = buff.Find('}')) > 1 && i < buff.GetLength())
    00866                         {
    00867                                 if(STSStyle* s = GetMicroDVDStyle(WToT(buff.Mid(i+1)), CharSet))
    00868                                 {
    00869                                         style = buff.Mid(1, i-1);
    00870                                         style.MakeUpper();
    00871                                         if(style.GetLength()) {CString str = style.Mid(1); str.MakeLower(); style = style.Left(1) + str;}
    00872                                         ret.AddStyle(style, s);
    00873                                         CharSet = s->charSet;
    00874                                         continue;
    00875                                 }
    00876                         }
    00877                 }
    00878
    00879                 if(c == 2)
    00880                 {
    00881                         if(fCheck2 && ret.GetSize())
    00882                         {
    00883                                 STSEntry& stse = ret[ret.GetSize()-1];
    00884                                 stse.end = min(stse.end, start);
    00885                                 fCheck2 = false;
    00886                         }
    00887
    00888                         ret.Add(
    00889                                 MicroDVD2SSA(buff.Mid(buff.Find('}', buff.Find('}')+1)+1), file->IsUnicode(), CharSet),
    00890                                 file->IsUnicode(),
    00891                                 start, end,
    00892                                 style);
    00893
    00894                         if(fCheck)
    00895                         {
    00896                                 fCheck = false;
    00897                                 fCheck2 = true;
    00898                         }
    00899                 }
    00900                 else if(c != EOF) // might be another format
    00901                 {
    00902                         return(false);
    00903                 }
    00904         }
    00905
    00906         return(ret.GetCount() > 0);
    00907 }
    00908
    00909 static void ReplaceNoCase(CStringW& str, CStringW from, CStringW to)
    00910 {
    00911         CStringW lstr = str;
    00912         lstr.MakeLower();
    00913
    00914         int i, j, k;
    00915
    00916         for(i = 0, j = str.GetLength(); i < j; )
    00917         {
    00918                 if((k = lstr.Find(from, i)) >= 0)
    00919                 {
    00920                         str.Delete(k, from.GetLength()); lstr.Delete(k, from.GetLength());
    00921                         str.Insert(k, to); lstr.Insert(k, to);
    00922                         i = k + to.GetLength();
    00923                         j = str.GetLength();
    00924                 }
    00925                 else break;
    00926         }
    00927 }
    00928
    00929 static CStringW SMI2SSA(CStringW str, int CharSet)
    00930 {
    00931         ReplaceNoCase(str, L"&nbsp;", L" ");
    00932         ReplaceNoCase(str, L"&quot;", L"\"");
    00933         ReplaceNoCase(str, L"<br>", L"\\N");
    00934         ReplaceNoCase(str, L"<i>", L"{\\i1}");
    00935         ReplaceNoCase(str, L"</i>", L"{\\i}");
    00936         ReplaceNoCase(str, L"<b>", L"{\\b1}");
    00937         ReplaceNoCase(str, L"</b>", L"{\\b}");
    00938
    00939         CStringW lstr = str;
    00940         lstr.MakeLower();
    00941
    00942         // maven@maven.de
    00943         // now parse line
    00944         for(int i = 0, j = str.GetLength(); i < j; )
    00945         {
    00946                 int k;
    00947                 if((k = lstr.Find('<', i)) < 0) break;
    00948
    00949                 int chars_inserted = 0;
    00950
    00951                 int l = 1;
    00952                 for(; k+l < j && lstr[k+l] != '>'; l++);
    00953                 l++;
    00954
    00955 // Modified by Cookie Monster
    00956                 if (lstr.Find(L"<font ", k) == k)
    00957                 {
    00958                         CStringW args = lstr.Mid(k+6, l-6);     // delete "<font "
    00959                         CStringW arg ;
    00960
    00961                         args.Remove('\"'); args.Remove('#');    // may include 2 * " + #
    00962                         arg.TrimLeft(); arg.TrimRight(L" >");
    00963
    00964                         for (;;)
    00965                         {
    00966                                 args.TrimLeft();
    00967                                 arg = args.SpanExcluding(L" \t>");
    00968                                 args = args.Mid(arg.GetLength());
    00969
    00970                                 if(arg.IsEmpty())
    00971                                         break;
    00972                                 if (arg.Find(L"color=") == 0 )
    00973                                 {
    00974                                         DWORD color;
    00975
    00976                                         arg = arg.Mid(6);       // delete "color="
    00977                                         if ( arg.IsEmpty())
    00978                                                 continue;
    00979
    00980                                         CString key = WToT(arg);
    00981                                         void* val;
    00982                                         if(g_colors.Lookup(key, val))
    00983                                                 color = (DWORD)val;
    00984                                         else if ( (color = wcstol(arg, NULL, 16) ) == 0 )
    00985                                                 color = 0x00ffffff;  // default is white
    00986
    00987                                         arg.Format(L"%02x%02x%02x", color&0xff, (color>>8)&0xff, (color>>16)&0xff);
    00988                                         lstr.Insert(k + l + chars_inserted, CStringW(L"{\\c&H") + arg + L"&}");
    00989                                         str.Insert(k + l + chars_inserted, CStringW(L"{\\c&H") + arg + L"&}");
    00990                                         chars_inserted += 5 + arg.GetLength() + 2;
    00991                                 }
    00992 /*
    00993                                 else if (arg.Find(_T("size=" )) == 0 )
    00994                                 {
    00995                                         uint fsize;
    00996
    00997                                         arg = arg.Mid(5);       // delete "size="
    00998                                         if ( arg.GetLength() == 0)
    00999                                                 continue;
    01000
    01001                                         if ( fsize = _tcstol(arg, &tmp, 10) == 0 )
    01002                                                 continue;
    01003
    01004                                         lstr.Insert(k + l + chars_inserted, CString(_T("{\\fs")) + arg + _T("&}"));
    01005                                         str.Insert(k + l + chars_inserted, CString(_T("{\\fs")) + arg + _T("&}"));
    01006                                         chars_inserted += 4 + arg.GetLength() + 2;
    01007                                 }
    01008 */
    01009                         }
    01010                 }
    01011
    01012 // Original Code
    01013 /*
    01014                 if (lstr.Find(L"<font color=", k) == k)
    01015                 {
    01016                         CStringW arg = lstr.Mid(k+12, l-12); // may include 2 * " + #
    01017
    01018                         arg.Remove('\"');
    01019                         arg.Remove('#');
    01020                         arg.TrimLeft(); arg.TrimRight(L" >");
    01021
    01022                         if(arg.GetLength() > 0)
    01023                         {
    01024                                 DWORD color;
    01025
    01026                                 CString key = WToT(arg);
    01027                                 void* val;
    01028                                 if(g_colors.Lookup(key, val)) color = (DWORD)val;
    01029                                 else color = wcstol(arg, NULL, 16);
    01030
    01031                                 arg.Format(L"%02x%02x%02x", color&0xff, (color>>8)&0xff, (color>>16)&0xff);
    01032                         }
    01033
    01034                         lstr.Insert(k + l + chars_inserted, L"{\\c&H" + arg + L"&}");
    01035                         str.Insert(k + l + chars_inserted, L"{\\c&H" + arg + L"&}");
    01036                         chars_inserted += 5 + arg.GetLength() + 2;
    01037                 }
    01038 */
    01039                 else if (lstr.Find(L"</font>", k) == k)
    01040                 {
    01041                         lstr.Insert(k + l + chars_inserted, L"{\\c}");
    01042                         str.Insert(k + l + chars_inserted, L"{\\c}");
    01043                         chars_inserted += 4;
    01044                 }
    01045
    01046                 str.Delete(k, l); lstr.Delete(k, l);
    01047                 i = k + chars_inserted;
    01048                 j = str.GetLength();
    01049         }
    01050
    01051         return(str);
    01052 }
    01053
    01054 static bool OpenSami(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01055 {
    01056         CStringW buff, caption;
    01057
    01058         ULONGLONG pos = file->GetPosition();
    01059
    01060         bool fSAMI = false;
    01061
    01062         while(file->ReadString(buff) && !fSAMI)
    01063         {
    01064                 if(buff.MakeUpper().Find(L"<SAMI>") >= 0) fSAMI = true;
    01065         }
    01066
    01067         if(!fSAMI) return(false);
    01068
    01069         file->Seek(pos, 0);
    01070
    01071         bool fComment = false;
    01072
    01073         int start_time = 0;
    01074
    01075         while(file->ReadString(buff))
    01076         {
    01077                 buff.Trim();
    01078                 if(buff.IsEmpty()) continue;
    01079
    01080                 CStringW ubuff = buff;
    01081                 ubuff.MakeUpper();
    01082
    01083                 if(ubuff.Find(L"<!--") >= 0 || ubuff.Find(L"<TITLE>") >= 0)
    01084                         fComment = true;
    01085
    01086                 if(!fComment)
    01087                 {
    01088                         int i;
    01089
    01090                         if((i = ubuff.Find(L"<SYNC START=")) >= 0)
    01091                         {
    01092                                 int time = 0;
    01093
    01094                                 for(i = 12; i < ubuff.GetLength(); i++)
    01095                                 {
    01096                                         if(ubuff[i] != '>' && ubuff[i] != 'M')
    01097                                         {
    01098                                                 if(iswdigit(ubuff[i]))
    01099                                                 {
    01100                                                         time *= 10;
    01101                                                         time += ubuff[i] - 0x30;
    01102                                                 }
    01103                                         }
    01104                                         else break;
    01105                                 }
    01106
    01107                                 ret.Add(
    01108                                         SMI2SSA(caption, CharSet),
    01109                                         file->IsUnicode(),
    01110                                         start_time, time);
    01111
    01112                                 start_time = time;
    01113                                 caption.Empty();
    01114                         }
    01115
    01116                         caption += buff;
    01117                 }
    01118
    01119                 if(ubuff.Find(L"-->") >= 0 || ubuff.Find(L"</TITLE>") >= 0)
    01120                         fComment = false;
    01121         }
    01122
    01123         ret.Add(
    01124                 SMI2SSA(caption, CharSet),
    01125                 file->IsUnicode(),
    01126                 start_time, MAXLONG);
    01127
    01128         return(true);
    01129 }
    01130
    01131 static bool OpenVPlayer(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01132 {
    01133         CStringW buff;
    01134         while(file->ReadString(buff))
    01135         {
    01136                 buff.Trim();
    01137                 if(buff.IsEmpty()) continue;
    01138
    01139                 for(int i = 0; i < buff.GetLength(); i++)
    01140                 {
    01141                         if((i = FindChar(buff, '|', i, file->IsUnicode(), CharSet)) < 0) break;
    01142                         buff.SetAt(i, '\n');
    01143                 }
    01144
    01145                 int hh, mm, ss;
    01146                 int c = swscanf(buff, L"%d:%d:%d:", &hh, &mm, &ss);
    01147
    01148                 if(c == 3)
    01149                 {
    01150                         CStringW str = buff.Mid(buff.Find(':', buff.Find(':', buff.Find(':')+1)+1)+1);
    01151                         ret.Add(str,
    01152                                 file->IsUnicode(),
    01153                                 (((hh*60 + mm)*60) + ss)*1000,
    01154                                 (((hh*60 + mm)*60) + ss)*1000 + 1000 + 50*str.GetLength());
    01155                 }
    01156                 else if(c != EOF) // might be another format
    01157                 {
    01158                         return(false);
    01159                 }
    01160         }
    01161
    01162         return(ret.GetCount() > 0);
    01163 }
    01164
    01165 CStringW GetStr(CStringW& buff, char sep = ',') //throw(...)
    01166 {
    01167         buff.TrimLeft();
    01168
    01169         int pos = buff.Find(sep);
    01170         if(pos < 0)
    01171         {
    01172                 pos = buff.GetLength();
    01173                 if(pos < 1) throw 1;
    01174         }
    01175
    01176         CStringW ret = buff.Left(pos);
    01177         if(pos < buff.GetLength()) buff = buff.Mid(pos+1);
    01178
    01179         return(ret);
    01180 }
    01181
    01182 int GetInt(CStringW& buff, char sep = ',') //throw(...)
    01183 {
    01184         CStringW str;
    01185
    01186         str = GetStr(buff, sep);
    01187         str.MakeLower();
    01188
    01189         CStringW fmtstr = str.GetLength() > 2 && (str.Left(2) == L"&h" || str.Left(2) == L"0x")
    01190                 ? str = str.Mid(2), L"%x"
    01191                 : L"%d";
    01192
    01193         int ret;
    01194         if(swscanf(str, fmtstr, &ret) != 1) throw 1;
    01195
    01196         return(ret);
    01197 }
    01198
    01199 double GetFloat(CStringW& buff, char sep = ',') //throw(...)
    01200 {
    01201         CStringW str;
    01202
    01203         str = GetStr(buff, sep);
    01204         str.MakeLower();
    01205
    01206         float ret;
    01207         if(swscanf(str, L"%f", &ret) != 1) throw 1;
    01208
    01209         return((double)ret);
    01210 }
    01211
    01212 static bool LoadFont(CString& font)
    01213 {
    01214         int len = font.GetLength();
    01215
    01216         CAutoVectorPtr<BYTE> pData;
    01217         if(len == 0 || (len&3) == 1 || !pData.Allocate(len))
    01218                 return(false);
    01219
    01220         const TCHAR* s = font;
    01221         const TCHAR* e = s + len;
    01222         for(BYTE* p = pData; s < e; s++, p++) *p = *s - 33;
    01223
    01224         for(int i = 0, j = 0, k = len&~3; i < k; i+=4, j+=3)
    01225         {
    01226                 pData[j+0] = ((pData[i+0]&63)<<2)|((pData[i+1]>>4)& 3);
    01227                 pData[j+1] = ((pData[i+1]&15)<<4)|((pData[i+2]>>2)&15);
    01228                 pData[j+2] = ((pData[i+2]& 3)<<6)|((pData[i+3]>>0)&63);
    01229         }
    01230
    01231         int datalen = (len&~3)*3/4;
    01232
    01233         if((len&3) == 2)
    01234         {
    01235                 pData[datalen++] = ((pData[(len&~3)+0]&63)<<2)|((pData[(len&~3)+1]>>4)&3);
    01236         }
    01237         else if((len&3) == 3)
    01238         {
    01239                 pData[datalen++] = ((pData[(len&~3)+0]&63)<<2)|((pData[(len&~3)+1]>>4)& 3);
    01240                 pData[datalen++] = ((pData[(len&~3)+1]&15)<<4)|((pData[(len&~3)+2]>>2)&15);
    01241         }
    01242
    01243         HANDLE hFont = INVALID_HANDLE_VALUE;
    01244
    01245         if(HMODULE hModule = LoadLibrary(_T("GDI32.DLL")))
    01246         {
    01247                 typedef HANDLE (WINAPI *PAddFontMemResourceEx)( IN PVOID, IN DWORD, IN PVOID , IN DWORD*);
    01248                 if(PAddFontMemResourceEx f = (PAddFontMemResourceEx)GetProcAddress(hModule, "AddFontMemResourceEx"))
    01249                 {
    01250                         DWORD cFonts;
    01251                         hFont = f(pData, datalen, NULL, &cFonts);
    01252                 }
    01253
    01254                 FreeLibrary(hModule);
    01255         }
    01256
    01257         if(hFont == INVALID_HANDLE_VALUE)
    01258         {
    01259                 TCHAR path[MAX_PATH];
    01260                 GetTempPath(MAX_PATH, path);
    01261
    01262                 DWORD chksum = 0;
    01263                 for(int i = 0, j = datalen>>2; i < j; i++)
    01264                         chksum += ((DWORD*)(BYTE*)pData)[i];
    01265
    01266                 CString fn;
    01267                 fn.Format(_T("%sfont%08x.ttf"), path, chksum);
    01268
    01269                 CFileStatus     fs;
    01270                 if(!CFileGetStatus(fn, fs))
    01271                 {
    01272                         CFile f;
    01273                         if(f.Open(fn, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary|CFile::shareDenyWrite))
    01274                         {
    01275                                 f.Write(pData, datalen);
    01276                                 f.Close();
    01277                         }
    01278                 }
    01279
    01280                 AddFontResource(fn);
    01281         }
    01282
    01283         return(true);
    01284 }
    01285
    01286 static bool LoadUUEFont(CTextFile* file)
    01287 {
    01288         CString s, font;
    01289         while(file->ReadString(s))
    01290         {
    01291                 s.Trim();
    01292                 if(s.IsEmpty() || s[0] == '[') break;
    01293                 if(s.Find(_T("fontname:")) == 0) {LoadFont(font); font.Empty(); continue;}
    01294
    01295                 font += s;
    01296         }
    01297
    01298         if(!font.IsEmpty())
    01299                 LoadFont(font);
    01300
    01301         return(true);
    01302 }
    01303
    01304 static bool OpenSubStationAlpha(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01305 {
    01306         bool fRet = false;
    01307
    01308         int version = 3, sver = 3;
    01309
    01310         CStringW buff;
    01311         while(file->ReadString(buff))
    01312         {
    01313                 buff.Trim();
    01314                 if(buff.IsEmpty() || buff.GetAt(0) == ';') continue;
    01315
    01316                 CStringW entry;
    01317
    01318 //              try {
    01319                         entry = GetStr(buff, ':');
    01320 //      }
    01321 //              catch(...) {continue;}
    01322
    01323                 entry.MakeLower();
    01324
    01325                 if(entry == L"[script info]")
    01326                 {
    01327                         fRet = true;
    01328                 }
    01329                 else if(entry == L"playresx")
    01330                 {
    01331                         try {ret.m_dstScreenSize.cx = GetInt(buff);}
    01332                         catch(...) {ret.m_dstScreenSize = CSize(0, 0); return(false);}
    01333
    01334                         if(ret.m_dstScreenSize.cy <= 0)
    01335                         {
    01336                                 ret.m_dstScreenSize.cy = (ret.m_dstScreenSize.cx == 1280)
    01337                                         ? 1024
    01338                                         : ret.m_dstScreenSize.cx * 3 / 4;
    01339                         }
    01340                 }
    01341                 else if(entry == L"playresy")
    01342                 {
    01343                         try {ret.m_dstScreenSize.cy = GetInt(buff);}
    01344                         catch(...) {ret.m_dstScreenSize = CSize(0, 0); return(false);}
    01345
    01346                         if(ret.m_dstScreenSize.cx <= 0)
    01347                         {
    01348                                 ret.m_dstScreenSize.cx = (ret.m_dstScreenSize.cy == 1024)
    01349                                         ? 1280
    01350                                         : ret.m_dstScreenSize.cy * 4 / 3;
    01351                         }
    01352                 }
    01353                 else if(entry == L"wrapstyle")
    01354                 {
    01355                         try {ret.m_defaultWrapStyle = GetInt(buff);}
    01356                         catch(...) {ret.m_defaultWrapStyle = 1; return(false);}
    01357                 }
    01358                 else if(entry == L"scripttype")
    01359                 {
    01360                         if(buff.GetLength() >= 4 && !buff.Right(4).CompareNoCase(L"4.00")) version = sver = 4;
    01361                         else if(buff.GetLength() >= 5 && !buff.Right(5).CompareNoCase(L"4.00+")) version = sver = 5;
    01362                 }
    01363                 else if(entry == L"collisions")
    01364                 {
    01365                         buff = GetStr(buff);
    01366                         buff.MakeLower();
    01367                         ret.m_collisions = buff.Find(L"reverse") >= 0 ? 1 : 0;
    01368                 }
    01369                 else if(entry == L"scaledborderandshadow")
    01370                 {
    01371                         buff = GetStr(buff);
    01372                         buff.MakeLower();
    01373                         ret.m_fScaledBAS = buff.Find(L"yes") >= 0;
    01374                 }
    01375                 else if(entry == L"[v4 styles]")
    01376                 {
    01377                         fRet = true;
    01378             sver = 4;
    01379                 }
    01380                 else if(entry == L"[v4+ styles]")
    01381                 {
    01382                         fRet = true;
    01383             sver = 5;
    01384                 }
    01385                 else if(entry == L"style")
    01386                 {
    01387                         STSStyle* style = new STSStyle;
    01388                         if(!style) return(false);
    01389
    01390                         try
    01391                         {
    01392                                 CString StyleName;
    01393                                 int alpha;
    01394
    01395                                 StyleName = WToT(GetStr(buff));
    01396                                 style->fontName = WToT(GetStr(buff));
    01397                                 style->fontSize = GetFloat(buff);
    01398                                 for(int i = 0; i < 4; i++) style->colors[i] = (COLORREF)GetInt(buff);
    01399                                 style->fontWeight = !!GetInt(buff) ? FW_BOLD : FW_NORMAL;
    01400                                 style->fItalic = !!GetInt(buff);
    01401 if(sver >= 5)   style->fUnderline = !!GetInt(buff);
    01402 if(sver >= 5)   style->fStrikeOut = !!GetInt(buff);
    01403 if(sver >= 5)   style->fontScaleX = GetFloat(buff);
    01404 if(sver >= 5)   style->fontScaleY = GetFloat(buff);
    01405 if(sver >= 5)   style->fontSpacing = GetFloat(buff);
    01406 if(sver >= 5)   style->fontAngleZ = GetFloat(buff);
    01407 if(sver >= 4)   style->borderStyle = GetInt(buff);
    01408                                 style->outlineWidth = GetFloat(buff);
    01409                                 style->shadowDepth = GetFloat(buff);
    01410                                 style->scrAlignment = GetInt(buff);
    01411                                 style->marginRect.left = GetInt(buff);
    01412                                 style->marginRect.right = GetInt(buff);
    01413                                 style->marginRect.top = style->marginRect.bottom = GetInt(buff);
    01414 if(sver <= 4)   alpha = GetInt(buff);
    01415                                 style->charSet = GetInt(buff);
    01416
    01417 if(sver <= 4)   style->colors[2] = style->colors[3]; // style->colors[2] is used for drawing the outline
    01418 if(sver <= 4)   alpha = max(min(alpha, 0xff), 0);
    01419 if(sver <= 4)   {for(int i = 0; i < 3; i++) style->alpha[i] = alpha; style->alpha[3] = 0x80;}
    01420 if(sver >= 5)   for(int i = 0; i < 4; i++) {style->alpha[i] = (BYTE)(style->colors[i]>>24); style->colors[i] &= 0xffffff;}
    01421 if(sver >= 5)   style->fontScaleX = max(style->fontScaleX, 0);
    01422 if(sver >= 5)   style->fontScaleY = max(style->fontScaleY, 0);
    01423 if(sver >= 5)   style->fontSpacing = max(style->fontSpacing, 0);
    01424                                 style->fontAngleX = style->fontAngleY = 0;
    01425                                 style->borderStyle = style->borderStyle == 1 ? 0 : style->borderStyle == 3 ? 1 : 0;
    01426                                 style->outlineWidth = max(style->outlineWidth, 0);
    01427                                 style->shadowDepth = max(style->shadowDepth, 0);
    01428 if(sver <= 4)   style->scrAlignment = (style->scrAlignment&4) ? ((style->scrAlignment&3)+6) // top
    01429                                                                                 : (style->scrAlignment&8) ? ((style->scrAlignment&3)+3) // mid
    01430                                                                                 : (style->scrAlignment&3); // bottom
    01431
    01432                                 StyleName.TrimLeft('*');
    01433
    01434                                 ret.AddStyle(StyleName, style);
    01435                         }
    01436                         catch(...)
    01437                         {
    01438                                 delete style;
    01439                                 return(false);
    01440                         }
    01441                 }
    01442                 else if(entry == L"[events]")
    01443                 {
    01444                         fRet = true;
    01445                 }
    01446                 else if(entry == _T("dialogue"))
    01447                 {
    01448                         try
    01449                         {
    01450                                 int hh1, mm1, ss1, ms1_div10, hh2, mm2, ss2, ms2_div10, layer = 0;
    01451                                 CString Style, Actor, Effect;
    01452                                 CRect marginRect;
    01453
    01454 if(version <= 4){GetStr(buff, '='); GetInt(buff);} /* Marked = */
    01455 if(version >= 5)layer = GetInt(buff);
    01456                                 hh1 = GetInt(buff, ':');
    01457                                 mm1 = GetInt(buff, ':');
    01458                                 ss1 = GetInt(buff, '.');
    01459                                 ms1_div10 = GetInt(buff);
    01460                                 hh2 = GetInt(buff, ':');
    01461                                 mm2 = GetInt(buff, ':');
    01462                                 ss2 = GetInt(buff, '.');
    01463                                 ms2_div10 = GetInt(buff);
    01464                                 Style = WToT(GetStr(buff));
    01465                                 Actor = WToT(GetStr(buff));
    01466                                 marginRect.left = GetInt(buff);
    01467                                 marginRect.right = GetInt(buff);
    01468                                 marginRect.top = marginRect.bottom = GetInt(buff);
    01469                                 Effect = WToT(GetStr(buff));
    01470
    01471                                 int len = min(Effect.GetLength(), buff.GetLength());
    01472                                 if(Effect.Left(len) == WToT(buff.Left(len))) Effect.Empty();
    01473
    01474                                 Style.TrimLeft('*');
    01475                                 if(!Style.CompareNoCase(_T("Default"))) Style = _T("Default");
    01476
    01477                                 ret.Add(buff,
    01478                                         file->IsUnicode(),
    01479                                         (((hh1*60 + mm1)*60) + ss1)*1000 + ms1_div10*10,
    01480                                         (((hh2*60 + mm2)*60) + ss2)*1000 + ms2_div10*10,
    01481                                         Style, Actor, Effect,
    01482                                         marginRect,
    01483                                         layer);
    01484                         }
    01485                         catch(...)
    01486                         {
    01487                                 return(false);
    01488                         }
    01489                 }
    01490                 else if(entry == L"fontname")
    01491                 {
    01492                         LoadUUEFont(file);
    01493                 }
    01494         }
    01495
    01496         return(fRet);
    01497 }
    01498
    01499 static bool OpenXombieSub(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01500 {
    01501         float version = 0;
    01502
    01503 //      CMapStringToPtr stylemap;
    01504
    01505         CStringW buff;
    01506         while(file->ReadString(buff))
    01507         {
    01508                 buff.Trim();
    01509                 if(buff.IsEmpty() || buff.GetAt(0) == ';') continue;
    01510
    01511                 CStringW entry;
    01512
    01513 //              try {
    01514                         entry = GetStr(buff, '=');
    01515 //      }
    01516 //              catch(...) {continue;}
    01517
    01518                 entry.MakeLower();
    01519
    01520                 if(entry == L"version")
    01521                 {
    01522             version = (float)GetFloat(buff);
    01523                 }
    01524                 else if(entry == L"screenhorizontal")
    01525                 {
    01526                         try {ret.m_dstScreenSize.cx = GetInt(buff);}
    01527                         catch(...) {ret.m_dstScreenSize = CSize(0, 0); return(false);}
    01528
    01529                         if(ret.m_dstScreenSize.cy <= 0)
    01530                         {
    01531                                 ret.m_dstScreenSize.cy = (ret.m_dstScreenSize.cx == 1280)
    01532                                         ? 1024
    01533                                         : ret.m_dstScreenSize.cx * 3 / 4;
    01534                         }
    01535                 }
    01536                 else if(entry == L"screenvertical")
    01537                 {
    01538                         try {ret.m_dstScreenSize.cy = GetInt(buff);}
    01539                         catch(...) {ret.m_dstScreenSize = CSize(0, 0); return(false);}
    01540
    01541                         if(ret.m_dstScreenSize.cx <= 0)
    01542                         {
    01543                                 ret.m_dstScreenSize.cx = (ret.m_dstScreenSize.cy == 1024)
    01544                                         ? 1280
    01545                                         : ret.m_dstScreenSize.cy * 4 / 3;
    01546                         }
    01547                 }
    01548                 else if(entry == L"style")
    01549                 {
    01550                         STSStyle* style = new STSStyle;
    01551                         if(!style) return(false);
    01552
    01553                         try
    01554                         {
    01555                                 CString StyleName;
    01556
    01557                                 StyleName = WToT(GetStr(buff)) + _T("_") + WToT(GetStr(buff));
    01558                                 style->fontName = WToT(GetStr(buff));
    01559                                 style->fontSize = GetFloat(buff);
    01560                                 for(int i = 0; i < 4; i++) style->colors[i] = (COLORREF)GetInt(buff);
    01561                                 for(int i = 0; i < 4; i++) style->alpha[i] = GetInt(buff);
    01562                                 style->fontWeight = !!GetInt(buff) ? FW_BOLD : FW_NORMAL;
    01563                                 style->fItalic = !!GetInt(buff);
    01564                                 style->fUnderline = !!GetInt(buff);
    01565                                 style->fStrikeOut = !!GetInt(buff);
    01566                                 style->fBlur = !!GetInt(buff);
    01567                                 style->fontScaleX = GetFloat(buff);
    01568                                 style->fontScaleY = GetFloat(buff);
    01569                                 style->fontSpacing = GetFloat(buff);
    01570                                 style->fontAngleX = GetFloat(buff);
    01571                                 style->fontAngleY = GetFloat(buff);
    01572                                 style->fontAngleZ = GetFloat(buff);
    01573                                 style->borderStyle = GetInt(buff);
    01574                                 style->outlineWidth = GetFloat(buff);
    01575                                 style->shadowDepth = GetFloat(buff);
    01576                                 style->scrAlignment = GetInt(buff);
    01577                                 style->marginRect.left = GetInt(buff);
    01578                                 style->marginRect.right = GetInt(buff);
    01579                                 style->marginRect.top = style->marginRect.bottom = GetInt(buff);
    01580                                 style->charSet = GetInt(buff);
    01581
    01582                                 style->fontScaleX = max(style->fontScaleX, 0);
    01583                                 style->fontScaleY = max(style->fontScaleY, 0);
    01584                                 style->fontSpacing = max(style->fontSpacing, 0);
    01585                                 style->borderStyle = style->borderStyle == 1 ? 0 : style->borderStyle == 3 ? 1 : 0;
    01586                                 style->outlineWidth = max(style->outlineWidth, 0);
    01587                                 style->shadowDepth = max(style->shadowDepth, 0);
    01588
    01589                                 ret.AddStyle(StyleName, style);
    01590                         }
    01591                         catch(...)
    01592                         {
    01593                                 delete style;
    01594                                 return(false);
    01595                         }
    01596                 }
    01597                 else if(entry == L"line")
    01598                 {
    01599                         try
    01600                         {
    01601                                 CString id;
    01602                                 int hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, layer = 0;
    01603                                 CString Style, Actor;
    01604                                 CRect marginRect;
    01605
    01606                                 if(GetStr(buff) != L"D") continue;
    01607                                 id = GetStr(buff);
    01608                                 layer = GetInt(buff);
    01609                                 hh1 = GetInt(buff, ':');
    01610                                 mm1 = GetInt(buff, ':');
    01611                                 ss1 = GetInt(buff, '.');
    01612                                 ms1 = GetInt(buff);
    01613                                 hh2 = GetInt(buff, ':');
    01614                                 mm2 = GetInt(buff, ':');
    01615                                 ss2 = GetInt(buff, '.');
    01616                                 ms2 = GetInt(buff);
    01617                                 Style = WToT(GetStr(buff)) + _T("_") + WToT(GetStr(buff));
    01618                                 Actor = WToT(GetStr(buff));
    01619                                 marginRect.left = GetInt(buff);
    01620                                 marginRect.right = GetInt(buff);
    01621                                 marginRect.top = marginRect.bottom = GetInt(buff);
    01622
    01623                                 Style.TrimLeft('*');
    01624                                 if(!Style.CompareNoCase(_T("Default"))) Style = _T("Default");
    01625
    01626                                 ret.Add(buff,
    01627                                         file->IsUnicode(),
    01628                                         (((hh1*60 + mm1)*60) + ss1)*1000 + ms1,
    01629                                         (((hh2*60 + mm2)*60) + ss2)*1000 + ms2,
    01630                                         Style, Actor, _T(""),
    01631                                         marginRect,
    01632                                         layer);
    01633                         }
    01634                         catch(...)
    01635                         {
    01636                                 return(false);
    01637                         }
    01638                 }
    01639                 else if(entry == L"fontname")
    01640                 {
    01641                         LoadUUEFont(file);
    01642                 }
    01643         }
    01644
    01645         return(ret.GetCount() > 0);
    01646 }
    01647
    01648 #include "USFSubtitles.h"
    01649
    01650 static bool OpenUSF(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01651 {
    01652         CString str;
    01653         while(file->ReadString(str))
    01654         {
    01655                 if(str.Find(_T("USFSubtitles")) >= 0)
    01656                 {
    01657                         CUSFSubtitles usf;
    01658                         if(usf.Read(file->GetFilePath()) && usf.ConvertToSTS(ret))
    01659                                 return(true);
    01660
    01661                         break;
    01662                 }
    01663         }
    01664
    01665         return(false);
    01666 }
    01667
    01668 static CStringW MPL22SSA(CStringW str)
    01669 {
    01670         CList<CStringW> sl;
    01671         Explode(str, sl, '|');
    01672         POSITION pos = sl.GetHeadPosition();
    01673         while(pos)
    01674         {
    01675                 CStringW& s = sl.GetNext(pos);
    01676                 if(s[0] == '/') {s = L"{\\i1}" + s.Mid(1) + L"{\\i0}";}
    01677         }
    01678         str = Implode(sl, '\n');
    01679         str.Replace(L"\n", L"\\N");
    01680         return str;
    01681 }
    01682
    01683 static bool OpenMPL2(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
    01684 {
    01685         CStringW buff;;
    01686         while(file->ReadString(buff))
    01687         {
    01688                 buff.Trim();
    01689                 if(buff.IsEmpty()) continue;
    01690
    01691                 int start, end;
    01692                 int c = swscanf(buff, L"[%d][%d]", &start, &end);
    01693
    01694                 if(c == 2)
    01695                 {
    01696                         ret.Add(
    01697                                 MPL22SSA(buff.Mid(buff.Find(']', buff.Find(']')+1)+1)),
    01698                                 file->IsUnicode(),
    01699                                 start*100, end*100);
    01700                 }
    01701                 else if(c != EOF) // might be another format
    01702                 {
    01703                         return(false);
    01704                 }
    01705         }
    01706
    01707         return(ret.GetCount() > 0);
    01708 }
    01709
    01710 typedef bool (*STSOpenFunct)(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet);
    01711
    01712 typedef struct {STSOpenFunct open; tmode mode;} OpenFunctStruct;
    01713
    01714 static OpenFunctStruct OpenFuncts[] =
    01715 {
    01716         OpenSubRipper, TIME,
    01717         OpenOldSubRipper, TIME,
    01718         OpenSubViewer, TIME,
    01719         OpenMicroDVD, FRAME,
    01720         OpenSami, TIME,
    01721         OpenVPlayer, TIME,
    01722         OpenSubStationAlpha, TIME,
    01723         OpenXombieSub, TIME,
    01724         OpenUSF, TIME,
    01725         OpenMPL2, TIME,
    01726 };
    01727
    01728 static int nOpenFuncts = countof(OpenFuncts);
    01729
    01730 //
    01731
    01732 CSimpleTextSubtitle::CSimpleTextSubtitle()
    01733 {
    01734         m_mode = TIME;
    01735         m_dstScreenSize = CSize(0, 0);
    01736         m_defaultWrapStyle = 0;
    01737         m_collisions = 0;
    01738         m_fScaledBAS = false;
    01739         m_encoding = CTextFile::ASCII;
    01740 }
    01741
    01742 CSimpleTextSubtitle::~CSimpleTextSubtitle()
    01743 {
    01744         Empty();
    01745 }
    01746 /*
    01747 CSimpleTextSubtitle::CSimpleTextSubtitle(CSimpleTextSubtitle& sts)
    01748 {
    01749         *this = sts;
    01750 }
    01751
    01752 CSimpleTextSubtitle& CSimpleTextSubtitle::operator = (CSimpleTextSubtitle& sts)
    01753 {
    01754         Empty();
    01755
    01756         m_name = sts.m_name;
    01757         m_mode = sts.m_mode;
    01758         m_dstScreenSize = sts.m_dstScreenSize;
    01759         m_defaultWrapStyle = sts.m_defaultWrapStyle;
    01760         m_collisions = sts.m_collisions;
    01761         m_fScaledBAS = sts.m_fScaledBAS;
    01762         m_fSSA = sts.m_fSSA;
    01763         m_fUsingAutoGeneratedDefaultStyle = sts.m_fUsingAutoGeneratedDefaultStyle;
    01764         CopyStyles(sts.m_styles);
    01765         m_segments.Copy(sts.m_segments);
    01766         Copy(sts);
    01767
    01768         return(*this);
    01769 }
    01770 */
    01771
    01772 void CSimpleTextSubtitle::Copy(CSimpleTextSubtitle& sts)
    01773 {
    01774         Empty();
    01775
    01776         m_name = sts.m_name;
    01777         m_mode = sts.m_mode;
    01778         m_dstScreenSize = sts.m_dstScreenSize;
    01779         m_defaultWrapStyle = sts.m_defaultWrapStyle;
    01780         m_collisions = sts.m_collisions;
    01781         m_fScaledBAS = sts.m_fScaledBAS;
    01782         m_encoding = sts.m_encoding;
    01783         m_fUsingAutoGeneratedDefaultStyle = sts.m_fUsingAutoGeneratedDefaultStyle;
    01784         CopyStyles(sts.m_styles);
    01785         m_segments.Copy(sts.m_segments);
    01786         CSTSArray::Copy(sts);
    01787 }
    01788
    01789 void CSimpleTextSubtitle::Append(CSimpleTextSubtitle& sts, int timeoff)
    01790 {
    01791         if(timeoff < 0)
    01792         {
    01793                 timeoff = GetSize() > 0 ? GetAt(GetSize()-1).end : 0;
    01794         }
    01795
    01796         for(int i = 0, j = GetSize(); i < j; i++)
    01797         {
    01798                 if(GetAt(i).start > timeoff)
    01799                 {
    01800                         RemoveAt(i, j - i);
    01801                         break;
    01802                 }
    01803         }
    01804
    01805         CopyStyles(sts.m_styles, true);
    01806
    01807         for(int i = 0, j = sts.GetSize(); i < j; i++)
    01808         {
    01809                 STSEntry stse = sts.GetAt(i);
    01810                 stse.start += timeoff;
    01811                 stse.end += timeoff;
    01812                 stse.readorder += GetSize();
    01813                 CSTSArray::Add(stse);
    01814         }
    01815
    01816         CreateSegments();
    01817 }
    01818
    01819 void CSTSStyleMap::Free()
    01820 {
    01821         POSITION pos = GetStartPosition();
    01822         while(pos)
    01823         {
    01824                 CString key;
    01825                 void* ptr;
    01826                 GetNextAssoc(pos, key, ptr);
    01827                 delete (STSStyle*)ptr;
    01828         }
    01829
    01830         RemoveAll();
    01831 }
    01832
    01833 bool CSimpleTextSubtitle::CopyStyles(const CSTSStyleMap& styles, bool fAppend)
    01834 {
    01835         if(!fAppend) m_styles.Free();
    01836
    01837         POSITION pos = styles.GetStartPosition();
    01838         while(pos)
    01839         {
    01840                 CString key;
    01841                 void* ptr;
    01842                 styles.GetNextAssoc(pos, key, ptr);
    01843
    01844                 STSStyle* s = new STSStyle;
    01845                 if(!s) return(false);
    01846
    01847                 *s = *((STSStyle*)ptr);
    01848
    01849                 AddStyle(key, s);
    01850         }
    01851
    01852         return(true);
    01853 }
    01854
    01855 void CSimpleTextSubtitle::Empty()
    01856 {
    01857         m_dstScreenSize = CSize(0, 0);
    01858         m_styles.Free();
    01859         m_segments.RemoveAll();
    01860         RemoveAll();
    01861 }
    01862
    01863 void CSimpleTextSubtitle::Add(CStringW str, bool fUnicode, int start, int end, CString style, CString actor, CString effect, CRect marginRect, int layer, int readorder)
    01864 {
    01865         if(str.Trim().IsEmpty() || start > end) return;
    01866
    01867         str.Remove('\r');
    01868         str.Replace(L"\n", L"\\N");
    01869         if(style.IsEmpty()) style = _T("Default");
    01870         style.TrimLeft('*');
    01871
    01872         STSEntry sub;
    01873         sub.str = str;
    01874         sub.fUnicode = fUnicode;
    01875         sub.style = style;
    01876         sub.actor = actor;
    01877         sub.effect = effect;
    01878         sub.marginRect = marginRect;
    01879         sub.layer = layer;
    01880         sub.start = start;
    01881         sub.end = end;
    01882         sub.readorder = readorder < 0 ? GetSize() : readorder;
    01883         int n = CSTSArray::Add(sub);
    01884
    01885         int len = m_segments.GetSize();
    01886
    01887     if(len == 0)
    01888         {
    01889                 STSSegment stss(start, end);
    01890                 stss.subs.Add(n);
    01891                 m_segments.Add(stss);
    01892         }
    01893         else if(end <= m_segments[0].start)
    01894         {
    01895                 STSSegment stss(start, end);
    01896                 stss.subs.Add(n);
    01897                 m_segments.InsertAt(0, stss);
    01898         }
    01899         else if(start >= m_segments[len-1].end)
    01900         {
    01901                 STSSegment stss(start, end);
    01902                 stss.subs.Add(n);
    01903                 m_segments.Add(stss);
    01904         }
    01905         else
    01906         {
    01907                 if(start < m_segments[0].start)
    01908                 {
    01909                         STSSegment stss(start, m_segments[0].start);
    01910                         stss.subs.Add(n);
    01911                         start = m_segments[0].start;
    01912                         m_segments.InsertAt(0, stss);
    01913                 }
    01914
    01915                 for(int i = 0; i < m_segments.GetCount(); i++)
    01916                 {
    01917                         STSSegment& s = m_segments[i];
    01918
    01919                         if(start >= s.end)
    01920                                 continue;
    01921
    01922                         if(end <= s.start)
    01923                                 break;
    01924
    01925                         if(s.start < start && start < s.end)
    01926                         {
    01927                                 STSSegment stss(s.start, start);
    01928                                 stss.subs.Copy(s.subs);
    01929                                 s.start = start;
    01930                                 m_segments.InsertAt(i, stss);
    01931                                 continue;
    01932                         }
    01933
    01934                         if(start <= s.start && s.end <= end)
    01935                         {
    01936                                 for(int j = 0, k = s.subs.GetCount(); j <= k; j++)
    01937                                 {
    01938                                         if(j == k || sub.readorder < GetAt(s.subs[j]).readorder)
    01939                                                 s.subs.InsertAt(j, n);
    01940                                 }
    01941 //                              s.subs.Add(n);
    01942                         }
    01943
    01944                         if(s.start < end && end < s.end)
    01945                         {
    01946                                 STSSegment stss(s.start, end);
    01947                                 stss.subs.Copy(s.subs);
    01948                                 for(int j = 0, k = s.subs.GetCount(); j <= k; j++)
    01949                                 {
    01950                                         if(j == k || sub.readorder < GetAt(stss.subs[j]).readorder)
    01951                                                 stss.subs.InsertAt(j, n);
    01952                                 }
    01953 //                              stss.subs.Add(n);
    01954                                 s.start = end;
    01955                                 m_segments.InsertAt(i, stss);
    01956                         }
    01957                 }
    01958
    01959                 if(end > m_segments[m_segments.GetCount()-1].end)
    01960                 {
    01961                         STSSegment stss(m_segments[m_segments.GetCount()-1].end, end);
    01962                         stss.subs.Add(n);
    01963                         m_segments.Add(stss);
    01964                 }
    01965         }
    01966
    01967 /*
    01968         str.Remove('\r');
    01969         str.Replace(L"\n", L"\\N");
    01970         if(style.IsEmpty()) style = _T("Default");
    01971
    01972         int j = m_segments.GetSize();
    01973         for(int i = j-1; i >= 0; i--)
    01974         {
    01975                 if(m_segments[i].end <= start)
    01976                 {
    01977                         break;
    01978                 }
    01979                 else if(m_segments[i].start >= start)
    01980                 {
    01981                         m_segments.SetSize(m_segments.GetSize()-1);
    01982                         j--;
    01983                 }
    01984                 else if(m_segments[i].end > start)
    01985                 {
    01986                         if(i < j-1) m_segments.RemoveAt(i+1, j-i-1);
    01987                         m_segments[i].end = start;
    01988                         break;
    01989                 }
    01990         }
    01991
    01992         if(m_segments.GetSize() == 0 && j > 0)
    01993                 CSTSArray::RemoveAll();
    01994
    01995         STSSegment stss(start, end);
    01996         int len = GetSize();
    01997         stss.subs.Add(len);
    01998         m_segments.Add(stss);
    01999
    02000         STSEntry sub;
    02001         sub.str = str;
    02002         sub.fUnicode = fUnicode;
    02003         sub.style = style;
    02004         sub.actor = actor;
    02005         sub.effect = effect;
    02006         sub.marginRect = marginRect;
    02007         sub.layer = layer;
    02008         sub.start = start;
    02009         sub.end = end;
    02010         sub.readorder = GetSize();
    02011         CSTSArray::Add(sub);
    02012 */
    02013 }
    02014
    02015 void CSimpleTextSubtitle::CreateDefaultStyle(int CharSet)
    02016 {
    02017         CString def(_T("Default"));
    02018         void* value;
    02019
    02020 //      if(m_styles.IsEmpty())
    02021         if(!m_styles.Lookup(def, value))
    02022         {
    02023                 STSStyle* style = new STSStyle;
    02024                 if(!style) return;
    02025
    02026                 style->charSet = CharSet;
    02027
    02028                 AddStyle(def, style);
    02029 /*
    02030                 for(int i = 0; i < GetSize(); i++)
    02031                 {
    02032                         (*this)[i].style = def;
    02033                 }
    02034 */
    02035                 m_fUsingAutoGeneratedDefaultStyle = true;
    02036         }
    02037         else
    02038         {
    02039                 m_fUsingAutoGeneratedDefaultStyle = false;
    02040         }
    02041 }
    02042
    02043 void CSimpleTextSubtitle::ChangeUnknownStylesToDefault()
    02044 {
    02045         CMapStringToPtr unknown;
    02046         bool fReport = true;
    02047
    02048         for(int i = 0; i < GetSize(); i++)
    02049         {
    02050                 STSEntry& stse = GetAt(i);
    02051
    02052                 void* val;
    02053                 if(!m_styles.Lookup(stse.style, val))
    02054                 {
    02055                         if(!unknown.Lookup(stse.style, val))
    02056                         {
    02057                                 if(fReport)
    02058                                 {
    02059                                         CString msg;
    02060                                         msg.Format(_T("Unknown style found: \"%s\", changed to \"Default\"!\n\nPress Cancel to ignore further warnings."), stse.style);
    02061                                         if(MessageBox(NULL, msg, _T("Warning"), MB_OKCANCEL|MB_ICONWARNING) != IDOK) fReport = false;
    02062                                 }
    02063
    02064                                 unknown[stse.style] = NULL;
    02065                         }
    02066
    02067                         stse.style = _T("Default");
    02068                 }
    02069         }
    02070 }
    02071
    02072 void CSimpleTextSubtitle::AddStyle(CString name, STSStyle* style)
    02073 {
    02074         int i, j;
    02075
    02076         if(name.IsEmpty()) name = _T("Default");
    02077
    02078         void* value;
    02079         if(m_styles.Lookup(name, value))
    02080         {
    02081                 if(*((STSStyle*)value) == *style)
    02082                 {
    02083                         delete style;
    02084                         return;
    02085                 }
    02086
    02087                 int len = name.GetLength();
    02088
    02089                 for(i = len; i > 0 && _istdigit(name[i-1]); i--);
    02090
    02091                 int idx = 1;
    02092
    02093                 CString name2 = name;
    02094
    02095                 if(i < len && _stscanf(name.Right(len-i), _T("%d"), &idx) == 1)
    02096                 {
    02097                         name2 = name.Left(i);
    02098                 }
    02099
    02100                 idx++;
    02101
    02102                 CString name3;
    02103                 do
    02104                 {
    02105                         name3.Format(_T("%s%d"), name2, idx);
    02106                         idx++;
    02107                 }
    02108                 while(m_styles[name3]);
    02109
    02110                 m_styles.RemoveKey(name);
    02111                 m_styles[name3] = (STSStyle*)value;
    02112
    02113                 for(i = 0, j = GetSize(); i < j; i++)
    02114                 {
    02115                         STSEntry& stse = GetAt(i);
    02116                         if(stse.style == name) stse.style = name3;
    02117                 }
    02118         }
    02119
    02120         m_styles[name] = style;
    02121 }
    02122
    02123 bool CSimpleTextSubtitle::SetDefaultStyle(STSStyle& s)
    02124 {
    02125         void* val;
    02126         if(m_styles.Lookup(_T("Default"), val))
    02127         {
    02128                 *((STSStyle*)val) = s;
    02129                 m_fUsingAutoGeneratedDefaultStyle = false;
    02130                 return(true);
    02131         }
    02132
    02133         return(false);
    02134 }
    02135
    02136 bool CSimpleTextSubtitle::GetDefaultStyle(STSStyle& s)
    02137 {
    02138         void* val;
    02139         if(m_styles.Lookup(_T("Default"), val))
    02140         {
    02141                 s = *((STSStyle*)val);
    02142                 return(true);
    02143         }
    02144
    02145         return(false);
    02146 }
    02147
    02148 void CSimpleTextSubtitle::ConvertToTimeBased(double fps)
    02149 {
    02150         if(m_mode == TIME) return;
    02151
    02152         for(int i = 0, j = GetSize(); i < j; i++)
    02153         {
    02154                 STSEntry& stse = (*this)[i];
    02155                 stse.start = int(1.0 * stse.start * 1000 / fps + 0.5);
    02156                 stse.end = int(1.0 * stse.end * 1000 / fps + 0.5);
    02157         }
    02158
    02159         m_mode = TIME;
    02160
    02161         CreateSegments();
    02162 }
    02163
    02164 void CSimpleTextSubtitle::ConvertToFrameBased(double fps)
    02165 {
    02166         if(m_mode == FRAME) return;
    02167
    02168         for(int i = 0, j = GetSize(); i < j; i++)
    02169         {
    02170                 STSEntry& stse = (*this)[i];
    02171                 stse.start = int(1.0 * stse.start * fps / 1000 + 0.5);
    02172                 stse.end = int(1.0 * stse.end * fps / 1000 + 0.5);
    02173         }
    02174
    02175         m_mode = FRAME;
    02176
    02177         CreateSegments();
    02178 }
    02179
    02180 int CSimpleTextSubtitle::SearchSub(int t, double fps)
    02181 {
    02182         int i = 0, j = GetSize() - 1, ret = -1;
    02183
    02184         if(j >= 0 && t >= TranslateStart(j, fps))
    02185         {
    02186                 return(j);
    02187         }
    02188
    02189         while(i < j)
    02190         {
    02191                 int mid = (i + j) >> 1;
    02192
    02193                 int midt = TranslateStart(mid, fps);
    02194
    02195                 if(t == midt)
    02196                 {
    02197                         while(mid > 0 && t == TranslateStart(mid-1, fps)) mid--;
    02198                         ret = mid;
    02199                         break;
    02200                 }
    02201                 else if(t < midt)
    02202                 {
    02203                         ret = -1;
    02204                         if(j == mid) mid--;
    02205                         j = mid;
    02206                 }
    02207                 else if(t > midt)
    02208                 {
    02209                         ret = mid;
    02210                         if(i == mid) mid++;
    02211                         i = mid;
    02212                 }
    02213         }
    02214
    02215         return(ret);
    02216 }
    02217
    02218 const STSSegment* CSimpleTextSubtitle::SearchSubs(int t, double fps, /*[out]*/ int* iSegment, int* nSegments)
    02219 {
    02220         int i = 0, j = m_segments.GetSize() - 1, ret = -1;
    02221
    02222         if(nSegments) *nSegments = j+1;
    02223
    02224         if(j >= 0 && t >= TranslateSegmentStart(j, fps) && t < TranslateSegmentEnd(j, fps))
    02225         {
    02226                 if(iSegment) *iSegment = j;
    02227                 return(&m_segments[j]);
    02228         }
    02229
    02230         if(j >= 0 && t >= TranslateSegmentEnd(j, fps))
    02231         {
    02232                 if(iSegment) *iSegment = j+1;
    02233                 return(NULL);
    02234         }
    02235
    02236         if(j > 0 && t < TranslateSegmentStart(i, fps))
    02237         {
    02238                 if(iSegment) *iSegment = -1;
    02239                 return(NULL);
    02240         }
    02241
    02242         while(i < j)
    02243         {
    02244                 int mid = (i + j) >> 1;
    02245
    02246                 int midt = TranslateSegmentStart(mid, fps);
    02247
    02248                 if(t == midt)
    02249                 {
    02250                         ret = mid;
    02251                         break;
    02252                 }
    02253                 else if(t < midt)
    02254                 {
    02255                         ret = -1;
    02256                         if(j == mid) mid--;
    02257                         j = mid;
    02258                 }
    02259                 else if(t > midt)
    02260                 {
    02261                         ret = mid;
    02262                         if(i == mid) mid++;
    02263                         i = mid;
    02264                 }
    02265         }
    02266
    02267         if(0 <= ret && ret < m_segments.GetSize())
    02268         {
    02269                 if(iSegment) *iSegment = ret;
    02270         }
    02271
    02272         if(0 <= ret && ret < m_segments.GetSize()
    02273         && m_segments[ret].subs.GetSize() > 0
    02274         && TranslateSegmentStart(ret, fps) <= t && t < TranslateSegmentEnd(ret, fps))
    02275         {
    02276                 return(&m_segments[ret]);
    02277         }
    02278
    02279         return(NULL);
    02280 }
    02281
    02282 int CSimpleTextSubtitle::TranslateStart(int i, double fps)
    02283 {
    02284         return(i < 0 || GetSize() <= i ? -1 :
    02285                 m_mode == TIME ? GetAt(i).start :
    02286                 m_mode == FRAME ? (int)(GetAt(i).start*1000/fps) :
    02287                 0);
    02288 }
    02289
    02290 int CSimpleTextSubtitle::TranslateEnd(int i, double fps)
    02291 {
    02292         return(i < 0 || GetSize() <= i ? -1 :
    02293                 m_mode == TIME ? GetAt(i).end :
    02294                 m_mode == FRAME ? (int)(GetAt(i).end*1000/fps) :
    02295                 0);
    02296 }
    02297
    02298 int CSimpleTextSubtitle::TranslateSegmentStart(int i, double fps)
    02299 {
    02300         return(i < 0 || m_segments.GetSize() <= i ? -1 :
    02301                 m_mode == TIME ? m_segments[i].start :
    02302                 m_mode == FRAME ? (int)(m_segments[i].start*1000/fps) :
    02303                 0);
    02304 }
    02305
    02306 int CSimpleTextSubtitle::TranslateSegmentEnd(int i, double fps)
    02307 {
    02308         return(i < 0 || m_segments.GetSize() <= i ? -1 :
    02309                 m_mode == TIME ? m_segments[i].end :
    02310                 m_mode == FRAME ? (int)(m_segments[i].end*1000/fps) :
    02311                 0);
    02312 }
    02313
    02314 STSStyle* CSimpleTextSubtitle::GetStyle(int i)
    02315 {
    02316         STSStyle* style = (STSStyle*)m_styles[GetAt(i).style];
    02317         if(!style) style = (STSStyle*)m_styles[_T("Default")];
    02318         ASSERT(style);
    02319         return(style);
    02320 }
    02321
    02322 bool CSimpleTextSubtitle::GetStyle(int i, STSStyle& stss)
    02323 {
    02324         CString def = _T("Default");
    02325
    02326         STSStyle* style = (STSStyle*)m_styles[GetAt(i).style];
    02327         STSStyle* defstyle = (STSStyle*)m_styles[def];
    02328         if(!style) {if(defstyle) {ASSERT(0); CreateDefaultStyle(DEFAULT_CHARSET); defstyle = (STSStyle*)m_styles[def];} style = defstyle;}
    02329         if(!style) {ASSERT(0); return(false);}
    02330         stss = *style;
    02331         if(stss.relativeTo == 2 && defstyle)
    02332                 stss.relativeTo = defstyle->relativeTo;
    02333         return(true);
    02334 }
    02335
    02336 int CSimpleTextSubtitle::GetCharSet(int i)
    02337 {
    02338         STSStyle stss;
    02339         GetStyle(i, stss);
    02340         return(stss.charSet);
    02341 }
    02342
    02343 bool CSimpleTextSubtitle::IsEntryUnicode(int i)
    02344 {
    02345         return(GetAt(i).fUnicode);
    02346 }
    02347
    02348 void CSimpleTextSubtitle::ConvertUnicode(int i, bool fUnicode)
    02349 {
    02350         STSEntry& stse = GetAt(i);
    02351
    02352         if(stse.fUnicode ^ fUnicode)
    02353         {
    02354                 int CharSet = GetCharSet(i);
    02355
    02356                 stse.str = fUnicode
    02357                         ? MBCSSSAToUnicode(stse.str, CharSet)
    02358                         : UnicodeSSAToMBCS(stse.str, CharSet);
    02359
    02360                 stse.fUnicode = fUnicode;
    02361         }
    02362 }
    02363
    02364 CStringA CSimpleTextSubtitle::GetStrA(int i, bool fSSA)
    02365 {
    02366         return(WToA(GetStrWA(i, fSSA)));
    02367 }
    02368
    02369 CStringW CSimpleTextSubtitle::GetStrW(int i, bool fSSA)
    02370 {
    02371         bool fUnicode = IsEntryUnicode(i);
    02372         int CharSet = GetCharSet(i);
    02373
    02374         CStringW str = GetAt(i).str;
    02375
    02376         if(!fUnicode)
    02377                 str = MBCSSSAToUnicode(str, CharSet);
    02378
    02379         if(!fSSA)
    02380                 str = RemoveSSATags(str, fUnicode, CharSet);
    02381
    02382         return(str);
    02383 }
    02384
    02385 CStringW CSimpleTextSubtitle::GetStrWA(int i, bool fSSA)
    02386 {
    02387         bool fUnicode = IsEntryUnicode(i);
    02388         int CharSet = GetCharSet(i);
    02389
    02390         CStringW str = GetAt(i).str;
    02391
    02392         if(fUnicode)
    02393                 str = UnicodeSSAToMBCS(str, CharSet);
    02394
    02395         if(!fSSA)
    02396                 str = RemoveSSATags(str, fUnicode, CharSet);
    02397
    02398         return(str);
    02399 }
    02400
    02401 void CSimpleTextSubtitle::SetStr(int i, CStringA str, bool fUnicode)
    02402 {
    02403         SetStr(i, AToW(str), false);
    02404 }
    02405
    02406 void CSimpleTextSubtitle::SetStr(int i, CStringW str, bool fUnicode)
    02407 {
    02408         STSEntry& stse = GetAt(i);
    02409
    02410         str.Replace(L"\n", L"\\N");
    02411
    02412         if(stse.fUnicode && !fUnicode) stse.str = MBCSSSAToUnicode(str, GetCharSet(i));
    02413         else if(!stse.fUnicode && fUnicode) stse.str = UnicodeSSAToMBCS(str, GetCharSet(i));
    02414         else stse.str = str;
    02415 }
    02416
    02417 static int comp1(const void* a, const void* b)
    02418 {
    02419         int ret = ((STSEntry*)a)->start - ((STSEntry*)b)->start;
    02420         if(ret == 0) ret = ((STSEntry*)a)->layer - ((STSEntry*)b)->layer;
    02421         if(ret == 0) ret = ((STSEntry*)a)->readorder - ((STSEntry*)b)->readorder;
    02422         return(ret);
    02423 }
    02424
    02425 static int comp2(const void* a, const void* b)
    02426 {
    02427         return(((STSEntry*)a)->readorder - ((STSEntry*)b)->readorder);
    02428 }
    02429
    02430 void CSimpleTextSubtitle::Sort(bool fRestoreReadorder)
    02431 {
    02432         qsort(GetData(), GetSize(), sizeof(STSEntry), !fRestoreReadorder ? comp1 : comp2);
    02433         CreateSegments();
    02434 }
    02435
    02436 static int intcomp(const void* i1, const void* i2)
    02437 {
    02438         return(*((int*)i1) - *((int*)i2));
    02439 }
    02440
    02441 void CSimpleTextSubtitle::CreateSegments()
    02442 {
    02443         m_segments.RemoveAll();
    02444
    02445         int i, j;
    02446
    02447         CArray<int> breakpoints;
    02448
    02449         for(i = 0; i < GetSize(); i++)
    02450         {
    02451                 STSEntry& stse = GetAt(i);
    02452                 breakpoints.Add(stse.start);
    02453                 breakpoints.Add(stse.end);
    02454         }
    02455
    02456         qsort(breakpoints.GetData(), breakpoints.GetSize(), sizeof(int), intcomp);
    02457
    02458         int* ptr = breakpoints.GetData(), prev = ptr ? *ptr : NULL;
    02459
    02460         for(i = breakpoints.GetSize(); i > 0; i--, ptr++)
    02461         {
    02462                 if(*ptr != prev)
    02463                 {
    02464                         m_segments.Add(STSSegment(prev, *ptr));
    02465                         prev = *ptr;
    02466                 }
    02467         }
    02468
    02469         for(i = 0; i < GetSize(); i++)
    02470         {
    02471                 STSEntry& stse = GetAt(i);
    02472                 for(j = 0; j < m_segments.GetSize() && m_segments[j].start < stse.start; j++);
    02473                 for(; j < m_segments.GetSize() && m_segments[j].end <= stse.end; j++)
    02474                         m_segments[j].subs.Add(i);
    02475         }
    02476
    02477         OnChanged();
    02478 /*
    02479         for(i = 0, j = m_segments.GetSize(); i < j; i++)
    02480         {
    02481                 STSSegment& stss = m_segments[i];
    02482
    02483                 TRACE(_T("%d - %d"), stss.start, stss.end);
    02484
    02485                 for(int k = 0, l = stss.subs.GetSize(); k < l; k++)
    02486                 {
    02487                         TRACE(_T(", %d"), stss.subs[k]);
    02488                 }
    02489
    02490                 TRACE(_T("\n"));
    02491         }
    02492 */
    02493 }
    02494
    02495 bool CSimpleTextSubtitle::Open(CString fn, int CharSet, CString name)
    02496 {
    02497         Empty();
    02498
    02499         CWebTextFile f;
    02500         if(!f.Open(fn)) return(false);
    02501
    02502         fn.Replace('\\', '/');
    02503         if(name.IsEmpty())
    02504         {
    02505                 name = fn.Left(fn.ReverseFind('.'));
    02506                 name = name.Mid(name.ReverseFind('/')+1);
    02507                 name = name.Mid(name.ReverseFind('.')+1);
    02508         }
    02509
    02510         return(Open(&f, CharSet, name));
    02511 }
    02512
    02513 static int CountLines(CTextFile* f, ULONGLONG from, ULONGLONG to)
    02514 {
    02515         int n = 0;
    02516         CString s;
    02517         f->Seek(from, 0);
    02518         while(f->ReadString(s) && f->GetPosition() < to) n++;
    02519         return(n);
    02520 }
    02521
    02522 bool CSimpleTextSubtitle::Open(CTextFile* f, int CharSet, CString name)
    02523 {
    02524         Empty();
    02525
    02526         ULONGLONG pos = f->GetPosition();
    02527
    02528         for(int i = 0; i < nOpenFuncts; i++)
    02529         {
    02530                 if(!OpenFuncts[i].open(f, *this, CharSet) /*|| !GetSize()*/)
    02531                 {
    02532                         if(GetSize() > 0)
    02533                         {
    02534                                 int n = CountLines(f, pos, f->GetPosition());
    02535                                 CString s;
    02536                                 s.Format(_T("Syntax error at line %d!\t"), n+1);
    02537                                 AfxMessageBox(s, MB_OK|MB_ICONERROR);
    02538                                 Empty();
    02539                                 break;
    02540                         }
    02541
    02542                         f->Seek(pos, 0);
    02543                         Empty();
    02544                         continue;
    02545                 }
    02546
    02547                 m_name = name;
    02548                 m_mode = OpenFuncts[i].mode;
    02549                 m_encoding = f->GetEncoding();
    02550                 m_path = f->GetFilePath();
    02551
    02552 //              Sort();
    02553                 CreateSegments();
    02554
    02555                 CWebTextFile f2;
    02556                 if(f2.Open(f->GetFilePath() + _T(".style")))
    02557                         OpenSubStationAlpha(&f2, *this, CharSet);
    02558
    02559                 CreateDefaultStyle(CharSet);
    02560
    02561                 ChangeUnknownStylesToDefault();
    02562
    02563                 if(m_dstScreenSize == CSize(0, 0)) m_dstScreenSize = CSize(384, 288);
    02564
    02565                 return(true);
    02566         }
    02567
    02568         return(false);
    02569 }
    02570
    02571 bool CSimpleTextSubtitle::Open(BYTE* data, int len, int CharSet, CString name)
    02572 {
    02573         TCHAR path[MAX_PATH];
    02574         if(!GetTempPath(MAX_PATH, path)) return(false);
    02575
    02576         TCHAR fn[MAX_PATH];
    02577         if(!GetTempFileName(path, _T("vs"), 0, fn)) return(false);
    02578
    02579         FILE* tmp = _tfopen(fn, _T("wb"));
    02580         if(!tmp) return(false);
    02581
    02582         int i = 0;
    02583         for(; i <= (len-1024); i += 1024) fwrite(&data[i], 1024, 1, tmp);
    02584         if(len > i) fwrite(&data[i], len - i, 1, tmp);
    02585
    02586         fclose(tmp);
    02587
    02588         bool fRet = Open(fn, CharSet, name);
    02589
    02590         _tremove(fn);
    02591
    02592         return(fRet);
    02593 }
    02594
    02595 bool CSimpleTextSubtitle::SaveAs(CString fn, exttype et, double fps, CTextFile::enc e)
    02596 {
    02597         if(fn.Mid(fn.ReverseFind('.')+1).CompareNoCase(exttypestr[et]))
    02598         {
    02599                 if(fn[fn.GetLength()-1] != '.') fn += _T(".");
    02600                 fn += exttypestr[et];
    02601         }
    02602
    02603         CTextFile f;
    02604         if(!f.Save(fn, e))
    02605                 return(false);
    02606
    02607         if(et == EXTSMI)
    02608         {
    02609                 CString str;
    02610
    02611                 str += _T("<SAMI>\n<HEAD>\n");
    02612                 str += _T("<STYLE TYPE=\"text/css\">\n");
    02613                 str += _T("<!--\n");
    02614                 str += _T("P {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;\n");
    02615                 str += _T("   text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}\n");
    02616                 str += _T(".UNKNOWNCC {Name:Unknown; lang:en-US; SAMIType:CC;}\n");
    02617                 str += _T("-->\n");
    02618                 str += _T("</STYLE>\n");
    02619                 str += _T("</HEAD>\n");
    02620                 str += _T("\n");
    02621                 str += _T("<BODY>\n");
    02622
    02623                 f.WriteString(str);
    02624         }
    02625         else if(et == EXTSSA || et == EXTASS)
    02626         {
    02627                 CString str;
    02628
    02629                 str  = _T("[Script Info]\n");
    02630                 str += (et == EXTSSA) ? _T("; This is a Sub Station Alpha v4 script.\n") : _T("; This is an Advanced Sub Station Alpha v4+ script.\n");
    02631                 str += _T("; For Sub Station Alpha info and downloads,\n");
    02632                 str += _T("; go to http://www.eswat.demon.co.uk/\n");
    02633                 str += _T("; or email kotus@eswat.demon.co.uk\n");
    02634                 str += _T("; \n");
    02635                 if(et == EXTASS)
    02636                 {
    02637                         str += _T("; Advanced Sub Station Alpha script format developed by #Anime-Fansubs@EfNET\n");
    02638                         str += _T("; http://www.anime-fansubs.org\n");
    02639                         str += _T("; \n");
    02640                         str += _T("; For additional info and downloads go to http://gabest.org/\n");
    02641                         str += _T("; or email gabest@freemail.hu\n");
    02642                         str += _T("; \n");
    02643                 }
    02644                 str += _T("; Note: This file was saved by Subresync.\n");
    02645                 str += _T("; \n");
    02646                 str += (et == EXTSSA) ? _T("ScriptType: v4.00\n") : _T("ScriptType: v4.00+\n");
    02647                 str += (m_collisions == 0) ? _T("Collisions: Normal\n") : _T("Collisions: Reverse\n");
    02648                 if(et == EXTASS && m_fScaledBAS) str += _T("ScaledBorderAndShadow: Yes\n");
    02649                 str += _T("PlayResX: %d\n");
    02650                 str += _T("PlayResY: %d\n");
    02651                 str += _T("Timer: 100.0000\n");
    02652                 str += _T("\n");
    02653                 str += (et == EXTSSA)
    02654                         ? _T("[V4 Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\n")
    02655                         : _T("[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n");
    02656
    02657                 CString str2;
    02658                 str2.Format(str, m_dstScreenSize.cx, m_dstScreenSize.cy);
    02659                 f.WriteString(str2);
    02660
    02661                 str  = (et == EXTSSA)
    02662                         ? _T("Style: %s,%s,%d,&H%06x,&H%06x,&H%06x,&H%06x,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n")
    02663                         : _T("Style: %s,%s,%d,&H%08x,&H%08x,&H%08x,&H%08x,%d,%d,%d,%d,%d,%d,%d,%.2f,%d,%d,%d,%d,%d,%d,%d,%d\n");
    02664
    02665                 POSITION pos = m_styles.GetStartPosition();
    02666                 while(pos)
    02667                 {
    02668                         CString key;
    02669                         void* ptr;
    02670                         m_styles.GetNextAssoc(pos, key, ptr);
    02671                         STSStyle* s = (STSStyle*)ptr;
    02672
    02673                         if(et == EXTSSA)
    02674                         {
    02675                                 CString str2;
    02676                                 str2.Format(str, key,
    02677                                         s->fontName, (int)s->fontSize,
    02678                                         s->colors[0]&0xffffff,
    02679                                         s->colors[1]&0xffffff,
    02680                                         s->colors[2]&0xffffff,
    02681                                         s->colors[3]&0xffffff,
    02682                                         s->fontWeight > FW_NORMAL ? -1 : 0, s->fItalic ? -1 : 0,
    02683                                         s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
    02684                                         (int)s->outlineWidth, (int)s->shadowDepth,
    02685                                         s->scrAlignment <= 3 ? s->scrAlignment : s->scrAlignment <= 6 ? ((s->scrAlignment-3)|8) : s->scrAlignment <= 9 ? ((s->scrAlignment-6)|4) : 2,
    02686                                         s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
    02687                                         s->alpha[0],
    02688                                         s->charSet);
    02689                                 f.WriteString(str2);
    02690                         }
    02691                         else
    02692                         {
    02693                                 CString str2;
    02694                                 str2.Format(str, key,
    02695                                         s->fontName, (int)s->fontSize,
    02696                                         (s->colors[0]&0xffffff) | (s->alpha[0]<<24),
    02697                                         (s->colors[1]&0xffffff) | (s->alpha[1]<<24),
    02698                                         (s->colors[2]&0xffffff) | (s->alpha[2]<<24),
    02699                                         (s->colors[3]&0xffffff) | (s->alpha[3]<<24),
    02700                                         s->fontWeight > FW_NORMAL ? -1 : 0,
    02701                                         s->fItalic ? -1 : 0, s->fUnderline ? -1 : 0, s->fStrikeOut ? -1 : 0,
    02702                                         (int)s->fontScaleX, (int)s->fontScaleY,
    02703                                         (int)s->fontSpacing, (float)s->fontAngleZ,
    02704                                         s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
    02705                                         (int)s->outlineWidth, (int)s->shadowDepth,
    02706                                         s->scrAlignment,
    02707                                         s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
    02708                                         s->charSet);
    02709                                 f.WriteString(str2);
    02710                         }
    02711                 }
    02712
    02713                 if(GetSize() > 0)
    02714                 {
    02715                         str  = _T("\n");
    02716                         str += _T("[Events]\n");
    02717                         str += (et == EXTSSA)
    02718                                 ? _T("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n")
    02719                                 : _T("Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text\n");
    02720                         f.WriteString(str);
    02721                 }
    02722         }
    02723
    02724         CStringW fmt =
    02725                 et == EXTSRT ? L"%d\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\n%s\n\n" :
    02726                 et == EXTSUB ? L"{%d}{%d}%s\n" :
    02727                 et == EXTSMI ? L"<SYNC Start=%d><P Class=UNKNOWNCC>\n%s\n<SYNC Start=%d><P Class=UNKNOWNCC>&nbsp;\n" :
    02728                 et == EXTPSB ? L"{%d:%02d:%02d}{%d:%02d:%02d}%s\n" :
    02729                 et == EXTSSA ? L"Dialogue: Marked=0,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s,%s,%04d,%04d,%04d,%s,%s\n" :
    02730                 et == EXTASS ? L"Dialogue: %d,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s,%s,%04d,%04d,%04d,%s,%s\n" :
    02731                                            L"";
    02732 //      Sort(true);
    02733
    02734         for(int i = 0, j = GetSize(), k = 0; i < j; i++)
    02735         {
    02736                 STSEntry& stse = GetAt(i);
    02737
    02738                 int t1 = TranslateStart(i, fps);
    02739                 if(t1 < 0) {k++; continue;}
    02740
    02741                 int t2 = TranslateEnd(i, fps);
    02742
    02743                 int hh1 = (t1/60/60/1000);
    02744                 int mm1 = (t1/60/1000)%60;
    02745                 int ss1 = (t1/1000)%60;
    02746                 int ms1 = (t1)%1000;
    02747                 int hh2 = (t2/60/60/1000);
    02748                 int mm2 = (t2/60/1000)%60;
    02749                 int ss2 = (t2/1000)%60;
    02750                 int ms2 = (t2)%1000;
    02751
    02752                 CStringW str = f.IsUnicode()
    02753                         ? GetStrW(i, et == EXTSSA || et == EXTASS)
    02754                         : GetStrWA(i, et == EXTSSA || et == EXTASS);
    02755
    02756                 CStringW str2;
    02757
    02758                 if(et == EXTSRT)
    02759                 {
    02760                         str2.Format(fmt, i-k+1, hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, str);
    02761                 }
    02762                 else if(et == EXTSUB)
    02763                 {
    02764                         str.Replace('\n', '|');
    02765                         str2.Format(fmt, int(t1*fps/1000), int(t2*fps/1000), str);
    02766                 }
    02767                 else if(et == EXTSMI)
    02768                 {
    02769                         str.Replace(L"\n", L"<br>");
    02770                         str2.Format(fmt, t1, str, t2);
    02771                 }
    02772                 else if(et == EXTPSB)
    02773                 {
    02774                         str.Replace('\n', '|');
    02775                         str2.Format(fmt, hh1, mm1, ss1, hh2, mm2, ss2, str);
    02776                 }
    02777                 else if(et == EXTSSA)
    02778                 {
    02779                         str.Replace(L"\n", L"\\N");
    02780                         str2.Format(fmt,
    02781                                 hh1, mm1, ss1, ms1/10,
    02782                                 hh2, mm2, ss2, ms2/10,
    02783                                 TToW(stse.style), TToW(stse.actor),
    02784                                 stse.marginRect.left, stse.marginRect.right, (stse.marginRect.top + stse.marginRect.bottom) / 2,
    02785                                 TToW(stse.effect), str);
    02786                 }
    02787                 else if(et == EXTASS)
    02788                 {
    02789                         str.Replace(L"\n", L"\\N");
    02790                         str2.Format(fmt,
    02791                                 stse.layer,
    02792                                 hh1, mm1, ss1, ms1/10,
    02793                                 hh2, mm2, ss2, ms2/10,
    02794                                 TToW(stse.style), TToW(stse.actor),
    02795                                 stse.marginRect.left, stse.marginRect.right, (stse.marginRect.top + stse.marginRect.bottom) / 2,
    02796                                 TToW(stse.effect), str);
    02797                 }
    02798
    02799                 f.WriteString(str2);
    02800         }
    02801
    02802 //      Sort();
    02803
    02804         if(et == EXTSMI)
    02805         {
    02806                 f.WriteString(_T("</BODY>\n</SAMI>\n"));
    02807         }
    02808
    02809         void* val;
    02810         if(!m_fUsingAutoGeneratedDefaultStyle && m_styles.Lookup(_T("Default"), val) && et != EXTSSA && et != EXTASS)
    02811         {
    02812                 STSStyle* s = (STSStyle*)val;
    02813
    02814                 CTextFile f;
    02815                 if(!f.Save(fn + _T(".style"), e))
    02816                         return(false);
    02817
    02818                 CString str, str2;
    02819
    02820                 str += _T("ScriptType: v4.00+\n");
    02821                 str += _T("PlayResX: %d\n");
    02822                 str += _T("PlayResY: %d\n");
    02823                 str += _T("\n");
    02824                 str += _T("[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n");
    02825                 str2.Format(str, m_dstScreenSize.cx, m_dstScreenSize.cy);
    02826                 f.WriteString(str2);
    02827
    02828                 str  = _T("Style: Default,%s,%d,&H%08x,&H%08x,&H%08x,&H%08x,%d,%d,%d,%d,%d,%d,%d,%.2f,%d,%d,%d,%d,%d,%d,%d,%d\n");
    02829                 str2.Format(str,
    02830                         s->fontName, (int)s->fontSize,
    02831                         (s->colors[0]&0xffffff) | (s->alpha[0]<<24),
    02832                         (s->colors[1]&0xffffff) | (s->alpha[1]<<24),
    02833                         (s->colors[2]&0xffffff) | (s->alpha[2]<<24),
    02834                         (s->colors[3]&0xffffff) | (s->alpha[3]<<24),
    02835                         s->fontWeight > FW_NORMAL ? -1 : 0,
    02836                         s->fItalic ? -1 : 0, s->fUnderline ? -1 : 0, s->fStrikeOut ? -1 : 0,
    02837                         (int)s->fontScaleX, (int)s->fontScaleY,
    02838                         (int)s->fontSpacing, (float)s->fontAngleZ,
    02839                         s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
    02840                         (int)s->outlineWidth, (int)s->shadowDepth,
    02841                         s->scrAlignment,
    02842                         s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
    02843                         s->charSet);
    02844                 f.WriteString(str2);
    02845         }
    02846
    02847         return(true);
    02848 }
    02849
    02851
    02852 STSStyle::STSStyle()
    02853 {
    02854         SetDefault();
    02855 }
    02856
    02857 void STSStyle::SetDefault()
    02858 {
    02859         marginRect = CRect(20, 20, 20, 20);
    02860         scrAlignment = 2;
    02861         borderStyle = 0;
    02862         outlineWidth = 2;
    02863         shadowDepth = 3;
    02864         colors[0] = 0x00ffffff;
    02865         colors[1] = 0x0000ffff;
    02866         colors[2] = 0x00000000;
    02867         colors[3] = 0x00000000;
    02868         alpha[0] = 0x00;
    02869         alpha[1] = 0x00;
    02870         alpha[2] = 0x00;
    02871         alpha[3] = 0x80;
    02872     charSet = DEFAULT_CHARSET;
    02873         fontName = _T("Arial");
    02874         fontSize = 18;
    02875         fontScaleX = fontScaleY = 100;
    02876         fontSpacing = 0;
    02877         fontWeight = FW_BOLD;
    02878         fItalic = false;
    02879         fUnderline = false;
    02880         fStrikeOut = false;
    02881         fBlur = false;
    02882         fontAngleZ = fontAngleX = fontAngleY = 0;
    02883         relativeTo = 2;
    02884 }
    02885
    02886 bool STSStyle::operator == (STSStyle& s)
    02887 {
    02888         return(marginRect == s.marginRect
    02889                 && scrAlignment == s.scrAlignment
    02890                 && borderStyle == s.borderStyle
    02891                 && outlineWidth == s.outlineWidth
    02892                 && shadowDepth == s.shadowDepth
    02893                 && *((int*)&colors[0]) == *((int*)&s.colors[0])
    02894                 && *((int*)&colors[1]) == *((int*)&s.colors[1])
    02895                 && *((int*)&colors[2]) == *((int*)&s.colors[2])
    02896                 && *((int*)&colors[3]) == *((int*)&s.colors[3])
    02897                 && alpha[0] == s.alpha[0]
    02898                 && alpha[1] == s.alpha[1]
    02899                 && alpha[2] == s.alpha[2]
    02900                 && alpha[3] == s.alpha[3]
    02901                 && fBlur == s.fBlur
    02902                 && relativeTo == s.relativeTo
    02903                 && IsFontStyleEqual(s));
    02904 }
    02905
    02906 bool STSStyle::IsFontStyleEqual(STSStyle& s)
    02907 {
    02908         return(
    02909                 charSet == s.charSet
    02910                 && fontName == s.fontName
    02911                 && fontSize == s.fontSize
    02912                 && fontScaleX == s.fontScaleX
    02913                 && fontScaleY == s.fontScaleY
    02914                 && fontSpacing == s.fontSpacing
    02915                 && fontWeight == s.fontWeight
    02916                 && fItalic == s.fItalic
    02917                 && fUnderline == s.fUnderline
    02918                 && fStrikeOut == s.fStrikeOut
    02919                 && fontAngleZ == s.fontAngleZ
    02920                 && fontAngleX == s.fontAngleX
    02921                 && fontAngleY == s.fontAngleY);
    02922 }
    02923
    02924 void STSStyle::operator = (LOGFONT& lf)
    02925 {
    02926         charSet = lf.lfCharSet;
    02927         fontName = lf.lfFaceName;
    02928         HDC hDC = GetDC(0);
    02929         fontSize = -MulDiv(lf.lfHeight, 72, GetDeviceCaps(hDC, LOGPIXELSY));
    02930         ReleaseDC(0, hDC);
    02931 //      fontAngleZ = (float)(1.0*lf.lfEscapement/10);
    02932         fontWeight = lf.lfWeight;
    02933         fItalic = !!lf.lfItalic;
    02934         fUnderline = !!lf.lfUnderline;
    02935         fStrikeOut = !!lf.lfStrikeOut;
    02936 }
    02937
    02938 LOGFONTA& operator <<= (LOGFONTA& lfa, STSStyle& s)
    02939 {
    02940         lfa.lfCharSet = s.charSet;
    02941 #ifdef UNICODE
    02942         wcstombs(lfa.lfFaceName, s.fontName, 32);
    02943 #else
    02944         strncpy(lfa.lfFaceName, s.fontName, 32);
    02945 #endif
    02946         HDC hDC = GetDC(0);
    02947         lfa.lfHeight = -MulDiv((int)(s.fontSize+0.5), GetDeviceCaps(hDC, LOGPIXELSY), 72);
    02948         ReleaseDC(0, hDC);
    02949         lfa.lfWeight = s.fontWeight;
    02950         lfa.lfItalic = s.fItalic?-1:0;
    02951         lfa.lfUnderline = s.fUnderline?-1:0;
    02952         lfa.lfStrikeOut = s.fStrikeOut?-1:0;
    02953
    02954         return(lfa);
    02955 }
    02956
    02957 LOGFONTW& operator <<= (LOGFONTW& lfw, STSStyle& s)
    02958 {
    02959         lfw.lfCharSet = s.charSet;
    02960 #ifdef UNICODE
    02961         wcsncpy(lfw.lfFaceName, s.fontName, 32);
    02962 #else
    02963         mbstowcs(lfw.lfFaceName, s.fontName, 32);
    02964 #endif
    02965         HDC hDC = GetDC(0);
    02966         lfw.lfHeight = -MulDiv((int)(s.fontSize+0.5), GetDeviceCaps(hDC, LOGPIXELSY), 72);
    02967         ReleaseDC(0, hDC);
    02968         lfw.lfWeight = s.fontWeight;
    02969         lfw.lfItalic = s.fItalic?-1:0;
    02970         lfw.lfUnderline = s.fUnderline?-1:0;
    02971         lfw.lfStrikeOut = s.fStrikeOut?-1:0;
    02972
    02973         return(lfw);
    02974 }
    02975
    02976 CString& operator <<= (CString& style, STSStyle& s)
    02977 {
    02978         style.Format(_T("%d,%d,%d,%d,%d,%d,%f,%f,0x%06x,0x%06x,0x%06x,0x%06x,0x%02x,0x%02x,0x%02x,0x%02x,%d,%s,%f,%f,%f,%f,%d,%d,%d,%d,%d,%f,%f,%f,%d"),
    02979                 s.marginRect.left,s.marginRect.right,s.marginRect.top,s.marginRect.bottom,
    02980                 s.scrAlignment, s.borderStyle, s.outlineWidth, s.shadowDepth,
    02981                 s.colors[0], s.colors[1], s.colors[2], s.colors[3], s.alpha[0], s.alpha[1], s.alpha[2], s.alpha[3],
    02982                 s.charSet,
    02983                 s.fontName, s.fontSize, s.fontScaleX, s.fontScaleY, s.fontSpacing, s.fontWeight,
    02984                 (int)s.fItalic, (int)s.fUnderline, (int)s.fStrikeOut, (int)s.fBlur,
    02985                 s.fontAngleZ, s.fontAngleX, s.fontAngleY,
    02986                 s.relativeTo);
    02987
    02988         return(style);
    02989 }
    02990
    02991 STSStyle& operator <<= (STSStyle& s, CString& style)
    02992 {
    02993         s.SetDefault();
    02994
    02995         try
    02996         {
    02997                 CStringW str = TToW(style);
    02998                 s.marginRect.left = GetInt(str); s.marginRect.right = GetInt(str); s.marginRect.top = GetInt(str); s.marginRect.bottom = GetInt(str);
    02999                 s.scrAlignment = GetInt(str); s.borderStyle = GetInt(str); s.outlineWidth = GetFloat(str); s.shadowDepth = GetFloat(str);
    03000                 for(int i = 0; i < 4; i++) s.colors[i] = (COLORREF)GetInt(str);
    03001                 for(int i = 0; i < 4; i++) s.alpha[i] = GetInt(str);
    03002                 s.charSet = GetInt(str);
    03003                 s.fontName = WToT(GetStr(str)); s.fontSize = GetFloat(str);
    03004                 s.fontScaleX = GetFloat(str); s.fontScaleY = GetFloat(str);
    03005                 s.fontSpacing = GetFloat(str); s.fontWeight = GetInt(str);
    03006                 s.fItalic = !!GetInt(str); s.fUnderline = !!GetInt(str); s.fStrikeOut = !!GetInt(str); s.fBlur = !!GetInt(str);
    03007                 s.fontAngleZ = GetFloat(str); s.fontAngleX = GetFloat(str); s.fontAngleY = GetFloat(str);
    03008                 s.relativeTo = GetInt(str);
    03009         }
    03010         catch(...)
    03011         {
    03012                 s.SetDefault();
    03013         }
    03014
    03015         return(s);
    03016 }
    03017