| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include "ScpCommander.h"#include "ScpExplorer.h"#include <CoreMain.h>#include <Common.h>#include <Exceptions.h>#include <Cryptography.h>#include "ProgParams.h"#include "VCLCommon.h"#include "WinConfiguration.h"#include "TerminalManager.h"#include "TextsWin.h"#include "TBXThemes.hpp"#include "TBXOfficeXPTheme.hpp"#include "TBXOffice2003Theme.hpp"#include "PasswordEdit.hpp"#include "ProgParams.h"#include "Tools.h"#include "Custom.h"#include "HelpWin.h"#include <Math.hpp>#include <PasTools.hpp>#include <GUITools.h>//---------------------------------------------------------------------------#pragma package(smart_init)//---------------------------------------------------------------------------const UnicodeString AppName = L"WinSCP";//---------------------------------------------------------------------------TConfiguration * __fastcall CreateConfiguration(){  WinConfiguration = new TWinConfiguration();  CustomWinConfiguration = WinConfiguration;  GUIConfiguration = CustomWinConfiguration;  TProgramParams * Params = TProgramParams::Instance();  UnicodeString IniFileName = Params->SwitchValue(L"ini");  if (!IniFileName.IsEmpty())  {    if (AnsiSameText(IniFileName, L"nul"))    {      WinConfiguration->SetNulStorage();    }    else if (CheckSafe(Params))    {      IniFileName = ExpandFileName(ExpandEnvironmentVariables(IniFileName));      WinConfiguration->IniFileStorageName = IniFileName;    }  }  if (CheckSafe(Params))  {    std::unique_ptr<TStrings> RawConfig(new TStringList());    if (Params->FindSwitch(L"rawconfig", RawConfig.get()))    {      WinConfiguration->OptionsStorage = RawConfig.get();    }  }  return WinConfiguration;}//---------------------------------------------------------------------------TOptions * __fastcall GetGlobalOptions(){  return TProgramParams::Instance();}//---------------------------------------------------------------------------TCustomScpExplorerForm * __fastcall CreateScpExplorer(){  TCustomScpExplorerForm * ScpExplorer;  if (WinConfiguration->Interface == ifExplorer)  {    ScpExplorer = SafeFormCreate<TScpExplorerForm>();  }  else  {    ScpExplorer = SafeFormCreate<TScpCommanderForm>();  }  return ScpExplorer;}//---------------------------------------------------------------------------UnicodeString __fastcall SshVersionString(){  return FORMAT(L"WinSCP-release-%s", (Configuration->Version));}//---------------------------------------------------------------------------UnicodeString __fastcall AppNameString(){  return L"WinSCP";}//---------------------------------------------------------------------------UnicodeString __fastcall GetCompanyRegistryKey(){  return L"Software\\Martin Prikryl";}//---------------------------------------------------------------------------UnicodeString __fastcall GetRegistryKey(){  return GetCompanyRegistryKey() + L"\\WinSCP 2";}//---------------------------------------------------------------------------static bool ForcedOnForeground = false;void __fastcall SetOnForeground(bool OnForeground){  ForcedOnForeground = OnForeground;}//---------------------------------------------------------------------------void __fastcall FlashOnBackground(){  assert(Application);  if (!ForcedOnForeground && !ForegroundTask())  {    FlashWindow(Application->MainFormHandle, true);  }}//---------------------------------------------------------------------------void __fastcall LocalSystemSettings(TCustomForm * /*Control*/){  // noop}//---------------------------------------------------------------------------void __fastcall ShowExtendedException(Exception * E){  ShowExtendedExceptionEx(NULL, E);}//---------------------------------------------------------------------------void __fastcall ShowExtendedExceptionEx(TTerminal * Terminal,  Exception * E){  bool Show = ShouldDisplayException(E);  bool DoNotDisplay = false;  try  {    // This is special case used particularly when called from .NET assembly    // (which always uses /nointeractiveinput),    // but can be useful for other console runs too    TProgramParams * Params = TProgramParams::Instance();    if (Params->FindSwitch(L"nointeractiveinput"))    {      DoNotDisplay = true;      if (Show && CheckXmlLogParam(Params))      {        std::unique_ptr<TActionLog> ActionLog(new TActionLog(Configuration));        ActionLog->AddFailure(E);        // unnecessary explicit release        ActionLog.reset(NULL);      }    }  }  catch (Exception & E)  {    // swallow  }  if (!DoNotDisplay)  {    TTerminalManager * Manager = TTerminalManager::Instance(false);    TQueryType Type;    ESshTerminate * Terminate = dynamic_cast<ESshTerminate*>(E);    bool CloseOnCompletion = (Terminate != NULL);    Type = CloseOnCompletion ? qtInformation : qtError;    bool ConfirmExitOnCompletion =      CloseOnCompletion &&      ((Terminate->Operation == odoDisconnect) || (Terminate->Operation == odoSuspend)) &&      WinConfiguration->ConfirmExitOnCompletion;    if (E->InheritsFrom(__classid(EFatal)) && (Terminal != NULL) &&        (Manager != NULL) && (Manager->ActiveTerminal == Terminal))    {      int SessionReopenTimeout = 0;      TManagedTerminal * ManagedTerminal = dynamic_cast<TManagedTerminal *>(Terminal);      if ((ManagedTerminal != NULL) &&          ((Configuration->SessionReopenTimeout == 0) ||           ((double)ManagedTerminal->ReopenStart == 0) ||           (int(double(Now() - ManagedTerminal->ReopenStart) * MSecsPerDay) < Configuration->SessionReopenTimeout)))      {        SessionReopenTimeout = GUIConfiguration->SessionReopenAutoIdle;      }      unsigned int Result;      if (CloseOnCompletion)      {        Manager->DisconnectActiveTerminal();        if (Terminate->Operation == odoSuspend)        {          // suspend, so that exit prompt is shown only after windows resume          SuspendWindows();        }        assert(Show);        if (ConfirmExitOnCompletion)        {          TMessageParams Params(mpNeverAskAgainCheck);          UnicodeString MessageFormat =            MainInstructions((Manager->Count > 1) ?              FMTLOAD(DISCONNECT_ON_COMPLETION, (Manager->Count - 1)) :              LoadStr(EXIT_ON_COMPLETION));          Result = FatalExceptionMessageDialog(E, Type, 0,            MessageFormat,            qaYes | qaNo, HELP_NONE, &Params);          if (Result == qaNeverAskAgain)          {            Result = qaYes;            WinConfiguration->ConfirmExitOnCompletion = false;          }        }        else        {          Result = qaYes;        }      }      else      {        if (Show)        {          Result = FatalExceptionMessageDialog(E, Type, SessionReopenTimeout);        }        else        {          Result = qaOK;        }      }      if (Result == qaYes)      {        assert(CloseOnCompletion);        assert(Terminate != NULL);        assert(Terminate->Operation != odoIdle);        Application->Terminate();        switch (Terminate->Operation)        {          case odoDisconnect:            break;          case odoSuspend:            // suspended before already            break;          case odoShutDown:            ShutDownWindows();            break;          default:            FAIL;        }      }      else if (Result == qaRetry)      {        Manager->ReconnectActiveTerminal();      }      else      {        Manager->FreeActiveTerminal();      }    }    else    {      // this should not happen as we never use Terminal->CloseOnCompletion      // on inactive terminal      if (CloseOnCompletion)      {        assert(Show);        if (ConfirmExitOnCompletion)        {          TMessageParams Params(mpNeverAskAgainCheck);          if (ExceptionMessageDialog(E, Type, L"", qaOK, HELP_NONE, &Params) ==                qaNeverAskAgain)          {            WinConfiguration->ConfirmExitOnCompletion = false;          }        }      }      else      {        if (Show)        {          ExceptionMessageDialog(E, Type);        }      }    }  }}//---------------------------------------------------------------------------void __fastcall ShowNotification(TTerminal * Terminal, const UnicodeString & Str,  TQueryType Type){  TTerminalManager * Manager = TTerminalManager::Instance(false);  assert(Manager != NULL);  Manager->ScpExplorer->PopupTrayBalloon(Terminal, Str, Type);}//---------------------------------------------------------------------------void __fastcall ConfigureInterface(){  UnicodeString S;  S = LoadStr(MIDDLE_EAST);  if (!S.IsEmpty())  {    SysLocale.MiddleEast = static_cast<bool>(StrToInt(S));  }  else  {    SysLocale.MiddleEast = false;  }  S = LoadStr(BIDI_MODE);  if (!S.IsEmpty())  {    Application->BiDiMode = static_cast<TBiDiMode>(StrToInt(bdRightToLeft));  }  else  {    Application->BiDiMode = bdLeftToRight;  }  SetTBXSysParam(TSP_XPVISUALSTYLE, XPVS_AUTOMATIC);  // Can be called during configuration creation.  // Skip now, will be called again later.  if (Configuration != NULL)  {    TBXSetTheme(WinConfiguration->Theme);  }  // Has any effect on Wine only  // (otherwise initial UserDocumentDirectory is equivalent to GetPersonalFolder())  UserDocumentDirectory = GetPersonalFolder();}//---------------------------------------------------------------------------// dummy function to force linking of TBXOfficeXPTheme.pasvoid __fastcall CreateThemes(){  new TTBXOfficeXPTheme(L"OfficeXP");  new TTBXOffice2003Theme(L"Office2003");}//---------------------------------------------------------------------------void __fastcall DoAboutDialog(TConfiguration *Configuration){  DoAboutDialog(Configuration, true, NULL);}//---------------------------------------------------------------------void __fastcall DoProductLicense(){  DoLicenseDialog(lcWinScp);}//---------------------------------------------------------------------------const UnicodeString PixelsPerInchKey = L"PixelsPerInch";//---------------------------------------------------------------------int __fastcall GetToolbarLayoutPixelsPerInch(TStrings * Storage){  int Result;  if (Storage->IndexOfName(PixelsPerInchKey))  {    Result = LoadPixelsPerInch(Storage->Values[PixelsPerInchKey]);  }  else  {    Result = -1;  }  return Result;}//---------------------------------------------------------------------static inline void __fastcall GetToolbarKey(const UnicodeString & ToolbarName,  const UnicodeString & Value, UnicodeString & ToolbarKey){  int ToolbarNameLen;  if ((ToolbarName.Length() > 7) &&      (ToolbarName.SubString(ToolbarName.Length() - 7 + 1, 7) == L"Toolbar"))  {    ToolbarNameLen = ToolbarName.Length() - 7;  }  else  {    ToolbarNameLen = ToolbarName.Length();  }  ToolbarKey = ToolbarName.SubString(1, ToolbarNameLen) + L"_" + Value;}//---------------------------------------------------------------------------static int __fastcall ToolbarReadInt(const UnicodeString ToolbarName,  const UnicodeString Value, const int Default, const void * ExtraData){  int Result;  if (Value == L"Rev")  {    Result = 2000;  }  else  {    TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));    UnicodeString ToolbarKey;    GetToolbarKey(ToolbarName, Value, ToolbarKey);    if (Storage->IndexOfName(ToolbarKey) >= 0)    {      Result = StrToIntDef(Storage->Values[ToolbarKey], Default);      #if 0      // this does not work well, as it scales down the stretched      // toolbars (path toolbars) too much, it has to be reimplemented smarter      if (Value == L"DockPos")      {        int PixelsPerInch = GetToolbarLayoutPixelsPerInch(Storage);        // When DPI has decreased since the last time, scale down        // toolbar position to get rid of gaps caused by smaller labels.        // Do not do this when DPI has increased as it would introduce gaps,        // as toolbars consists mostly of icons only, that do not scale.        // The toolbars shift themselves anyway, when other toolbars to the left        // get wider. We also risk a bit that toolbar order changes,        // as with very small toolbars (History) we can get scaled down position        // of the following toolbar to the left of it.        // There's special handling (also for scaling-up) stretched toolbars        // in LoadToolbarsLayoutStr        if ((PixelsPerInch > 0) && (Screen->PixelsPerInch < PixelsPerInch))        {          Result = LoadDimension(Result, PixelsPerInch);        }      }      #endif    }    else    {      Result = Default;    }  }  return Result;}//---------------------------------------------------------------------------static UnicodeString __fastcall ToolbarReadString(const UnicodeString ToolbarName,  const UnicodeString Value, const UnicodeString Default, const void * ExtraData){  UnicodeString Result;  TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));  UnicodeString ToolbarKey;  GetToolbarKey(ToolbarName, Value, ToolbarKey);  if (Storage->IndexOfName(ToolbarKey) >= 0)  {    Result = Storage->Values[ToolbarKey];  }  else  {    Result = Default;  }  return Result;}//---------------------------------------------------------------------------static void __fastcall ToolbarWriteInt(const UnicodeString ToolbarName,  const UnicodeString Value, const int Data, const void * ExtraData){  if (Value != L"Rev")  {    TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));    UnicodeString ToolbarKey;    GetToolbarKey(ToolbarName, Value, ToolbarKey);    assert(Storage->IndexOfName(ToolbarKey) < 0);    Storage->Values[ToolbarKey] = IntToStr(Data);  }}//---------------------------------------------------------------------------static void __fastcall ToolbarWriteString(const UnicodeString ToolbarName,  const UnicodeString Value, const UnicodeString Data, const void * ExtraData){  TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));  UnicodeString ToolbarKey;  GetToolbarKey(ToolbarName, Value, ToolbarKey);  assert(Storage->IndexOfName(ToolbarKey) < 0);  Storage->Values[ToolbarKey] = Data;}//---------------------------------------------------------------------------UnicodeString __fastcall GetToolbarsLayoutStr(TComponent * OwnerComponent){  UnicodeString Result;  TStrings * Storage = new TStringList();  try  {    TBCustomSavePositions(OwnerComponent, ToolbarWriteInt, ToolbarWriteString,      Storage);    Storage->Values[PixelsPerInchKey] = SavePixelsPerInch();    Result = Storage->CommaText;  }  __finally  {    delete Storage;  }  return Result;}//---------------------------------------------------------------------------void __fastcall LoadToolbarsLayoutStr(TComponent * OwnerComponent, UnicodeString LayoutStr){  TStrings * Storage = new TStringList();  try  {    Storage->CommaText = LayoutStr;    TBCustomLoadPositions(OwnerComponent, ToolbarReadInt, ToolbarReadString,      Storage);    int PixelsPerInch = GetToolbarLayoutPixelsPerInch(Storage);    // Scale toolbars stretched to the first other toolbar to the right    if ((PixelsPerInch > 0) && (PixelsPerInch != Screen->PixelsPerInch)) // optimization    {      for (int Index = 0; Index < OwnerComponent->ComponentCount; Index++)      {        TTBXToolbar * Toolbar =          dynamic_cast<TTBXToolbar *>(OwnerComponent->Components[Index]);        if ((Toolbar != NULL) && Toolbar->Stretch &&            (Toolbar->OnGetBaseSize != NULL) &&            // we do not support floating of stretched toolbars            ALWAYS_TRUE(!Toolbar->Floating))        {          TTBXToolbar * FollowingToolbar = NULL;          for (int Index2 = 0; Index2 < OwnerComponent->ComponentCount; Index2++)          {            TTBXToolbar * Toolbar2 =              dynamic_cast<TTBXToolbar *>(OwnerComponent->Components[Index2]);            if ((Toolbar2 != NULL) && !Toolbar2->Floating &&                (Toolbar2->Parent == Toolbar->Parent) &&                (Toolbar2->DockRow == Toolbar->DockRow) &&                (Toolbar2->DockPos > Toolbar->DockPos) &&                ((FollowingToolbar == NULL) || (FollowingToolbar->DockPos > Toolbar2->DockPos)))            {              FollowingToolbar = Toolbar2;            }          }          if (FollowingToolbar != NULL)          {            int NewWidth = LoadDimension(Toolbar->Width, PixelsPerInch);            FollowingToolbar->DockPos += NewWidth - Toolbar->Width;          }        }      }    }  }  __finally  {    delete Storage;  }}//---------------------------------------------------------------------------void __fastcall AddMenuSeparator(TTBCustomItem * Menu){  TTBXSeparatorItem * Item = new TTBXSeparatorItem(Menu);  Menu->Add(Item);}//---------------------------------------------------------------------------static TComponent * LastPopupComponent = NULL;static TRect LastPopupRect(-1, -1, -1, -1);static TDateTime LastCloseUp;//---------------------------------------------------------------------------void __fastcall MenuPopup(TPopupMenu * AMenu, TRect Rect,  TComponent * PopupComponent){  // Pressing the same button within 200ms after closing its popup menu  // does nothing.  // It is to immitate close-by-click behavior. Note that menu closes itself  // before onclick handler of button occurs.  // To support content menu popups, we have to check for the popup location too,  // to allow poping menu on different location (such as different node of TTreeView),  // even if there's another popup opened already (so that the time interval  // below does not elapse).  TDateTime N = Now();  TDateTime Diff = N - LastCloseUp;  if ((PopupComponent == LastPopupComponent) &&      (Rect == LastPopupRect) &&      (Diff < TDateTime(0, 0, 0, 200)))  {    LastPopupComponent = NULL;  }  else  {    TTBXPopupMenu * Menu = dynamic_cast<TTBXPopupMenu *>(AMenu);    if (Menu == NULL)    {      Menu = CreateTBXPopupMenu(AMenu->Owner);      Menu->OnPopup = AMenu->OnPopup;      Menu->Items->SubMenuImages = AMenu->Images;      for (int Index = 0; Index < AMenu->Items->Count; Index++)      {        TMenuItem * AItem = AMenu->Items->Items[Index];        TTBCustomItem * Item;        if (!AItem->Enabled && !AItem->Visible && (AItem->Action == NULL) &&                 (AItem->OnClick == NULL) && ALWAYS_TRUE(AItem->Count == 0))        {          TTBXLabelItem * LabelItem = new TTBXLabelItem(Menu);          // TTBXLabelItem has it's own Caption          LabelItem->Caption = AItem->Caption;          LabelItem->SectionHeader = true;          Item = LabelItem;        }        else        {          // see TB2DsgnConverter.pas DoConvert          if (AItem->Caption == L"-")          {            Item = new TTBXSeparatorItem(Menu);          }          else          {            if (AItem->Count > 0)            {              Item = new TTBXSubmenuItem(Menu);            }            else            {              Item = new TTBXItem(Menu);            }            Item->Action = AItem->Action;            Item->AutoCheck = AItem->AutoCheck;            Item->Caption = AItem->Caption;            Item->Checked = AItem->Checked;            if (AItem->Default)            {              Item->Options = Item->Options << tboDefault;            }            Item->Enabled = AItem->Enabled;            Item->GroupIndex = AItem->GroupIndex;            Item->HelpContext = AItem->HelpContext;            Item->ImageIndex = AItem->ImageIndex;            Item->RadioItem = AItem->RadioItem;            Item->ShortCut = AItem->ShortCut;            Item->SubMenuImages = AItem->SubMenuImages;            Item->OnClick = AItem->OnClick;          }          Item->Hint = AItem->Hint;          Item->Tag = AItem->Tag;          Item->Visible = AItem->Visible;          // recurse is supported only for empty submenus (as used for custom commands)          if ((AItem->Count > 0) &&              ALWAYS_TRUE((AItem->Count == 1) && (AItem->Items[0]->Caption == L"")))          {            Item->Add(new TTBXItem(Menu));          }        }        Menu->Items->Add(Item);      }    }    Menu->PopupComponent = PopupComponent;    Menu->PopupEx(Rect);    LastPopupComponent = PopupComponent;    LastPopupRect = Rect;    LastCloseUp = Now();  }}//---------------------------------------------------------------------------const int ColorCols = 8;const int StandardColorRows = 2;const int StandardColorCount = ColorCols * StandardColorRows;const int UserColorRows = 1;const int UserColorCount = UserColorRows * ColorCols;const wchar_t ColorSeparator = L',';//---------------------------------------------------------------------------static void __fastcall GetStandardSessionColorInfo(  int Col, int Row, TColor & Color, UnicodeString & Name){  #define COLOR_INFO(COL, ROW, NAME, COLOR) \    if ((Col == COL) && (Row == ROW)) { Name = NAME; Color = TColor(COLOR); } else  // bottom row of default TBX color set  COLOR_INFO(0, 0, L"Rose",              0xCC99FF)  COLOR_INFO(1, 0, L"Tan",               0x99CCFF)  COLOR_INFO(2, 0, L"Light Yellow",      0x99FFFF)  COLOR_INFO(3, 0, L"Light Green",       0xCCFFCC)  COLOR_INFO(4, 0, L"Light Turquoise",   0xFFFFCC)  COLOR_INFO(5, 0, L"Pale Blue",         0xFFCC99)  COLOR_INFO(6, 0, L"Lavender",          0xFF99CC)  // second row of Excel 2010 palette with second color (Lighter Black) skipped  COLOR_INFO(7, 0, L"Light Orange",      0xB5D5FB)  COLOR_INFO(0, 1, L"Darker White",      0xD8D8D8)  COLOR_INFO(1, 1, L"Darker Tan",        0x97BDC4)  COLOR_INFO(2, 1, L"Lighter Blue",      0xE2B38D)  COLOR_INFO(3, 1, L"Light Blue",        0xE4CCB8)  COLOR_INFO(4, 1, L"Lighter Red",       0xB7B9E5)  COLOR_INFO(5, 1, L"Light Olive Green", 0xBCE3D7)  COLOR_INFO(6, 1, L"Light Purple",      0xD9C1CC)  COLOR_INFO(7, 1, L"Light Aqua",        0xE8DDB7)  FAIL;  #undef COLOR_INFO}//---------------------------------------------------------------------------static void __fastcall SessionColorSetGetColorInfo(  void * /*Data*/, TTBXCustomColorSet * /*Sender*/, int Col, int Row, TColor & Color, UnicodeString & Name){  GetStandardSessionColorInfo(Col, Row, Color, Name);}//---------------------------------------------------------------------------static TColor __fastcall RestoreColor(UnicodeString CStr){  return TColor(StrToInt(UnicodeString(L"$") + CStr));}//---------------------------------------------------------------------------static UnicodeString __fastcall StoreColor(TColor Color){  return IntToHex(Color, 6);}//---------------------------------------------------------------------------static UnicodeString __fastcall ExtractColorStr(UnicodeString & Colors){  return ::CutToChar(Colors, ColorSeparator, true);}//---------------------------------------------------------------------------static bool __fastcall IsStandardColor(TColor Color){  for (int Row = 0; Row < StandardColorRows; Row++)  {    for (int Col = 0; Col < ColorCols; Col++)    {      TColor StandardColor;      UnicodeString Name; // unused      GetStandardSessionColorInfo(Col, Row, StandardColor, Name);      if (StandardColor == Color)      {        return true;      }    }  }  return false;}//---------------------------------------------------------------------------class TColorChangeData : public TComponent{public:  __fastcall TColorChangeData(TColorChangeEvent OnColorChange, TColor Color);  static TColorChangeData * __fastcall Retrieve(TObject * Object);  void __fastcall ColorChange(TColor Color);  __property TColor Color = { read = FColor };private:  TColorChangeEvent FOnColorChange;  TColor FColor;};//---------------------------------------------------------------------------__fastcall TColorChangeData::TColorChangeData(TColorChangeEvent OnColorChange, TColor Color) :  TComponent(NULL){  Name = QualifiedClassName();  FOnColorChange = OnColorChange;  FColor = Color;}//---------------------------------------------------------------------------TColorChangeData * __fastcall TColorChangeData::Retrieve(TObject * Object){  TComponent * Component = NOT_NULL(dynamic_cast<TComponent *>(Object));  TComponent * ColorChangeDataComponent = Component->FindComponent(QualifiedClassName());  return NOT_NULL(dynamic_cast<TColorChangeData *>(ColorChangeDataComponent));}//---------------------------------------------------------------------------void __fastcall TColorChangeData::ColorChange(TColor Color){  if ((Color != TColor(0)) &&      !IsStandardColor(Color))  {    UnicodeString SessionColors = StoreColor(Color);    UnicodeString Temp = CustomWinConfiguration->SessionColors;    while (!Temp.IsEmpty())    {      UnicodeString CStr = ExtractColorStr(Temp);      if (RestoreColor(CStr) != Color)      {        SessionColors += UnicodeString(ColorSeparator) + CStr;      }    }    CustomWinConfiguration->SessionColors = SessionColors;  }  FOnColorChange(Color);}//---------------------------------------------------------------------------static void __fastcall ColorDefaultClick(void * /*Data*/, TObject * Sender){  TColorChangeData::Retrieve(Sender)->ColorChange(TColor(0));}//---------------------------------------------------------------------------static void __fastcall ColorPaletteChange(void * /*Data*/, TObject * Sender){  TTBXColorPalette * ColorPalette = NOT_NULL(dynamic_cast<TTBXColorPalette *>(Sender));  TColor Color = (ColorPalette->Color != Vcl::Graphics::clNone ? ColorPalette->Color : (TColor)0);  TColorChangeData::Retrieve(Sender)->ColorChange(Color);}//---------------------------------------------------------------------------static UnicodeString __fastcall CustomColorName(int Index){  return UnicodeString(L"Color") + wchar_t(L'A' + Index);}//---------------------------------------------------------------------------static void __fastcall ColorPickClick(void * /*Data*/, TObject * Sender){  TColorChangeData * ColorChangeData = TColorChangeData::Retrieve(Sender);  std::unique_ptr<TColorDialog> Dialog(new TColorDialog(Application));  Dialog->Options = Dialog->Options << cdFullOpen << cdAnyColor;  Dialog->Color = (ColorChangeData->Color != 0 ? ColorChangeData->Color : clSkyBlue);  UnicodeString Temp = CustomWinConfiguration->SessionColors;  int StandardColorIndex = 0;  int CustomColors = Min(MaxCustomColors, StandardColorCount);  for (int Index = 0; Index < CustomColors; Index++)  {    TColor CustomColor;    if (!Temp.IsEmpty())    {      CustomColor = RestoreColor(ExtractColorStr(Temp));    }    else    {      UnicodeString Name; // not used      assert(StandardColorIndex < StandardColorCount);      GetStandardSessionColorInfo(        StandardColorIndex % ColorCols, StandardColorIndex / ColorCols,        CustomColor, Name);      StandardColorIndex++;    }    Dialog->CustomColors->Values[CustomColorName(Index)] = StoreColor(CustomColor);  }  if (Dialog->Execute())  {    // so that we do not have to try to preserve the excess colors    assert(UserColorCount <= MaxCustomColors);    UnicodeString SessionColors;    for (int Index = 0; Index < MaxCustomColors; Index++)    {      UnicodeString CStr = Dialog->CustomColors->Values[CustomColorName(Index)];      if (!CStr.IsEmpty())      {        TColor CustomColor = RestoreColor(CStr);        if (!IsStandardColor(CustomColor))        {          AddToList(SessionColors, StoreColor(CustomColor), ColorSeparator);        }      }    }    CustomWinConfiguration->SessionColors = SessionColors;    // call color change only after copying custom colors back,    // so that it can add selected color to the user list    ColorChangeData->ColorChange(Dialog->Color);  }}//---------------------------------------------------------------------------TPopupMenu * __fastcall CreateSessionColorPopupMenu(TColor Color,  TColorChangeEvent OnColorChange){  std::unique_ptr<TTBXPopupMenu> PopupMenu(new TTBXPopupMenu(Application));  CreateSessionColorMenu(PopupMenu->Items, Color, OnColorChange);  return PopupMenu.release();}//---------------------------------------------------------------------------static void __fastcall UserSessionColorSetGetColorInfo(  void * /*Data*/, TTBXCustomColorSet * Sender, int Col, int Row, TColor & Color, UnicodeString & /*Name*/){  int Index = (Row * Sender->ColCount) + Col;  UnicodeString Temp = CustomWinConfiguration->SessionColors;  while ((Index > 0) && !Temp.IsEmpty())  {    ExtractColorStr(Temp);    Index--;  }  if (!Temp.IsEmpty())  {    Color = RestoreColor(ExtractColorStr(Temp));  }  else  {    // hide the trailing cells    Color = Vcl::Graphics::clNone;  }}//---------------------------------------------------------------------------void __fastcall CreateColorPalette(TTBCustomItem * Owner, TColor Color, int Rows,  TCSGetColorInfo OnGetColorInfo, TColorChangeEvent OnColorChange){  TTBXCustomColorSet * ColorSet = new TTBXCustomColorSet(Owner);  TTBXColorPalette * ColorPalette = new TTBXColorPalette(Owner);  ColorPalette->InsertComponent(ColorSet);  ColorPalette->ColorSet = ColorSet;  // has to be set only after it's assigned to color palette  ColorSet->ColCount = ColorCols;  ColorSet->RowCount = Rows;  ColorSet->OnGetColorInfo = OnGetColorInfo;  ColorPalette->Color = (Color != 0) ? Color : Vcl::Graphics::clNone;  ColorPalette->OnChange = MakeMethod<TNotifyEvent>(NULL, ColorPaletteChange);  ColorPalette->InsertComponent(new TColorChangeData(OnColorChange, Color));  Owner->Add(ColorPalette);  Owner->Add(new TTBXSeparatorItem(Owner));}//---------------------------------------------------------------------------void __fastcall CreateSessionColorMenu(TComponent * AOwner, TColor Color,  TColorChangeEvent OnColorChange){  TTBCustomItem * Owner = dynamic_cast<TTBCustomItem *>(AOwner);  if (ALWAYS_TRUE(Owner != NULL))  {    Owner->Clear();    TTBCustomItem * Item;    Item = new TTBXItem(Owner);    Item->Caption = LoadStr(COLOR_DEFAULT_CAPTION);    Item->Hint = LoadStr(COLOR_DEFAULT_HINT);    Item->HelpKeyword = HELP_COLOR;    Item->OnClick = MakeMethod<TNotifyEvent>(NULL, ColorDefaultClick);    Item->Checked = (Color == TColor(0));    Item->InsertComponent(new TColorChangeData(OnColorChange, Color));    Owner->Add(Item);    Owner->Add(new TTBXSeparatorItem(Owner));    int SessionColorCount = 0;    UnicodeString Temp = CustomWinConfiguration->SessionColors;    while (!Temp.IsEmpty())    {      SessionColorCount++;      ExtractColorStr(Temp);    }    if (SessionColorCount > 0)    {      SessionColorCount = Min(SessionColorCount, UserColorCount);      int RowCount = ((SessionColorCount + ColorCols - 1) / ColorCols);      assert(RowCount <= UserColorRows);      CreateColorPalette(Owner, Color, RowCount,        MakeMethod<TCSGetColorInfo>(NULL, UserSessionColorSetGetColorInfo),        OnColorChange);    }    CreateColorPalette(Owner, Color, StandardColorRows,      MakeMethod<TCSGetColorInfo>(NULL, SessionColorSetGetColorInfo),      OnColorChange);    Owner->Add(new TTBXSeparatorItem(Owner));    Item = new TTBXItem(Owner);    Item->Caption = LoadStr(COLOR_PICK_CAPTION);    Item->Hint = LoadStr(COLOR_PICK_HINT);    Item->HelpKeyword = HELP_COLOR;    Item->OnClick = MakeMethod<TNotifyEvent>(NULL, ColorPickClick);    Item->InsertComponent(new TColorChangeData(OnColorChange, Color));    Owner->Add(Item);  }}//---------------------------------------------------------------------------void __fastcall UpgradeSpeedButton(TSpeedButton * /*Button*/){  // no-op yet}//---------------------------------------------------------------------------struct TThreadParam{  TThreadFunc ThreadFunc;  void * Parameter;};//---------------------------------------------------------------------------static int __fastcall ThreadProc(void * AParam){  TThreadParam * Param = reinterpret_cast<TThreadParam *>(AParam);  unsigned int Result = Param->ThreadFunc(Param->Parameter);  delete Param;  EndThread(Result);  return Result;}//---------------------------------------------------------------------------int __fastcall StartThread(void * SecurityAttributes, unsigned StackSize,  TThreadFunc ThreadFunc, void * Parameter, unsigned CreationFlags,  TThreadID & ThreadId){  TThreadParam * Param = new TThreadParam;  Param->ThreadFunc = ThreadFunc;  Param->Parameter = Parameter;  return BeginThread(SecurityAttributes, StackSize, ThreadProc, Param,    CreationFlags, ThreadId);}//---------------------------------------------------------------------------static TShortCut FirstCtrlNumberShortCut = ShortCut(L'0', TShiftState() << ssCtrl);static TShortCut LastCtrlNumberShortCut = ShortCut(L'9', TShiftState() << ssCtrl);static TShortCut FirstShiftCtrlAltLetterShortCut = ShortCut(L'A', TShiftState() << ssShift << ssCtrl << ssAlt);static TShortCut LastShiftCtrlAltLetterShortCut = ShortCut(L'Z', TShiftState() << ssShift << ssCtrl << ssAlt);//---------------------------------------------------------------------------void __fastcall InitializeShortCutCombo(TComboBox * ComboBox,  const TShortCuts & ShortCuts){  ComboBox->Items->BeginUpdate();  try  {    ComboBox->Items->Clear();    ComboBox->Items->AddObject(LoadStr(SHORTCUT_NONE), reinterpret_cast<TObject* >(0));    for (TShortCut AShortCut = FirstCtrlNumberShortCut; AShortCut <= LastCtrlNumberShortCut; AShortCut++)    {      if (!ShortCuts.Has(AShortCut))      {        ComboBox->Items->AddObject(ShortCutToText(AShortCut), reinterpret_cast<TObject* >(AShortCut));      }    }    for (TShortCut AShortCut = FirstShiftCtrlAltLetterShortCut; AShortCut <= LastShiftCtrlAltLetterShortCut; AShortCut++)    {      if (!ShortCuts.Has(AShortCut))      {        ComboBox->Items->AddObject(ShortCutToText(AShortCut), reinterpret_cast<TObject* >(AShortCut));      }    }  }  __finally  {    ComboBox->Items->EndUpdate();  }  ComboBox->Style = csDropDownList;  ComboBox->DropDownCount = Max(ComboBox->DropDownCount, 16);}//---------------------------------------------------------------------------void __fastcall SetShortCutCombo(TComboBox * ComboBox, TShortCut Value){  for (int Index = ComboBox->Items->Count - 1; Index >= 0; Index--)  {    TShortCut AShortCut = TShortCut(ComboBox->Items->Objects[Index]);    if (AShortCut == Value)    {      ComboBox->ItemIndex = Index;      break;    }    else if (AShortCut < Value)    {      assert(Value != 0);      ComboBox->Items->InsertObject(Index + 1, ShortCutToText(Value),        reinterpret_cast<TObject* >(Value));      ComboBox->ItemIndex = Index + 1;      break;    }    assert(Index > 0);  }}//---------------------------------------------------------------------------TShortCut __fastcall GetShortCutCombo(TComboBox * ComboBox){  return TShortCut(ComboBox->Items->Objects[ComboBox->ItemIndex]);}//---------------------------------------------------------------------------bool __fastcall IsCustomShortCut(TShortCut ShortCut){  return    ((FirstCtrlNumberShortCut <= ShortCut) && (ShortCut <= LastCtrlNumberShortCut)) ||    ((FirstShiftCtrlAltLetterShortCut <= ShortCut) && (ShortCut <= LastShiftCtrlAltLetterShortCut));}//---------------------------------------------------------------------------//---------------------------------------------------------------------------class TMasterPasswordDialog : public TCustomDialog{public:  __fastcall TMasterPasswordDialog(bool Current);  bool __fastcall Execute(UnicodeString & CurrentPassword, UnicodeString & NewPassword);protected:  virtual void __fastcall DoValidate();  virtual void __fastcall DoChange(bool & CanSubmit);private:  TPasswordEdit * CurrentEdit;  TPasswordEdit * NewEdit;  TPasswordEdit * ConfirmEdit;};//---------------------------------------------------------------------------__fastcall TMasterPasswordDialog::TMasterPasswordDialog(bool Current) :  TCustomDialog(Current ? HELP_MASTER_PASSWORD_CURRENT : HELP_MASTER_PASSWORD_CHANGE){  Caption = LoadStr(MASTER_PASSWORD_CAPTION);  CurrentEdit = new TPasswordEdit(this);  AddEdit(CurrentEdit, CreateLabel(LoadStr(MASTER_PASSWORD_CURRENT)));  EnableControl(CurrentEdit, Current || WinConfiguration->UseMasterPassword);  CurrentEdit->MaxLength = PasswordMaxLength();  if (!Current)  {    NewEdit = new TPasswordEdit(this);    AddEdit(NewEdit, CreateLabel(LoadStr(MASTER_PASSWORD_NEW)));    NewEdit->MaxLength = CurrentEdit->MaxLength;    if (!WinConfiguration->UseMasterPassword)    {      ActiveControl = NewEdit;    }    ConfirmEdit = new TPasswordEdit(this);    AddEdit(ConfirmEdit, CreateLabel(LoadStr(MASTER_PASSWORD_CONFIRM)));    ConfirmEdit->MaxLength = CurrentEdit->MaxLength;  }  else  {    NewEdit = NULL;    ConfirmEdit = NULL;  }}//---------------------------------------------------------------------------bool __fastcall TMasterPasswordDialog::Execute(  UnicodeString & CurrentPassword, UnicodeString & NewPassword){  bool Result = TCustomDialog::Execute();  if (Result)  {    if (CurrentEdit->Enabled)    {      CurrentPassword = CurrentEdit->Text;    }    if (NewEdit != NULL)    {      NewPassword = NewEdit->Text;    }  }  return Result;}//---------------------------------------------------------------------------void __fastcall TMasterPasswordDialog::DoChange(bool & CanSubmit){  CanSubmit =    (!WinConfiguration->UseMasterPassword || (IsValidPassword(CurrentEdit->Text) >= 0)) &&    ((NewEdit == NULL) || (IsValidPassword(NewEdit->Text) >= 0)) &&    ((ConfirmEdit == NULL) || (IsValidPassword(ConfirmEdit->Text) >= 0));  TCustomDialog::DoChange(CanSubmit);}//---------------------------------------------------------------------------void __fastcall TMasterPasswordDialog::DoValidate(){  TCustomDialog::DoValidate();  if (WinConfiguration->UseMasterPassword &&      !WinConfiguration->ValidateMasterPassword(CurrentEdit->Text))  {    CurrentEdit->SetFocus();    CurrentEdit->SelectAll();    throw Exception(MainInstructions(LoadStr(MASTER_PASSWORD_INCORRECT)));  }  if (NewEdit != NULL)  {    if (NewEdit->Text != ConfirmEdit->Text)    {      ConfirmEdit->SetFocus();      ConfirmEdit->SelectAll();      throw Exception(MainInstructions(LoadStr(MASTER_PASSWORD_DIFFERENT)));    }    int Valid = IsValidPassword(NewEdit->Text);    if (Valid <= 0)    {      assert(Valid == 0);      if (MessageDialog(LoadStr(MASTER_PASSWORD_SIMPLE2), qtWarning,            qaOK | qaCancel, HELP_MASTER_PASSWORD_SIMPLE) == qaCancel)      {        NewEdit->SetFocus();        NewEdit->SelectAll();        Abort();      }    }  }}//---------------------------------------------------------------------------static bool __fastcall DoMasterPasswordDialog(bool Current,  UnicodeString & NewPassword){  bool Result;  TMasterPasswordDialog * Dialog = new TMasterPasswordDialog(Current);  try  {    UnicodeString CurrentPassword;    Result = Dialog->Execute(CurrentPassword, NewPassword);    if (Result)    {      if ((Current || WinConfiguration->UseMasterPassword) &&          ALWAYS_TRUE(!CurrentPassword.IsEmpty()))      {        WinConfiguration->SetMasterPassword(CurrentPassword);      }    }  }  __finally  {    delete Dialog;  }  return Result;}//---------------------------------------------------------------------------bool __fastcall DoMasterPasswordDialog(){  UnicodeString NewPassword;  bool Result = DoMasterPasswordDialog(true, NewPassword);  assert(NewPassword.IsEmpty());  return Result;}//---------------------------------------------------------------------------bool __fastcall DoChangeMasterPasswordDialog(UnicodeString & NewPassword){  bool Result = DoMasterPasswordDialog(false, NewPassword);  return Result;}//---------------------------------------------------------------------------void __fastcall MessageWithNoHelp(const UnicodeString & Message){  TMessageParams Params;  Params.AllowHelp = false; // to avoid recursion  if (MessageDialog(LoadStr(HELP_SEND_MESSAGE2), qtConfirmation,        qaOK | qaCancel, HELP_NONE, &Params) == qaOK)  {    SearchHelp(Message);  }}//---------------------------------------------------------------------------bool __fastcall CheckXmlLogParam(TProgramParams * Params){  UnicodeString LogFile;  bool Result =    Params->FindSwitch(L"XmlLog", LogFile) &&    CheckSafe(Params);  if (Result)  {    Configuration->Usage->Inc(L"ScriptXmlLog");    Configuration->TemporaryActionsLogging(LogFile);  }  return Result;}//---------------------------------------------------------------------------bool __fastcall CheckSafe(TProgramParams * Params){  // Originally we warned when the test didn't pass,  // but it would actually be helping hackers, so let's be silent.  // Earlier we tested presence of any URL on command-line.  // That was added to prevent abusing URL handler in 3.8.2 (2006).  // Later in 4.0.4 (2007) an /Unsafe switch was added to URL handler registration.  // So by now, we can check for the switch only and  // do not limit user from combining URL with say  // /rawconfig  return !Params->FindSwitch(UNSAFE_SWITCH);}
 |