Changeset 353


Ignore:
Timestamp:
Jun 15, 2009, 11:19:34 PM (12 years ago)
Author:
Arno Wacker
Message:

Enigma: major update

  • Included double-stepping, hence the compatibility to a real Enigma should now be complete
  • Complete rewrite of basic code (old code is uncommented and just for archiving still there; will be removed with next check-in), leading to some speed-up. Improvement still possible.
  • Added a ciphertext-only crypt-analyzer to the plugin. The analyzer follows the algorithm given by James Gillogly in Cryptologia October 1995; Volume XIX, Number 4 (http://www.fortunecity.com/skyscraper/coding/379/gillog1.htm); activate the analyzer by choosing "Analyze" as operation mode.
  • The analyzer still uses only the index of coincidences as the cost function, unlike proposed by J. Gillogly. Improvement for plug-detection is expected when using a specific log-trigraph sum as the cost function.
  • Added four new samples for demostrating the plugin (encryption/decryption/cryptanalysis), including a short description inside the samples
  • The plugin is still work-in-progress and still missing some feature, e.g.
    • no description available yet
    • no quickwatch or presentation available
    • only the 3-rotor "Enigma I / M3" is currently supported, other models are prepared (can actually be selected in the settings) however, the implementation is not done for them, hence the plugin will quit with a controlled error-message.
    • The analyzer only uses one CPU core for the heavy work, i.e. it works strictly sequentially. Since the heavy work is searching through the rotor-space, it could be improved by searching the key space in parallel.
Location:
trunk
Files:
8 added
2 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypPlugins/Enigma/Enigma.cs

    r317 r353  
    211211using System.Windows.Controls;
    212212using System.ComponentModel;
     213using System.Threading;
     214using System.Collections;
     215using System.Diagnostics;
    213216
    214217//Cryptool 2.0 specific includes
     
    217220using Cryptool.PluginBase.Miscellaneous;
    218221using Cryptool.PluginBase.IO;
    219 using System.ComponentModel;
     222
     223
    220224
    221225namespace Cryptool.Enigma
    222226{
    223     [Author("Dr. Arno Wacker", "arno.wacker@cryptool.org", "Uni Duisburg", "http://www.uni-duisburg-essen.de")]
     227    [Author("Dr. Arno Wacker", "arno.wacker@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-duisburg-essen.de")]
    224228    [PluginInfo(false, "Enigma", "Polyalphabetic rotor-cipher machine.", null,
    225229      "Enigma/Images/Enigma.png", "Enigma/Images/encrypt.png", "Enigma/Images/decrypt.png")]
     
    229233        #region Private variables
    230234
     235        private bool stop = false;
     236
    231237        private EnigmaSettings settings;
     238        private EnigmaCore core;
     239        private EnigmaAnalyzer analyzer;
    232240        private string inputString;
    233241        private string outputString;
    234         private string initialKey;
    235         private string[,] rotors = new string[,]{
    236                                         { // Kommerzielle Enigma A/B, ab 1924
    237                                             "DMTWSILRUYQNKFEJCAZBPGXOHV",
    238                                             "HQZGPJTMOBLNCIFDYAWVEUSRXL",
    239                                             "UQNTLSZFMREHDPLKIBVYGJCWGA",
    240                                             "",
    241                                             "",
    242                                             "",
    243                                             "",
    244                                             "",
    245                                         },
    246                                         { // Kommerzielle Enigma D
    247                                           // ETW: JWULCMNOHPQZYXIRADKEGVBTSF
    248                                             "LPGSZMHAEOQKVXRFYBUTNICJDW",
    249                                             "SLVGBTFXJQOHEWIRZYAMKPCNDU",
    250                                             "CJGDPSHKTURAWZXFMYNQOBVLIE",
    251                                             "",
    252                                             "",
    253                                             "",
    254                                             "",
    255                                             "",
    256                                         },
    257                                         { // Enigma der Reichsbahn („Rocket“), ab 7. Feb 1941
    258                                           // ETW: QWERTZUIOASDFGHJKPYXCVBNML
    259                                             "JGDQOXUSCAMIFRVTPNEWKBLZYH",
    260                                             "NTZPSFBOKMWRCJDIVLAEYUXHGQ",
    261                                             "JVIUBHTCDYAKEQZPOSGXNRMWFL",
    262                                             "",
    263                                             "",
    264                                             "",
    265                                             "",
    266                                             "",
    267                                         },
    268                                         {   // Enigma I, ab 1930, Walzen IV ab 1938, Walzen V-VII ab 1938
    269                                             // ETW: ABCDEFGHIJKLMNOPQRSTUVWXYZ
    270                                             "EKMFLGDQVZNTOWYHXUSPAIBRCJ", // I
    271                                             "AJDKSIRUXBLHWTMCQGZNPYFVOE", // II
    272                                             "BDFHJLCPRTXVZNYEIWGAKMUSQO", // III
    273                                             "ESOVPZJAYQUIRHXLNFTGKDCMWB", // IV
    274                                             "VZBRGITYUPSDNHLXAWMJQOFECK", // V
    275                                             "JPGVOUMFYQBENHZRDKASXLICTW", // VI
    276                                             "NZJHGRCXMYSWBOUFAIVLPEKQDT", // VII
    277                                             "FKQHTLXOCBJSPDZRAMEWNIUYGV"  // VIII
    278                                         },
    279                                         {   // Enigma M4 "Shark"
    280                                             // ETW: ABCDEFGHIJKLMNOPQRSTUVWXYZ
    281                                             "LEYJVCNIXWPBQMDRTAKZGFUHOS", // Beta, ab 1 Feb. 1942
    282                                             "FSOKANUERHMBTIYCWLQPZXVGJD", // Gamma, ab 1. Juli 1943
    283                                             "",
    284                                             "",
    285                                             "",
    286                                             "",
    287                                             "",
    288                                             "",
    289                                         }
    290                                   };
    291         private string[,] reflectors = {
    292                                            {  // Kommerzielle Enigma A/B - there was no reflector
    293                                               "",
    294                                               "",
    295                                               "" 
    296                                            },
    297                                            {  // Kommerzielle Enigma D
    298                                               "IMETCGFRAYSQBZXWLHKDVUPOJN",
    299                                               "",
    300                                               "" 
    301                                            },
    302                                            {  // Enigma der Reichsbahn („Rocket“), ab 7. Feb 1941
    303                                               "QYHOGNECVPUZTFDJAXWMKISRBL",
    304                                               "",
    305                                               "" 
    306                                            },
    307                                            {  // Enigma I, ab 1930, Walzen IV ab 1938, Walzen V-VII ab 1938
    308                                               "EJMZALYXVBWFCRQUONTSPIKHGD", // UKW A
    309                                               "YRUHQSLDPXNGOKMIEBFZCWVJAT", // UKW B
    310                                               "FVPJIAOYEDRZXWGCTKUQSBNMHL"  // UKW C
    311                                            },
    312                                            {  // Enigma M4 "Shark"
    313                                               "",
    314                                               "ENKQAUYWJICOPBLMDXZVFTHRGS",
    315                                               "RDOBJNTKVEHMLFCWZAXGYIPSUQ" 
    316                                            },
    317                                        };
    318 
    319         private string[] notches = {
    320                                        "Q",  // I
    321                                        "E",  // II
    322                                        "V",  // III
    323                                        "J",  // IV
    324                                        "Z",  // V
    325                                        "ZM", // VI
    326                                        "ZM", // VII
    327                                        "ZM"  // VIII
    328                                     };
    329 
    330 
    331         string A; // local variable for alphabet
    332         int aLength; // alphabet length
    333 
    334         string rotor1For, rotor2For, rotor3For, rotor4For; // forward susbstitution strings for the rotors   
    335         string rotor1Rev, rotor2Rev, rotor3Rev, rotor4Rev; // reverse susbstitution strings for the rotors
    336         string reflector;
    337 
    338         string rotor1notches, rotor2notches, rotor3notches; // rotor notches
     242        private string savedKey;
     243       
     244        //private class analysisConfigSettings :IComparable<analysisConfigSettings>
     245        //{
     246        //    public int Rotor1;
     247        //    public int Rotor2;
     248        //    public int Rotor3;
     249        //    public int Ring1;
     250        //    public int Ring2;
     251        //    public int Ring3;
     252        //    public string Key;
     253        //    public string PlugBoard = "-- no plugs --";
     254        //    public double IC;
     255
     256        //    #region IComparable<analysisConfigSettings> Member
     257
     258        //    public int CompareTo(analysisConfigSettings other)
     259        //    {
     260        //        return this.IC.CompareTo(other.IC);
     261        //    }
     262
     263        //    #endregion
     264        //}
     265
     266        //private List<analysisConfigSettings> analysisCandidates = new List<analysisConfigSettings>();
     267        //private const int maxAnalysisEntries = 10;
     268       
    339269       
    340270        #endregion
    341271
     272        #region Private methods
     273
     274        #region Formatting stuff
     275
     276        /// <summary>
     277        /// Encrypts or decrypts a string with the given key (rotor positions) and formats
     278        /// the output according to the settings
     279        /// </summary>
     280        /// <param name="rotor1Pos">Position of rotor 1 (fastest)</param>
     281        /// <param name="rotor2Pos">Position of rotor 2 (middle)</param>
     282        /// <param name="rotor3Pos">Position of rotor 3 (slowest)</param>
     283        /// <param name="rotor4Pos">Position of rotor 4 (extra rotor for M4)</param>
     284        /// <param name="text">The text for en/decryption. This string may contain
     285        /// arbitrary characters, which will be dealt with according to the settings given</param>
     286        /// <returns>The encrypted/decrypted string</returns>
     287        private string FormattedEncrypt(int rotor1Pos, int rotor2Pos, int rotor3Pos, int rotor4Pos, string text)
     288        {
     289            return postFormatOutput(core.Encrypt(rotor1Pos, rotor2Pos, rotor3Pos, rotor4Pos, preFormatInput(text)));
     290        }
     291
     292        /// <summary>
     293        /// Format the string to contain only alphabet characters in upper case
     294        /// </summary>
     295        /// <param name="text">The string to be prepared</param>
     296        /// <returns>The properly formated string to be processed direct by the encryption function</returns>
     297        private string preFormatInput(string text)
     298        {
     299            StringBuilder result = new StringBuilder();
     300
     301            foreach (char c in text)
     302            {
     303                if (!settings.Alphabet.Contains(char.ToUpper(c)))
     304                {
     305                    switch (settings.UnknownSymbolHandling)
     306                    {
     307                        case 0: // ignore
     308                            result.Append(c);
     309                            break;
     310                        case 1: // remove
     311                            continue;
     312                        case 2: // replace by X
     313                            result.Append('X');
     314                            break;
     315                    }
     316                }
     317                else
     318                    result.Append(c);
     319            }
     320
     321            return result.ToString();
     322
     323        }
     324
     325        /// <summary>
     326        /// Formats the string processed by the encryption for presentation according
     327        /// to the settings given
     328        /// </summary>
     329        /// <param name="text">The encrypted text</param>
     330        /// <returns>The formatted text for output</returns>
     331        private string postFormatOutput(string text)
     332        {
     333            switch (settings.CaseHandling)
     334            {
     335                case 0: // preserve
     336                    break;
     337                case 1: // upper
     338                    return text.ToUpper();
     339                case 2: // lower
     340                    return text.ToLower();
     341            }
     342            return text;
     343        }
     344
     345        #endregion
     346
     347        #region Analyzer
     348
     349        /// <summary>
     350        /// This venthandler is called, when the analyzer has an intermediate result
     351        /// </summary>
     352        /// <param name="sender"></param>
     353        /// <param name="e"></param>
     354        private void analyzer_OnIntermediateResult(object sender, IntermediateResultEventArgs e)
     355        {
     356            // Got an intermidate results from the analyzer, hence display it
     357            outputString = e.Result;
     358            OnPropertyChanged("OutputString");
     359        }
     360
     361
     362
     363        //private void printBestCandidates()
     364        //{
     365        //    StringBuilder message = new StringBuilder("  -- Analysis results --" + Environment.NewLine);
     366        //    message.AppendLine("=====================================");
     367
     368        //    foreach (analysisConfigSettings cfg in analysisCandidates)
     369        //    {
     370        //        message.AppendFormat("{0} | {1},{2},{3} | {4},{5},{6} | {7} | {8}" + Environment.NewLine,
     371        //            cfg.IC.ToString(),
     372        //            (rotorEnum)cfg.Rotor3, (rotorEnum)cfg.Rotor2, (rotorEnum)cfg.Rotor1,
     373        //            cfg.Ring3.ToString("00"), cfg.Ring2.ToString("00"), cfg.Ring1.ToString("00"),
     374        //            cfg.Key, pB2String(cfg.PlugBoard));
     375        //    }
     376
     377        //    EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message.ToString(), this, NotificationLevel.Info));
     378        //}
     379
     380        //private string analyze(int rotor1Pos, int rotor2Pos, int rotor3Pos, string text)
     381        //{
     382        //    string result = core.Encrypt(rotor1Pos, rotor2Pos, rotor3Pos,0,text);
     383        //    double newIC = calculateIC(result);
     384
     385        //    if (analysisCandidates.Count >= maxAnalysisEntries)
     386        //    {
     387        //        // List is full, check if we need to remove one
     388        //        if (newIC > analysisCandidates[0].IC)
     389        //        {
     390        //            double currentMax = analysisCandidates[analysisCandidates.Count - 1].IC;
     391
     392        //            analysisConfigSettings csetting = new analysisConfigSettings();
     393        //            csetting.IC = newIC;
     394        //            csetting.Rotor1 = core.Rotor1;
     395        //            csetting.Rotor2 = core.Rotor2;
     396        //            csetting.Rotor3 = core.Rotor3;
     397        //            csetting.Ring1 = core.Ring1;
     398        //            csetting.Ring2 = core.Ring2;
     399        //            csetting.Ring3 = core.Ring3;
     400        //            csetting.PlugBoard = core.Plugboard;
     401        //            csetting.Key = settings.Alphabet[rotor3Pos].ToString() + settings.Alphabet[rotor2Pos].ToString() + settings.Alphabet[rotor1Pos].ToString();
     402
     403        //            analysisCandidates.Add(csetting);
     404        //            analysisCandidates.Sort();
     405
     406        //            // remove the smallest one
     407        //            analysisCandidates.RemoveAt(0);
     408
     409
     410        //            if (newIC > currentMax)
     411        //            {
     412        //                // new best option
     413        //                string status = String.Format("ANALYSIS: ==> Found better rotor settings: {0},{1},{2}; {3},{4},{5}; Key: {6}; I.C.={7} <==",
     414        //                (rotorEnum)csetting.Rotor3, (rotorEnum)csetting.Rotor2, (rotorEnum)csetting.Rotor1,
     415        //                csetting.Ring3.ToString("00"), csetting.Ring2.ToString("00"), csetting.Ring1.ToString("00"),
     416        //                csetting.Key, newIC.ToString());
     417        //                EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(status, this, NotificationLevel.Info));
     418
     419        //                printBestCandidates();
     420
     421        //                outputString = result;
     422        //                OnPropertyChanged("OutputString");
     423        //            }
     424
     425                   
     426        //        }
     427        //    }
     428        //    else
     429        //    {
     430        //        //there is room left, hence add the element
     431
     432        //        analysisConfigSettings csetting = new analysisConfigSettings();
     433        //        csetting.IC = newIC;
     434        //        csetting.Rotor1 = core.Rotor1;
     435        //        csetting.Rotor2 = core.Rotor2;
     436        //        csetting.Rotor3 = core.Rotor3;
     437        //        csetting.Ring1 = core.Ring1;
     438        //        csetting.Ring2 = core.Ring2;
     439        //        csetting.Ring3 = core.Ring3;
     440        //        csetting.PlugBoard = core.Plugboard;
     441        //        csetting.Key = settings.Alphabet[rotor3Pos].ToString() + settings.Alphabet[rotor2Pos].ToString() + settings.Alphabet[rotor1Pos].ToString();
     442
     443        //        analysisCandidates.Add(csetting);
     444        //        analysisCandidates.Sort();
     445
     446        //        if (analysisCandidates.Count == maxAnalysisEntries)
     447        //        {
     448        //            printBestCandidates();
     449
     450        //            // current best option
     451        //            analysisConfigSettings bestOption = analysisCandidates[analysisCandidates.Count - 1];
     452
     453        //            string status = String.Format("ANALYSIS: Best candidates is filled. Best option so far: {0},{1},{2}; Key: {3}; I.C.={4}",
     454        //            (rotorEnum)bestOption.Rotor3, (rotorEnum)bestOption.Rotor2, (rotorEnum)bestOption.Rotor1, bestOption.Key, bestOption.IC.ToString());
     455        //            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(status, this, NotificationLevel.Debug));
     456
     457        //            // fire the event, so someting becomes visible..
     458        //            outputString = result;
     459        //            OnPropertyChanged("OutputString");
     460        //        }
     461
     462        //    }
     463
     464        //    return result;
     465        //}
     466
     467        //private double calculateIC(string input)
     468        //{
     469        //    int[] statistics = new int[settings.Alphabet.Length];
     470        //    long cipherTextLength = 0; //input.Length; //n
     471        //    long countDoubleCharacters = 0;
     472
     473        //    // first count the frequency of (single) letters
     474        //    foreach (char c in input)
     475        //    {
     476        //        int i = settings.Alphabet.IndexOf(char.ToUpper(c));
     477        //        if (i >= 0) statistics[i]++;
     478        //    }
     479
     480
     481        //    // now calculate the index of coincidences
     482        //    for (int i = 0; i < statistics.Length; i++)
     483        //    {
     484        //        cipherTextLength += statistics[i];
     485        //        countDoubleCharacters += (statistics[i] * (statistics[i] - 1));
     486        //    }
     487
     488        //    return((double)countDoubleCharacters / (double)(cipherTextLength * (cipherTextLength - 1)));
     489        //}
     490
     491        //private void runAnalysis(string inputText)
     492        //{
     493        //    LogMessage("=========> ANALYSIS OF ENIGMA MESSAGE STARTED <=========", NotificationLevel.Info);
     494
     495
     496        //    // some initialisation
     497        //    analysisCandidates.Clear();
     498
     499
     500        //    //prepare for analysis
     501        //    LogMessage("ANALYSIS: Preformatting text...", NotificationLevel.Debug);
     502        //    string preformatedText = preFormatInput(inputText);
     503
     504        //    if (settings.AnalyzeRotors)
     505        //    {
     506        //        LogMessage("ANALYSIS: ====> Stage 1 - Searching used rotors <====", NotificationLevel.Info);
     507        //        analyzeRotors(preformatedText);
     508        //    }
     509        //    else
     510        //    {
     511        //        LogMessage("ANALYSIS: ====> Skipping stage 1 - Using rotors  from settings <====", NotificationLevel.Info);
     512        //        analysisConfigSettings settingsConfig = new analysisConfigSettings();
     513        //        settingsConfig.Rotor1 = settings.Rotor1;
     514        //        settingsConfig.Rotor2 = settings.Rotor2;
     515        //        settingsConfig.Rotor3 = settings.Rotor3;
     516        //        settingsConfig.Ring1 = settings.AnalyzeRings ? 1 : settings.Ring1;
     517        //        settingsConfig.Ring2 = settings.AnalyzeRings ? 1 : settings.Ring2;
     518        //        settingsConfig.Ring3 = settings.AnalyzeRings ? 1 : settings.Ring3;
     519        //        settingsConfig.Key = settings.Key;
     520
     521        //        analysisCandidates.Add(settingsConfig);
     522        //    }
     523           
     524        //    // just for debugging
     525        //    //analysisCandidates[analysisCandidates.Count-1].Rotor1 = 2;
     526        //    //analysisCandidates[analysisCandidates.Count - 1].Rotor2 = 0;
     527        //    //analysisCandidates[analysisCandidates.Count - 1].Rotor3 = 1;
     528        //    //analysisCandidates[analysisCandidates.Count - 1].Key = "BKF";
     529
     530        //    printBestCandidates();
     531
     532        //    // put the core in quiet mode, since now many internal changes occur
     533        //    core.VerboseLevel = VerboseLevels.Quiet;
     534
     535        //    if (settings.AnalyzeRings)
     536        //    {
     537        //        LogMessage("ANALYSIS: ====> Stage 2 - Searching ring positions <====", NotificationLevel.Info);
     538
     539        //        for (int j = analysisCandidates.Count - 1; j >= 0; j--)
     540        //        {
     541        //            analysisCandidates[j].PlugBoard = settings.Alphabet; // empty plugs
     542        //            analyzeRings(analysisCandidates[j], preformatedText);
     543        //        }
     544
     545        //        analysisCandidates.Sort();
     546        //    }
     547        //    else
     548        //    {
     549        //        LogMessage("ANALYSIS: ====> Skipping stage 2 - Using provided ring settings <====", NotificationLevel.Info);
     550
     551        //        for (int j = analysisCandidates.Count - 1; j >= 0; j--)
     552        //        {
     553        //            analysisCandidates[j].PlugBoard = settings.Alphabet; // empty plugs
     554        //            analysisCandidates[j].Ring1 = settings.Ring1;
     555        //            analysisCandidates[j].Ring2 = settings.Ring2;
     556        //            analysisCandidates[j].Ring3 = settings.Ring3;
     557        //        }
     558        //    }
     559
     560        //    printBestCandidates();
     561
     562
     563        //    if (settings.AnalyzePlugs)
     564        //    {
     565        //        LogMessage("ANALYSIS: ====> Stage 3 - Searching used plugs <====", NotificationLevel.Info);
     566
     567        //        for (int j = analysisCandidates.Count - 1; j >= 0; j--)
     568        //        {
     569        //            analyzePlugs(analysisCandidates[j], settings.MaxSearchedPlugs, preformatedText);
     570        //        }
     571
     572        //        analysisCandidates.Sort();
     573        //    }
     574        //    else
     575        //    {
     576        //        LogMessage("ANALYSIS: ====> Skipping stage 3 - Using provided plugboard <====", NotificationLevel.Info);
     577
     578        //        for (int j = analysisCandidates.Count - 1; j >= 0; j--)
     579        //        {
     580        //            analysisCandidates[j].PlugBoard = settings.PlugBoard;
     581        //        }
     582        //    }
     583
     584        //    printBestCandidates();
     585
     586           
     587        //    LogMessage("=========> ANALYSIS OF ENIGMA MESSAGE DONE <=========", NotificationLevel.Info);
     588
     589        //    // switch back to verbose core
     590        //    core.VerboseLevel = VerboseLevels.VeryVerbose;
     591
     592        //    // decrypt with best option
     593        //    analysisConfigSettings bestConfig = analysisCandidates[analysisCandidates.Count - 1];
     594
     595        //    core.setInternalConfig(bestConfig.Rotor1, bestConfig.Rotor2, bestConfig.Rotor3, 0, settings.Reflector, bestConfig.Ring1, bestConfig.Ring2, bestConfig.Ring3, 1, bestConfig.PlugBoard);
     596        //    int r1p = settings.Alphabet.IndexOf(bestConfig.Key[2]);
     597        //    int r2p = settings.Alphabet.IndexOf(bestConfig.Key[1]);
     598        //    int r3p = settings.Alphabet.IndexOf(bestConfig.Key[0]);
     599        //    outputString = postFormatOutput(core.Encrypt(r1p, r2p, r3p, 0, preformatedText));
     600        //    OnPropertyChanged("OutputString");
     601
     602        //}
     603
     604        //private void analyzeRotors(string text)
     605        //{
     606        //    // Start the stopwatch
     607        //    Stopwatch sw = Stopwatch.StartNew();
     608        //    int trials = 0;
     609
     610        //    for (int i = 0; i < 8; i++)
     611        //    {
     612        //        //Rotor 3 (slowest)
     613        //        if (!includeRotor(i)) continue;
     614        //        settings.Rotor3 = i;
     615        //        for (int j = 0; j < 8; j++)
     616        //        {
     617        //            // Rotor 2 (middle)
     618        //            if (!includeRotor(j) || j==i) continue;
     619        //            settings.Rotor2 = j;
     620
     621        //            for (int k = 0; k < 8; k++)
     622        //            {
     623        //                // Rotor 1 (fastest)
     624        //                if (!includeRotor(k) || k == i || k == j) continue;
     625        //                settings.Rotor1 = k;
     626
     627        //                //set the internal Config to the new rotors
     628        //                core.setInternalConfig(k, j, i, 0, settings.Reflector,
     629        //                    settings.AnalyzeRings?1: settings.Ring1,
     630        //                    settings.AnalyzeRings ? 1 : settings.Ring2,
     631        //                    settings.AnalyzeRings ? 1 : settings.Ring3,
     632        //                    settings.Ring4,
     633        //                    settings.AnalyzePlugs ? settings.Alphabet: settings.PlugBoard);
     634
     635        //                analyzeKey(text);
     636        //                trials++;
     637
     638        //                EventsHelper.ProgressChanged(OnPluginProgressChanged, this,
     639        //                        new PluginProgressEventArgs(i * Math.Pow(8, 2) + j * 8 + k, Math.Pow(8, 3)));
     640
     641        //                if (stop) break;
     642        //            } // Rotor 1
     643        //            if (stop) break;
     644        //        } // Rotor 2
     645        //        if (stop) break;
     646        //    } // Rotor 3
     647
     648        //    // Stop the stopwatch
     649        //    sw.Stop();
     650
     651        //    string msg = String.Format("Processed {0} rotor permutations in {1}!",
     652        //        trials, sw.Elapsed.ToString());
     653        //    LogMessage(msg, NotificationLevel.Info);
     654        //}
     655
     656        //private bool includeRotor(int i)
     657        //{
     658        //    switch (i)
     659        //    {
     660        //        case 0: return settings.AnalysisUseRotorI;
     661        //        case 1: return settings.AnalysisUseRotorII;
     662        //        case 2: return settings.AnalysisUseRotorIII;
     663        //        case 3: return settings.AnalysisUseRotorIV;
     664        //        case 4: return settings.AnalysisUseRotorV;
     665        //        case 5: return settings.AnalysisUseRotorVI;
     666        //        case 6: return settings.AnalysisUseRotorVII;
     667        //        case 7: return settings.AnalysisUseRotorVIII;
     668        //    }
     669        //    return false;
     670        //}
     671
     672        //private void analyzeKey(string text)
     673        //{
     674        //    /////////////////////////////////////////
     675        //    // now run through all rotor positions..
     676
     677        //    // Start the stopwatch
     678        //    Stopwatch sw = Stopwatch.StartNew();
     679        //    int trials = 0;
     680
     681        //    // Rotor 1 positions (fastest)
     682        //    for (int l = 0; l < 26; l++)
     683        //    {
     684        //        for (int m = 0; m < 26; m++)
     685        //        {
     686        //            for (int n = 0; n < 26; n++)
     687        //            {
     688        //                analyze(l, m, n, text);
     689        //                trials++;
     690        //                if (stop) break;
     691        //            }
     692        //            if (stop) break;
     693        //        }
     694        //        if (stop) break;
     695        //    } // Rotor1 positions
     696
     697        //    // Stop the stopwatch
     698        //    sw.Stop();
     699
     700        //    string msg = String.Format("Processed {0} rotor positions for {1},{2},{3} in {4}!",
     701        //        trials, (rotorEnum)core.Rotor3, (rotorEnum)core.Rotor2, (rotorEnum)core.Rotor1, sw.Elapsed.ToString());
     702        //    LogMessage(msg, NotificationLevel.Info);
     703        //}
     704
     705        //private void analyzeRings(analysisConfigSettings enigmaConfig, string text)
     706        //{
     707
     708        //    // get the current rotor positions
     709        //    int r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
     710        //    int r2pos = settings.Alphabet.IndexOf(enigmaConfig.Key[1]);
     711        //    int r3pos = settings.Alphabet.IndexOf(enigmaConfig.Key[0]);
     712
     713        //    if (settings.AnalyzeKey)
     714        //    {
     715        //        // turn fast rotor
     716        //        for (int i = 1; i <= settings.Alphabet.Length; i++)
     717        //        {
     718        //            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, i, 1, 1, 1, enigmaConfig.PlugBoard);
     719
     720
     721        //            int rotatedR1Pos;
     722        //            if (settings.AnalyzeKey)
     723        //                // rotate the fast rotor with the ring
     724        //                rotatedR1Pos = (r1pos + (i - 1)) % settings.Alphabet.Length;
     725        //            else
     726        //                rotatedR1Pos = r1pos;
     727
     728
     729        //            string result = core.Encrypt(rotatedR1Pos, r2pos, r3pos, 0, text);
     730
     731        //            double newIC = calculateIC(result);
     732
     733        //            if (newIC > enigmaConfig.IC)
     734        //            {
     735        //                //better value, hence update the data
     736        //                enigmaConfig.IC = newIC;
     737        //                enigmaConfig.Ring1 = i;
     738        //                enigmaConfig.Key = settings.Alphabet[r3pos].ToString() + settings.Alphabet[r2pos].ToString() + settings.Alphabet[rotatedR1Pos].ToString();
     739        //            }
     740
     741        //        }
     742
     743        //        // update the current rotor positions (only rotor 1 might have changed)
     744        //        r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
     745
     746        //        // turn middle rotor
     747        //        for (int i = 1; i <= settings.Alphabet.Length; i++)
     748        //        {
     749        //            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, i, 1, 1, enigmaConfig.PlugBoard);
     750
     751        //            int rotatedR2Pos;
     752        //            if (settings.AnalyzeKey)
     753        //                // rotate the middle rotor with the ring
     754        //                rotatedR2Pos = (r2pos + (i - 1)) % settings.Alphabet.Length;
     755        //            else
     756        //                rotatedR2Pos = r2pos;
     757
     758        //            string result = core.Encrypt(r1pos, rotatedR2Pos, r3pos, 0, text);
     759
     760        //            double newIC = calculateIC(result);
     761
     762        //            if (newIC > enigmaConfig.IC)
     763        //            {
     764        //                //better value, hence update the data
     765        //                enigmaConfig.IC = newIC;
     766        //                enigmaConfig.Ring2 = i;
     767        //                enigmaConfig.Key = settings.Alphabet[r3pos].ToString() + settings.Alphabet[rotatedR2Pos].ToString() + settings.Alphabet[r1pos].ToString();
     768        //            }
     769        //        }
     770        //    }
     771        //    else
     772        //    {
     773        //        // in case the key is fixed, we search all combinations, i.e. 26*26*26
     774        //        for (int i = 1; i <= settings.Alphabet.Length; i++)
     775        //        {
     776        //            for (int j = 1; j <= settings.Alphabet.Length; j++)
     777        //            {
     778        //                for (int k = 1; k <= settings.Alphabet.Length; k++)
     779        //                {
     780        //                    core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, k, j, i, 1, enigmaConfig.PlugBoard);
     781        //                    string result = core.Encrypt(r1pos, r2pos, r3pos, 0, text);
     782        //                    double newIC = calculateIC(result);
     783
     784        //                    if (newIC > enigmaConfig.IC)
     785        //                    {
     786        //                        //better value, hence update the data
     787        //                        enigmaConfig.IC = newIC;
     788        //                        enigmaConfig.Ring1 = k;
     789        //                        enigmaConfig.Ring2 = j;
     790        //                        enigmaConfig.Ring2 = i;
     791        //                        enigmaConfig.Key = settings.Alphabet[r3pos].ToString() + settings.Alphabet[r2pos].ToString() + settings.Alphabet[r1pos].ToString();
     792        //                    }
     793        //                }
     794        //            }
     795        //        }
     796        //    }
     797
     798        //    // print best option
     799        //    string msg = String.Format("ANALYSIS: Best ring setting: {0} | {1},{2},{3} | {4},{5},{6} | {7} | {8}",
     800        //        enigmaConfig.IC.ToString(),
     801        //        (rotorEnum)enigmaConfig.Rotor3, (rotorEnum)enigmaConfig.Rotor2, (rotorEnum)enigmaConfig.Rotor1,
     802        //        enigmaConfig.Ring3.ToString("00"), enigmaConfig.Ring2.ToString("00"), enigmaConfig.Ring1.ToString("00"),
     803        //        enigmaConfig.Key, pB2String(enigmaConfig.PlugBoard));
     804        //    LogMessage(msg, NotificationLevel.Info);
     805
     806        //}
     807
     808        //private void analyzePlugs(analysisConfigSettings enigmaConfig, int maxPlugs, string text)
     809        //{
     810        //    string tmp;
     811        //    bool plugFound = false;
     812        //    int trials = 0;
     813
     814        //    for (int n = 0; n < maxPlugs; n++)
     815        //    {
     816
     817        //        //LogMessage(String.Format("ANALYSIS: ====> Stage 3.{0} - Searching plugs <====",(n+1)), NotificationLevel.Info);
     818
     819        //        tmp = enigmaConfig.PlugBoard;
     820        //        plugFound = false;
     821
     822        //        for (int i = 0; i < settings.Alphabet.Length; i++)
     823        //        {
     824        //            for (int j = i + 1; j < settings.Alphabet.Length; j++)
     825        //            {
     826        //                //create a "clean" plugboard
     827        //                StringBuilder plugboard = new StringBuilder(tmp);
     828
     829        //                //if both selected letters are pluged, ignore them
     830        //                if (plugboard[i] != settings.Alphabet[i] && plugboard[j] != settings.Alphabet[j])
     831        //                    continue;
     832                       
     833        //                if (plugboard[i] != settings.Alphabet[i])
     834        //                {
     835        //                    plugFound = plugFound | resolvePlugConflict(i, j, enigmaConfig, plugboard.ToString(), text);
     836        //                    trials += 3;
     837        //                    continue;
     838        //                }
     839
     840        //                if (plugboard[j] != settings.Alphabet[j])
     841        //                {
     842        //                    plugFound = plugFound | resolvePlugConflict(j, i, enigmaConfig, plugboard.ToString(), text);
     843        //                    trials += 3;
     844        //                    continue;
     845        //                }
     846
     847        //                //swap i with j
     848        //                plugboard[i] = settings.Alphabet[j];
     849        //                plugboard[j] = settings.Alphabet[i];
     850
     851        //                core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, 1, 1, plugboard.ToString());
     852
     853
     854        //                int r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
     855        //                int r2pos = settings.Alphabet.IndexOf(enigmaConfig.Key[1]);
     856        //                int r3pos = settings.Alphabet.IndexOf(enigmaConfig.Key[0]);
     857        //                string result = core.Encrypt(r1pos, r2pos, r3pos, 0, text);
     858
     859        //                double newIC = calculateIC(result);
     860        //                trials++;
     861
     862        //                if (newIC > enigmaConfig.IC)
     863        //                {
     864        //                    enigmaConfig.IC = newIC;
     865        //                    enigmaConfig.PlugBoard = plugboard.ToString();
     866        //                    plugFound = true;
     867        //                }
     868        //            }
     869        //        }
     870
     871
     872        //        string msg = String.Format("ANALYSIS: Plugs setting in round {0} after {1} trials: {2} | {3},{4},{5} | {6},{7},{8} | {9} | {10}",
     873        //            (n+1),trials, enigmaConfig.IC.ToString(),
     874        //            (rotorEnum)enigmaConfig.Rotor3, (rotorEnum)enigmaConfig.Rotor2, (rotorEnum)enigmaConfig.Rotor1,
     875        //            enigmaConfig.Ring3, enigmaConfig.Ring2, enigmaConfig.Ring1,
     876        //            enigmaConfig.Key, pB2String(enigmaConfig.PlugBoard));
     877        //        LogMessage(msg, NotificationLevel.Info);
     878
     879        //        // no plug could lead to a better result, hence abort plug search.
     880        //        if (!plugFound)
     881        //            break;
     882        //    }
     883        //}
     884
     885        //private bool resolvePlugConflict(int conflictLetterPos, int otherLetterPos, analysisConfigSettings enigmaConfig, string unmodifiedPlugboard, string text)
     886        //{
     887        //    bool found = false;
     888
     889        //    int pluggedLetterPos = settings.Alphabet.IndexOf(unmodifiedPlugboard[conflictLetterPos]);
     890
     891
     892        //    // plug otherLetter together with pluggedLetter and restore the coflictLetter
     893        //    StringBuilder o2pPlugPlugboard = new StringBuilder(unmodifiedPlugboard);
     894        //    o2pPlugPlugboard[conflictLetterPos] = settings.Alphabet[conflictLetterPos]; // restore conflictLetter
     895        //    o2pPlugPlugboard[otherLetterPos] = settings.Alphabet[pluggedLetterPos];     // swap other with
     896        //    o2pPlugPlugboard[pluggedLetterPos] = settings.Alphabet[otherLetterPos];     // plugged
     897
     898
     899        //    // plug conflictLetter with otherLetter and restore pluggedLetter one
     900        //    StringBuilder c2oPlugboard = new StringBuilder(unmodifiedPlugboard);
     901        //    c2oPlugboard[pluggedLetterPos] = settings.Alphabet[pluggedLetterPos]; // restore pluggedLetter
     902        //    c2oPlugboard[conflictLetterPos] = settings.Alphabet[otherLetterPos];  // swap conflictLetter
     903        //    c2oPlugboard[otherLetterPos] = settings.Alphabet[conflictLetterPos];  // with otherLetter
     904
     905
     906        //    // now we habe three different plug-posibilities and need to determine
     907        //    // the best one, which remains set, hence we do 3 trial encryptions
     908           
     909
     910        //    // get the current key
     911        //    int r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
     912        //    int r2pos = settings.Alphabet.IndexOf(enigmaConfig.Key[1]);
     913        //    int r3pos = settings.Alphabet.IndexOf(enigmaConfig.Key[0]);
     914
     915
     916        //    // start with the unmodified
     917        //    core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, unmodifiedPlugboard);
     918        //    double unmodifiedIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     919
     920        //    // now o2p
     921        //    core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, o2pPlugPlugboard.ToString());
     922        //    double o2pIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     923
     924        //    // now c2o
     925        //    core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, c2oPlugboard.ToString());
     926        //    double c2oIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     927
     928        //    string bestPlugBoard = enigmaConfig.PlugBoard;
     929        //    double newIC;
     930
     931        //    if (c2oIC > unmodifiedIC)
     932        //    {
     933        //        if (c2oIC > o2pIC)
     934        //        {
     935        //            bestPlugBoard = c2oPlugboard.ToString();
     936        //            newIC = c2oIC;
     937        //        }
     938        //        else
     939        //        {
     940        //            bestPlugBoard = o2pPlugPlugboard.ToString();
     941        //            newIC = o2pIC;
     942        //        }
     943        //    }
     944        //    else
     945        //    {
     946        //        if (unmodifiedIC > o2pIC)
     947        //        {
     948        //            bestPlugBoard = unmodifiedPlugboard;
     949        //            newIC = unmodifiedIC;
     950        //        }
     951        //        else
     952        //        {
     953        //            bestPlugBoard = o2pPlugPlugboard.ToString();
     954        //            newIC = o2pIC;
     955        //        }
     956        //    }
     957
     958
     959        //    if (newIC > enigmaConfig.IC)
     960        //    {
     961        //        enigmaConfig.IC = newIC;
     962        //        enigmaConfig.PlugBoard = bestPlugBoard;
     963        //        found = true;
     964        //    }
     965
     966        //    //string msg = String.Format("ANALYSIS PlUG CONFLICT: Unmodified [{0}] => {1}; Variant A [{2}] => {3}; Variant B[{4}] => {5} || Selected [{6}]",
     967        //    //    pB2String(unmodifiedPlugboard), unmodifiedIC,
     968        //    //    pB2String(c2oPlugboard.ToString()), c2oIC,
     969        //    //    pB2String(o2pPlugPlugboard.ToString()), o2pIC,
     970        //    //    pB2String(bestPlugBoard));
     971
     972        //    //LogMessage(msg, NotificationLevel.Info);
     973
     974        //    return found;
     975        //}
     976
     977        #endregion
     978
     979        #region Encryption/Decryption
     980
     981        //private string crypt()
     982        //{
     983
     984        //    DateTime start = DateTime.Now;
     985
     986        //    configureEnimga();
     987
     988        //    StringBuilder output = new StringBuilder("");
     989        //    int i = 0;
     990        //    char resultChar = '?';
     991        //    bool wasUpperCase = false;
     992
     993        //    // re-set the key to initial value..
     994        //    //settings.Key = initialKey;
     995           
     996
     997
     998        //    // now process each letter
     999        //    foreach (char c in inputString.ToCharArray())
     1000        //    {
     1001        //        if (settings.Action == 0) EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(i++, inputString.Length));
     1002
     1003        //        wasUpperCase = char.IsUpper(c);
     1004        //        char upperC = char.ToUpper(c);
     1005
     1006        //        if (settings.Alphabet.Contains(upperC))
     1007        //        {
     1008        //            resultChar = enigmacrypt(upperC);
     1009
     1010        //        }
     1011        //        else
     1012        //        {
     1013        //            switch (settings.UnknownSymbolHandling)
     1014        //            {
     1015        //                case 0: // ignore
     1016        //                    resultChar = c;
     1017        //                    break;
     1018        //                case 1: // remove
     1019        //                    continue;
     1020        //                case 2: // replace by X
     1021        //                    resultChar = enigmacrypt('X');
     1022        //                    break;
     1023        //            }
     1024        //        }
     1025
     1026
     1027        //        // case handling
     1028        //        switch (settings.CaseHandling)
     1029        //        {
     1030        //            case 0: // preserve
     1031        //                if (wasUpperCase)
     1032        //                    resultChar = char.ToUpper(resultChar);
     1033        //                else
     1034        //                    resultChar = char.ToLower(resultChar);
     1035        //                break;
     1036        //            case 1: // upper
     1037        //                resultChar = char.ToUpper(resultChar);
     1038        //                break;
     1039        //            case 2: // lower
     1040        //                resultChar = char.ToLower(resultChar);
     1041        //                break;
     1042        //        }
     1043
     1044
     1045        //        // append the calculated value to the output
     1046        //        output.Append(resultChar);
     1047        //    }
     1048
     1049        //    procTime = DateTime.Now.Subtract(start);
     1050
     1051        //    return output.ToString();
     1052        //}
     1053
     1054        //private void configureEnimga()
     1055        //{
     1056        //    // set some helper variables
     1057        //    A = settings.Alphabet + settings.Alphabet + settings.Alphabet;
     1058        //    aLength = settings.Alphabet.Length;
     1059
     1060        //    // prepare the current string for the forward substitution. We use a the string 3-times, since this saves some alphabet wrap-arround checking
     1061        //    rotor1For = rotors[settings.Model, settings.Rotor1] + rotors[settings.Model, settings.Rotor1] + rotors[settings.Model, settings.Rotor1];
     1062        //    rotor2For = rotors[settings.Model, settings.Rotor2] + rotors[settings.Model, settings.Rotor2] + rotors[settings.Model, settings.Rotor2];
     1063        //    rotor3For = rotors[settings.Model, settings.Rotor3] + rotors[settings.Model, settings.Rotor3] + rotors[settings.Model, settings.Rotor3];
     1064        //    if (settings.Rotor4 < 8)
     1065        //    {
     1066        //        rotor4For = rotors[settings.Model, settings.Rotor4] + rotors[settings.Model, settings.Rotor4] + rotors[settings.Model, settings.Rotor4];
     1067        //    }
     1068
     1069
     1070        //    if (settings.Model > 0) // the Enigma A/B did not have a reflector, hence there is no reverse substitution
     1071        //    {
     1072        //        // prepare the current string for the reflector
     1073        //        reflector = reflectors[settings.Model, settings.Reflector] + reflectors[settings.Model, settings.Reflector] + reflectors[settings.Model, settings.Reflector];
     1074
     1075        //        // prepare the current string for the reverse substitution.
     1076        //        rotor1Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor1]);
     1077        //        rotor1Rev += rotor1Rev + rotor1Rev;
     1078        //        rotor2Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor2]);
     1079        //        rotor2Rev += rotor2Rev + rotor2Rev;
     1080        //        rotor3Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor3]);
     1081        //        rotor3Rev += rotor3Rev + rotor3Rev;
     1082        //        if (settings.Rotor4 < 8)
     1083        //        {
     1084        //            rotor4Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor4]);
     1085        //            rotor4Rev += rotor4Rev + rotor4Rev;
     1086        //        }
     1087        //    }
     1088        //    // configure rotor notches
     1089        //    rotor1notches = notches[settings.Rotor1];
     1090        //    rotor2notches = notches[settings.Rotor2];
     1091        //    rotor3notches = notches[settings.Rotor3];
     1092
     1093
     1094        //    //retrieve the current key from the settings           
     1095        //    //currentKey[3] = settings.Key[settings.Key.Length - 1];
     1096        //    //currentKey[2] = settings.Key[settings.Key.Length - 2];
     1097        //    //currentKey[1] = settings.Key[settings.Key.Length - 3];
     1098        //    //if (settings.Key.Length == 4) currentKey[0] = settings.Key[settings.Key.Length - 4];
     1099        //}
     1100
     1101        //private char enigmacrypt(char keyPressed)
     1102        //{
     1103        //    //1. Substitution with plugboard
     1104        //    char entrySubst = this.settings.PlugBoard(keyPressed);
     1105
     1106        //    //2. Spindle substitution
     1107        //    char spindleSubst = enigmaSpindle(entrySubst);
     1108
     1109        //    //3. Substitution with plugboard
     1110        //    return this.settings.PlugBoard(spindleSubst);
     1111        //}
     1112
     1113        //private char enigmaSpindle(char entrySubst)
     1114        //{
     1115
     1116        //    char ch = entrySubst;
     1117
     1118
     1119        //    // get the position of each rotor           
     1120        //    int rotor1Pos = settings.Alphabet.IndexOf(currentKey[3]);
     1121        //    int rotor2Pos = settings.Alphabet.IndexOf(currentKey[2]);
     1122        //    int rotor3Pos = settings.Alphabet.IndexOf(currentKey[1]);
     1123        //    int rotor4Pos = settings.Alphabet.IndexOf(currentKey[0]);
     1124
     1125
     1126        //    //check notches and update the rotor position
     1127        //    foreach (char n in rotor1notches)
     1128        //    {
     1129        //        if (n == currentKey[3]) rotor2Pos = (rotor2Pos + 1) % aLength;
     1130        //    }
     1131
     1132        //    foreach (char n in rotor2notches)
     1133        //    {
     1134        //        if (n == currentKey[2]) rotor3Pos = (rotor3Pos + 1) % aLength;
     1135        //    }
     1136
     1137        //    foreach (char n in rotor3notches)
     1138        //    {
     1139        //        if (n == currentKey[1]) rotor4Pos = (rotor4Pos + 1) % aLength;
     1140        //    }
     1141
     1142        //    rotor1Pos = (rotor1Pos + 1) % aLength;
     1143
     1144        //    currentKey[3] = A[rotor1Pos];
     1145        //    currentKey[2] = A[rotor2Pos];
     1146        //    currentKey[1] = A[rotor3Pos];
     1147        //    currentKey[0] = A[rotor4Pos];
     1148
     1149        //    // write back the updated rotor settings
     1150        //    //settings.Key = new string(currentKey);
     1151
     1152        //    //add the ring-offset
     1153        //    rotor1Pos = (aLength + rotor1Pos - (settings.Ring1 - 1)) % aLength;
     1154        //    rotor2Pos = (aLength + rotor2Pos - (settings.Ring2 - 1)) % aLength;
     1155        //    rotor3Pos = (aLength + rotor3Pos - (settings.Ring3 - 1)) % aLength;
     1156
     1157        //    // now do the substitution
     1158        //    ch = A[aLength + A.IndexOf(rotor1For[aLength + A.IndexOf(ch) + rotor1Pos]) - rotor1Pos];
     1159        //    ch = A[aLength + A.IndexOf(rotor2For[aLength + A.IndexOf(ch) + rotor2Pos]) - rotor2Pos];
     1160        //    ch = A[aLength + A.IndexOf(rotor3For[aLength + A.IndexOf(ch) + rotor3Pos]) - rotor3Pos];
     1161        //    ch = reflector[aLength + A.IndexOf(ch)];
     1162        //    ch = A[aLength + A.IndexOf(rotor3Rev[aLength + A.IndexOf(ch) + rotor3Pos]) - rotor3Pos];
     1163        //    ch = A[aLength + A.IndexOf(rotor2Rev[aLength + A.IndexOf(ch) + rotor2Pos]) - rotor2Pos];
     1164        //    ch = A[aLength + A.IndexOf(rotor1Rev[aLength + A.IndexOf(ch) + rotor1Pos]) - rotor1Pos];
     1165
     1166        //    return ch;
     1167        //}
     1168
     1169        //private string generateReverseSubst(string p)
     1170        //{
     1171        //    char[] result = new char[aLength];
     1172
     1173        //    for (int i = 0; i < aLength; i++)
     1174        //    {
     1175        //        result[i] = settings.Alphabet[p.IndexOf(settings.Alphabet[i])];
     1176        //    }
     1177
     1178        //    return new string(result);
     1179        //}
     1180
     1181        #endregion
     1182
     1183        #endregion
     1184
    3421185        #region Contstructor
    3431186
     
    3451188        {
    3461189            this.settings = new EnigmaSettings();
     1190            this.core = new EnigmaCore(this);
     1191            this.analyzer = new EnigmaAnalyzer(this);
     1192            this.analyzer.OnIntermediateResult += new EventHandler<IntermediateResultEventArgs>(analyzer_OnIntermediateResult);
    3471193        }
    3481194
     
    3511197        #region Events
    3521198
     1199#pragma warning disable 67
    3531200        public event StatusChangedEventHandler OnPluginStatusChanged;
     1201#pragma warning restore
    3541202        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
    3551203        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
     
    4171265            }
    4181266
     1267            // remember the current key-setting, in order to restore on stop
     1268            savedKey = settings.Key;
     1269
    4191270            //configure the enigma
    420             configureEnimga();
    421 
    422             initialKey = settings.Key;
     1271            core.setInternalConfig(settings.Rotor1, settings.Rotor2, settings.Rotor3, settings.Rotor4,
     1272                        settings.Reflector, settings.Ring1, settings.Ring2, settings.Ring3, settings.Ring4,
     1273                        settings.PlugBoard);
     1274           
     1275            // re-set the stop-flag
     1276            //stop = false;
    4231277        }
    4241278
    4251279        public void Execute()
    4261280        {
     1281            if (inputString == null)
     1282                return;
     1283
    4271284
    4281285            if (settings.Model != 3)
    4291286            {
    430                 EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("This simulator is work in progress. As of right now only Enigma I is supported!!", this, NotificationLevel.Error));
     1287                LogMessage("This simulator is work in progress. As of right now only Enigma I is supported!!", NotificationLevel.Error);
    4311288                return;
    4321289            }
    4331290
    434             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("Enigma execution started...", this, NotificationLevel.Info));
    435 
    436             if (inputString != null)
     1291           
     1292
     1293            switch (settings.Action)
    4371294            {
    438                 StringBuilder output = new StringBuilder("");
    439                 int i = 0;
    440                 char resultChar = '?';
    441                 bool wasUpperCase = false;
    442 
    443                 // re-set the key to initial value..
    444                 settings.Key = initialKey;
    445 
    446                 // now process each letter
    447                 foreach (char c in inputString.ToCharArray())
    448                 {
    449                     EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(i++, inputString.Length));
    450 
    451                     wasUpperCase = char.IsUpper(c);
    452                     char upperC = char.ToUpper(c);
    453 
    454                     if (settings.Alphabet.Contains(upperC))
    455                     {
    456                         resultChar = enigmacrypt(upperC);
    457                            
    458                     }
    459                     else
    460                     {
    461                         switch (settings.UnknownSymbolHandling)
    462                         {
    463                             case 0: // ignore
    464                                 resultChar = c;
    465                                 break;
    466                             case 1: // remove
    467                                 continue;
    468                             case 2: // replace by X
    469                                 resultChar = enigmacrypt('X');
    470                                 break;
    471                         }
    472                     }
    473 
    474 
    475                     // case handling
    476                     switch (settings.CaseHandling)
    477                     {
    478                         case 0: // preserve
    479                             if (wasUpperCase)
    480                                 resultChar = char.ToUpper(resultChar);
    481                             else
    482                                 resultChar = char.ToLower(resultChar);
    483                             break;
    484                         case 1: // upper
    485                             resultChar = char.ToUpper(resultChar);
    486                             break;
    487                         case 2: // lower
    488                             resultChar = char.ToLower(resultChar);
    489                             break;
    490                     }
    491 
    492 
    493                     // append the calculated value to the output
    494                     output.Append(resultChar);
    495                 }
    496 
    497                 outputString = output.ToString();
    498                 EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(100, 100));
    499                 OnPropertyChanged("OutputString");
     1295                case 0:
     1296                    LogMessage("Enigma encryption/decryption started...", NotificationLevel.Info);
     1297
     1298                    // re-set the key, in case we get executed again during single run
     1299                    settings.Key = savedKey;
     1300
     1301                    // do the encryption
     1302                    outputString = FormattedEncrypt(settings.Alphabet.IndexOf(settings.Key[2]),
     1303                        settings.Alphabet.IndexOf(settings.Key[1]),
     1304                        settings.Alphabet.IndexOf(settings.Key[0]),
     1305                        0, inputString);
     1306
     1307
     1308                    LogMessage("Enigma encryption done. The resulting index of coincidences is " + analyzer.IndexOfCoincidences(outputString), NotificationLevel.Info);
     1309
     1310                    // "fire" the output
     1311                    OnPropertyChanged("OutputString");
     1312                    break;
     1313                case 1:
     1314                    LogMessage("Enigma analysis starting ...", NotificationLevel.Info);
     1315
     1316                    //prepare for analysis
     1317                    LogMessage("ANALYSIS: Preformatting text...", NotificationLevel.Debug);
     1318                    string preformatedText = preFormatInput(inputString);
     1319
     1320                    // perform the analysis
     1321                    outputString = postFormatOutput(analyzer.Analyze(preformatedText));
     1322                    OnPropertyChanged("OutputString");
     1323
     1324                    ShowProgress(1000, 1000);
     1325                   
     1326                    // old version
     1327                    //runAnalysis(inputString);
     1328                    break;
     1329                default:
     1330                    break;
    5001331            }
    501         }
    502 
    503         private void configureEnimga()
    504         {
    505             // set some helper variables
    506             A = settings.Alphabet + settings.Alphabet + settings.Alphabet;
    507             aLength = settings.Alphabet.Length;
    508 
    509             // prepare the current string for the forward substitution. We use a the string 3-times, since this saves some alphabet wrap-arround checking
    510             rotor1For = rotors[settings.Model, settings.Rotor1] + rotors[settings.Model, settings.Rotor1] + rotors[settings.Model, settings.Rotor1];
    511             rotor2For = rotors[settings.Model, settings.Rotor2] + rotors[settings.Model, settings.Rotor2] + rotors[settings.Model, settings.Rotor2];
    512             rotor3For = rotors[settings.Model, settings.Rotor3] + rotors[settings.Model, settings.Rotor3] + rotors[settings.Model, settings.Rotor3];
    513             if (settings.Rotor4 < 8)
     1332
     1333        }
     1334
     1335        public void PostExecution()
     1336        {
     1337            LogMessage("Enigma shutting down. Reverting key to inial value!", NotificationLevel.Info);
     1338            if (savedKey.Length > 0)
    5141339            {
    515                 rotor4For = rotors[settings.Model, settings.Rotor4] + rotors[settings.Model, settings.Rotor4] + rotors[settings.Model, settings.Rotor4];
     1340                settings.Key = savedKey; // re-set the key
    5161341            }
    5171342           
    518 
    519             if (settings.Model > 0) // the Enigma A/B did not have a reflector, hence there is no reverse substitution
     1343        }
     1344
     1345        public void Pause()
     1346        {
     1347            LogMessage("The \"Pause\"-Feature is not implemented!", NotificationLevel.Warning);
     1348        }
     1349
     1350        public void Stop()
     1351        {
     1352            LogMessage("Enigma stopped", NotificationLevel.Info);
     1353            //stop = true;
     1354            analyzer.StopAnalysis();
     1355        }
     1356
     1357        public void Initialize()
     1358        {
     1359            LogMessage("Initialize", NotificationLevel.Debug);
     1360        }
     1361
     1362        public void Dispose()
     1363        {
     1364            LogMessage("Dispose", NotificationLevel.Debug);
     1365        }
     1366
     1367
     1368
     1369        /// <summary>
     1370        /// Logs a message to the Cryptool console
     1371        /// </summary>
     1372        public void LogMessage(string msg, NotificationLevel level)
     1373        {
     1374            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(msg, this, level));
     1375        }
     1376
     1377        /// <summary>
     1378        /// Sets the progress bar for this plugin
     1379        /// </summary>
     1380        /// <param name="val"></param>
     1381        /// <param name="max"></param>
     1382        public void ShowProgress(double val, double max)
     1383        {
     1384            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(val, max));
     1385        }
     1386
     1387        /// <summary>
     1388        /// Returns a formated string with all plugs from a given substitution string
     1389        /// This method should be move to some more adequate place
     1390        /// </summary>
     1391        /// <param name="pb">The substitution string for a plugboard</param>
     1392        /// <returns>A list of plugs</returns>
     1393        public string pB2String(string pb)
     1394        {
     1395            if (pb.Length != settings.Alphabet.Length)
     1396                return "-- no plugs --";
     1397
     1398
     1399            StringBuilder result = new StringBuilder();
     1400
     1401            for (int i = 0; i < settings.Alphabet.Length; i++)
    5201402            {
    521                 // prepare the current string for the reflector
    522                 reflector = reflectors[settings.Model, settings.Reflector] + reflectors[settings.Model, settings.Reflector] + reflectors[settings.Model, settings.Reflector];
    523 
    524                 // prepare the current string for the reverse substitution.
    525                 rotor1Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor1]);
    526                 rotor1Rev += rotor1Rev + rotor1Rev;
    527                 rotor2Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor2]);
    528                 rotor2Rev += rotor2Rev + rotor2Rev;
    529                 rotor3Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor3]);
    530                 rotor3Rev += rotor3Rev + rotor3Rev;
    531                 if (settings.Rotor4 < 8)
     1403                if (settings.Alphabet[i] != pb[i] && !result.ToString().Contains(settings.Alphabet[i]))
    5321404                {
    533                     rotor4Rev = generateReverseSubst(rotors[settings.Model, settings.Rotor4]);
    534                     rotor4Rev += rotor4Rev + rotor4Rev;
     1405                    if (result.Length > 0)
     1406                        result.Append(' ');
     1407
     1408                    result.Append(settings.Alphabet[i].ToString() + pb[i].ToString());
    5351409                }
    5361410            }
    537             // configure rotor notches
    538             rotor1notches = notches[settings.Rotor1];
    539             rotor2notches = notches[settings.Rotor2];
    540             rotor3notches = notches[settings.Rotor3];
    541         }
    542 
    543         private char enigmacrypt(char keyPressed)
    544         {
    545             //1. Substitution with plugboard
    546             char entrySubst = this.settings.PlugBoard(keyPressed);
    547 
    548             //2. Spindle substitution
    549             char spindleSubst = enigmaSpindle(entrySubst);
    550 
    551             //3. Substitution with plugboard
    552             return this.settings.PlugBoard(spindleSubst);
    553         }
    554 
    555         private char enigmaSpindle(char entrySubst)
    556         {
    557 
    558             char ch = entrySubst;
    559            
    560 
    561             // get the position of each rotor
    562             char[] key = settings.Key.ToCharArray();
    563             int rotor4Pos = 0;
    564             if (settings.Model == 4 && key.Length == 4)
    565             {
    566                 // M4 "Shark" uses 4 rotors
    567                 rotor4Pos = settings.Alphabet.IndexOf(key[0]);
    568             }
    569             int rotor1Pos = settings.Alphabet.IndexOf(key[key.Length - 1]);
    570             int rotor2Pos = settings.Alphabet.IndexOf(key[key.Length - 2]);
    571             int rotor3Pos = settings.Alphabet.IndexOf(key[key.Length - 3]);
    572 
    573 
    574             //check notches and update the rotor position
    575             foreach (char n in rotor1notches)
    576             {
    577                 if (n == key[key.Length - 1]) rotor2Pos = (rotor2Pos + 1) % aLength;   
    578             }
    579 
    580             foreach (char n in rotor2notches)
    581             {
    582                 if (n == key[key.Length - 2]) rotor3Pos = (rotor3Pos + 1) % aLength;
    583             }
    584 
    585             foreach (char n in rotor3notches)
    586             {
    587                 if (n == key[key.Length - 3]) rotor4Pos = (rotor4Pos + 1) % aLength;
    588             }
    589 
    590             rotor1Pos = (rotor1Pos + 1) % aLength;
    591 
    592             key[key.Length - 1] = A[rotor1Pos];
    593             key[key.Length - 2] = A[rotor2Pos];
    594             key[key.Length - 3] = A[rotor3Pos];
    595             if (settings.Model == 4 && key.Length == 4) key[0] = A[rotor4Pos];
    596 
    597             // write back the updated rotor settings
    598             settings.Key = new string(key);
    599 
    600             //add the ring-offset
    601             rotor1Pos = (aLength + rotor1Pos - (settings.Ring1 - 1)) % aLength;
    602             rotor2Pos = (aLength + rotor2Pos - (settings.Ring2 - 1)) % aLength;
    603             rotor3Pos = (aLength + rotor3Pos - (settings.Ring3 - 1)) % aLength;
    604 
    605             // now do the substitution
    606             ch = A[aLength + A.IndexOf(rotor1For[aLength + A.IndexOf(ch) + rotor1Pos]) - rotor1Pos];
    607             ch = A[aLength + A.IndexOf(rotor2For[aLength + A.IndexOf(ch) + rotor2Pos]) - rotor2Pos];
    608             ch = A[aLength + A.IndexOf(rotor3For[aLength + A.IndexOf(ch) + rotor3Pos]) - rotor3Pos];
    609             ch = reflector[aLength + A.IndexOf(ch)];
    610             ch = A[aLength + A.IndexOf(rotor3Rev[aLength + A.IndexOf(ch) + rotor3Pos]) - rotor3Pos];
    611             ch = A[aLength + A.IndexOf(rotor2Rev[aLength + A.IndexOf(ch) + rotor2Pos]) - rotor2Pos];
    612             ch = A[aLength + A.IndexOf(rotor1Rev[aLength + A.IndexOf(ch) + rotor1Pos]) - rotor1Pos];
    613 
    614             return ch;
    615         }
    616 
    617         private string generateReverseSubst(string p)
    618         {
    619             char[] result = new char[aLength];
    620 
    621             for (int i = 0; i < aLength; i++)
    622             {
    623                 result[i] = settings.Alphabet[p.IndexOf(settings.Alphabet[i])];
    624             }
    625 
    626             return new string(result);
    627         }
    628 
    629         public void PostExecution()
    630         {
    631             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("Enigma shutting down. Reverting key to inial value!", this, NotificationLevel.Info));
    632             if (initialKey.Length > 0)
    633             {
    634                 settings.Key = initialKey;
    635             }
    636         }
    637 
    638         public void Pause()
    639         {
    640             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("The \"Pause\"-Feature is not implemented!", this, NotificationLevel.Warning));
    641         }
    642 
    643         public void Stop()
    644         {
    645             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("Enigma stopped", this, NotificationLevel.Info));
    646         }
    647 
    648         public void Initialize()
    649         {
    650             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("Initialize", this, NotificationLevel.Debug));
    651         }
    652 
    653         public void Dispose()
    654         {
    655             EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs("Dispose", this, NotificationLevel.Debug));
     1411
     1412            if (result.Length == 0)
     1413                result.Append("-- no plugs --");
     1414
     1415            return result.ToString();
    6561416        }
    6571417
  • trunk/CrypPlugins/Enigma/Enigma.csproj

    r311 r353  
    1919    <DebugSymbols>true</DebugSymbols>
    2020    <DebugType>full</DebugType>
    21     <Optimize>false</Optimize>
     21    <Optimize>true</Optimize>
    2222    <OutputPath>bin\Debug\</OutputPath>
    2323    <DefineConstants>DEBUG;TRACE</DefineConstants>
     
    5858  <ItemGroup>
    5959    <Compile Include="Enigma.cs" />
     60    <Compile Include="EnigmaAnalyzer.cs" />
     61    <Compile Include="EnigmaConstants.cs" />
     62    <Compile Include="EnigmaCore.cs" />
     63    <Compile Include="EnigmaEnums.cs" />
    6064    <Compile Include="EnigmaSettings.cs" />
    6165    <Compile Include="Properties\AssemblyInfo.cs" />
  • trunk/CrypPlugins/Enigma/EnigmaSettings.cs

    r317 r353  
    237237        private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    238238
     239        private int maxSearchedPlugs = 10;
     240        private bool analyzeRotors = true;
     241        private bool analyzeKey = true;
     242        private bool analyzeRings = true;
     243        private bool analyzePlugs = true;
     244        private bool analysisUseRotorI = true;
     245        private bool analysisUseRotorII = true;
     246        private bool analysisUseRotorIII = true;
     247        private bool analysisUseRotorIV = true;
     248        private bool analysisUseRotorV = true;
     249        private bool analysisUseRotorVI = true;
     250        private bool analysisUseRotorVII = true;
     251        private bool analysisUseRotorVIII = true;
     252
    239253        private int rotor1 = 0;
    240254        private int rotor2 = 1;
     
    309323        #region Public Methods
    310324
    311         public char PlugBoard(char c)
    312         {
    313             return this.plugBoard[alphabet.IndexOf(c)];
     325       
     326
     327        public void resetPlugBoard()
     328        {
     329            plugBoard = new StringBuilder("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
     330            OnPropertyChanged("PlugBoardDisplay");
    314331        }
    315332
     
    320337        public EnigmaSettings()
    321338        {
    322             actionStrings.Add("Encrypt/Decrypt");
     339            actionStrings.Add("Encrypt/Decrypt"); actionStrings.Add("Analyze");
    323340            reflectorStrings.Add("UKW A"); reflectorStrings.Add("UKW B (2. November 1937)"); reflectorStrings.Add("UKW C (since 1940/41)");
    324341            rotorAStrings.Add("I (since 1930)"); rotorAStrings.Add("II (since 1930)"); rotorAStrings.Add("III (since 1930)");
     
    344361        [ContextMenu("Enigma model", "Please select which Enigma model you want to use. This settings influences available rotors and their inner cabling.",
    345362            0, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, null,
    346             new string[] { "Commercial Enigma A/B - since 1924", "Commercial Enigma D", "Reichsbahn (Rocket) - since 1941", "Enigma I / M3 / M4", "M4 (Shark)", "K-Model", "G (Defense model)" })]
     363            new string[] { "Commercial Enigma A/B - since 1924", "Commercial Enigma D", "Reichsbahn (Rocket) - since 1941", "Enigma I / M3", "M4 (Shark)", "K-Model", "G (Defense model)" })]
    347364        [TaskPane("Enigma model", "Please select which Enigma model you want to use. This settings influences the available rotors and their inner cabling.",
    348365            null, 0, false, DisplayLevel.Beginner, ControlType.ComboBox,
    349             new string[] { "Enigma A/B - since 1924", "Enigma D", "Reichsbahn (Rocket) - since 1941", "Enigma I / M3 / M4", "M4 (Shark)", "K-Model", "G (Defense model)" })]
     366            new string[] { "Enigma A/B - since 1924", "Enigma D", "Reichsbahn (Rocket) - since 1941", "Enigma I / M3", "M4 (Shark)", "K-Model", "G (Defense model)" })]
    350367        public int Model
    351368        {
     
    383400                        break;
    384401                    case 3: // Enigma I / M3
    385                         actionStrings.Clear(); actionStrings.Add("Encrypt / Decrypt"); action = 0; OnPropertyChanged("Action");
     402                        actionStrings.Clear(); actionStrings.Add("Encrypt / Decrypt"); actionStrings.Add("Analyze"); action = 0; OnPropertyChanged("Action");
    386403                        if (key.Length > 3) key = key.Remove(0, 1); OnPropertyChanged("Key");
    387404                        rotorAStrings.Clear(); rotorAStrings.Add("I (since 1930)"); rotorAStrings.Add("II (since 1930)"); rotorAStrings.Add("III (since 1930)");
     
    506523        #endregion
    507524
     525        #region Analysis options
     526
     527        [TaskPane("Analyze key (initial rotor pos.)", "If checked, the analysis tries to detect the correct key. If unchecked, the value from \"Key\" is used.",
     528            "Analysis options", 6, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     529        public bool AnalyzeKey
     530        {
     531            get { return analyzeKey; }
     532            set
     533            {
     534                if (value != analyzeKey)
     535                {
     536                    analyzeKey = value;
     537                    hasChanges = true;
     538                    OnPropertyChanged("AnalyzeKey");
     539                }
     540            }
     541        }
     542
     543        [TaskPane("Analyze used rotors", "If checked, the analysis tries to detect the correct rotors and their positions. If unchecked, the values from the rotor settings are used.",
     544            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     545        public bool AnalyzeRotors
     546        {
     547            get { return analyzeRotors; }
     548            set
     549            {
     550                if (value != analyzeRotors)
     551                {
     552                    analyzeRotors = value;
     553                    hasChanges = true;
     554                    OnPropertyChanged("AnalyzeRotors");
     555                }
     556            }
     557        }
     558
     559        [SettingsFormat(1,"Normal","Normal")]
     560        [TaskPane("Include rotor I", "Check if rotor I should be included when analyzing rotors.",
     561            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     562        public bool AnalysisUseRotorI
     563        {
     564            get { return analysisUseRotorI; }
     565            set
     566            {
     567                if (value != analysisUseRotorI)
     568                {
     569                    analysisUseRotorI = value;
     570                    hasChanges = true;
     571                    OnPropertyChanged("AnalysisUseRotorI");
     572                }
     573            }
     574        }
     575
     576        [SettingsFormat(1, "Normal", "Normal")]
     577        [TaskPane("Include rotor II", "Check if rotor II should be included when analyzing rotors.",
     578            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     579        public bool AnalysisUseRotorII
     580        {
     581            get { return analysisUseRotorII; }
     582            set
     583            {
     584                if (value != analysisUseRotorII)
     585                {
     586                    analysisUseRotorII = value;
     587                    hasChanges = true;
     588                    OnPropertyChanged("AnalysisUseRotorII");
     589                }
     590            }
     591        }
     592
     593        [SettingsFormat(1, "Normal", "Normal")]
     594        [TaskPane("Include rotor III", "Check if rotor III should be included when analyzing rotors.",
     595            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     596        public bool AnalysisUseRotorIII
     597        {
     598            get { return analysisUseRotorIII; }
     599            set
     600            {
     601                if (value != analysisUseRotorIII)
     602                {
     603                    analysisUseRotorIII = value;
     604                    hasChanges = true;
     605                    OnPropertyChanged("AnalysisUseRotorIII");
     606                }
     607            }
     608        }
     609
     610        [SettingsFormat(1, "Normal", "Normal")]
     611        [TaskPane("Include rotor IV", "Check if rotor IV should be included when analyzing rotors.",
     612            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     613        public bool AnalysisUseRotorIV
     614        {
     615            get { return analysisUseRotorIV; }
     616            set
     617            {
     618                if (value != analysisUseRotorIV)
     619                {
     620                    analysisUseRotorIV = value;
     621                    hasChanges = true;
     622                    OnPropertyChanged("AnalysisUseRotorIV");
     623                }
     624            }
     625        }
     626
     627
     628        [SettingsFormat(1, "Normal", "Normal")]
     629        [TaskPane("Include rotor V", "Check if rotor V should be included when analyzing rotors.",
     630            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     631        public bool AnalysisUseRotorV
     632        {
     633            get { return analysisUseRotorV; }
     634            set
     635            {
     636                if (value != analysisUseRotorV)
     637                {
     638                    analysisUseRotorV = value;
     639                    hasChanges = true;
     640                    OnPropertyChanged("AnalysisUseRotorV");
     641                }
     642            }
     643        }
     644
     645        [SettingsFormat(1, "Normal", "Normal")]
     646        [TaskPane("Include rotor VI", "Check if rotor VI should be included when analyzing rotors.",
     647            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     648        public bool AnalysisUseRotorVI
     649        {
     650            get { return analysisUseRotorVI; }
     651            set
     652            {
     653                if (value != analysisUseRotorVI)
     654                {
     655                    analysisUseRotorVI = value;
     656                    hasChanges = true;
     657                    OnPropertyChanged("AnalysisUseRotorVI");
     658                }
     659            }
     660        }
     661
     662
     663        [SettingsFormat(1, "Normal", "Normal")]
     664        [TaskPane("Include rotor VII", "Check if rotor VII should be included when analyzing rotors.",
     665            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     666        public bool AnalysisUseRotorVII
     667        {
     668            get { return analysisUseRotorVII; }
     669            set
     670            {
     671                if (value != analysisUseRotorVII)
     672                {
     673                    analysisUseRotorVII = value;
     674                    hasChanges = true;
     675                    OnPropertyChanged("AnalysisUseRotorVII");
     676                }
     677            }
     678        }
     679
     680
     681        [SettingsFormat(1, "Normal", "Normal")]
     682        [TaskPane("Include rotor VIII", "Check if rotor VIII should be included when analyzing rotors.",
     683            "Analysis options", 7, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     684        public bool AnalysisUseRotorVIII
     685        {
     686            get { return analysisUseRotorVIII; }
     687            set
     688            {
     689                if (value != analysisUseRotorVIII)
     690                {
     691                    analysisUseRotorVIII = value;
     692                    hasChanges = true;
     693                    OnPropertyChanged("AnalysisUseRotorVIII");
     694                }
     695            }
     696        }
     697
     698
     699        [TaskPane("Analyze rings settings", "If checked, the analysis tries to detect the correct rings settings. If unchecked, the values from the ring settings are used.",
     700            "Analysis options", 8, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     701        public bool AnalyzeRings
     702        {
     703            get { return analyzeRings; }
     704            set
     705            {
     706                if (value != analyzeRings)
     707                {
     708                    analyzeRings = value;
     709                    hasChanges = true;
     710                    OnPropertyChanged("AnalyzeRings");
     711                }
     712            }
     713        }
     714
     715        [TaskPane("Analyze plugs", "If checked, the analysis tries to detect the correct plug settings. If unchecked, the values from the plugboard are used.",
     716            "Analysis options", 9, false, DisplayLevel.Beginner, ControlType.CheckBox, "", null)]
     717        public bool AnalyzePlugs
     718        {
     719            get { return analyzePlugs; }
     720            set
     721            {
     722                if (value != analyzePlugs)
     723                {
     724                    analyzePlugs = value;
     725                    hasChanges = true;
     726                    OnPropertyChanged("AnalyzePlugs");
     727                }
     728            }
     729        }
     730       
     731        [TaskPane("Max. plugs searched", "Select how many plugs should be searched at most. Note that the search algorithm might return less plugs - this number is just an upper limit",
     732            "Analysis options", 9, false, DisplayLevel.Beginner, ControlType.NumericUpDown, ValidationType.RangeInteger, 1, 26)]
     733        public int MaxSearchedPlugs
     734        {
     735            get { return this.maxSearchedPlugs; }
     736            set
     737            {
     738                if (value != maxSearchedPlugs)
     739                {
     740                    hasChanges = true;
     741                    maxSearchedPlugs = value;
     742                    OnPropertyChanged("MaxSearchedPlugs");
     743                }
     744            }
     745        }
     746
     747        #endregion
     748
    508749        #region Used rotor settings
    509750
     
    694935
    695936        [TaskPane("Plugboard substitution", "Displays the current substitution", "Plugboard", 30, false, DisplayLevel.Beginner, ControlType.TextBoxReadOnly)]
    696         public string PlugBoardDisplay
     937        public string PlugBoard
    697938        {
    698939            get { return plugBoard.ToString(); }
     
    715956        }
    716957
    717 
    718         [TaskPane("A", "Select the letter for connecting this plug.", "Plugboard", 40, false, DisplayLevel.Beginner, ControlType.ComboBox,
     958        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Eins")]
     959        [TaskPane("A=", "Select the letter for connecting this plug.", "Plugboard", 40, false, DisplayLevel.Beginner, ControlType.ComboBox,
    719960            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    720961        public int PlugBoardA
     
    724965        }
    725966
    726         [TaskPane("B", "Select the letter for connecting this plug.", "Plugboard", 41, false, DisplayLevel.Beginner, ControlType.ComboBox,
     967        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Eins")]
     968        [TaskPane("B=", "Select the letter for connecting this plug.", "Plugboard", 41, false, DisplayLevel.Beginner, ControlType.ComboBox,
    727969            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    728970        public int PlugBoardB
     
    732974        }
    733975
    734         [TaskPane("C", "Select the letter for connecting this plug.", "Plugboard", 42, false, DisplayLevel.Beginner, ControlType.ComboBox,
     976        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Eins")]
     977        [TaskPane("C=", "Select the letter for connecting this plug.", "Plugboard", 42, false, DisplayLevel.Beginner, ControlType.ComboBox,
    735978            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    736979        public int PlugBoardC
     
    740983        }
    741984
    742         [TaskPane("D", "Select the letter for connecting this plug.", "Plugboard", 43, false, DisplayLevel.Beginner, ControlType.ComboBox,
     985        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Zwei")]
     986        [TaskPane("D=", "Select the letter for connecting this plug.", "Plugboard", 43, false, DisplayLevel.Beginner, ControlType.ComboBox,
    743987            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    744988        public int PlugBoardD
     
    748992        }
    749993
    750         [TaskPane("E", "Select the letter for connecting this plug.", "Plugboard", 44, false, DisplayLevel.Beginner, ControlType.ComboBox,
     994        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Zwei")]
     995        [TaskPane("E=", "Select the letter for connecting this plug.", "Plugboard", 44, false, DisplayLevel.Beginner, ControlType.ComboBox,
    751996            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    752997        public int PlugBoardE
     
    7561001        }
    7571002
    758         [TaskPane("F", "Select the letter for connecting this plug.", "Plugboard", 45, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1003        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Zwei")]
     1004        [TaskPane("F=", "Select the letter for connecting this plug.", "Plugboard", 45, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7591005            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    7601006        public int PlugBoardF
     
    7641010        }
    7651011
    766         [TaskPane("G", "Select the letter for connecting this plug.", "Plugboard", 46, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1012        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Drei")]
     1013        [TaskPane("G=", "Select the letter for connecting this plug.", "Plugboard", 46, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7671014            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    7681015        public int PlugBoardG
     
    7721019        }
    7731020
    774         [TaskPane("H", "Select the letter for connecting this plug.", "Plugboard", 47, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1021        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Drei")]
     1022        [TaskPane("H=", "Select the letter for connecting this plug.", "Plugboard", 47, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7751023            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    7761024        public int PlugBoardH
     
    7801028        }
    7811029
    782         [TaskPane("I", "Select the letter for connecting this plug.", "Plugboard", 48, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1030        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Drei")]
     1031        [TaskPane("I=", "Select the letter for connecting this plug.", "Plugboard", 48, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7831032            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    7841033        public int PlugBoardI
     
    7881037        }
    7891038
    790         [TaskPane("J", "Select the letter for connecting this plug.", "Plugboard", 49, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1039        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Vier")]
     1040        [TaskPane("J=", "Select the letter for connecting this plug.", "Plugboard", 49, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7911041            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    7921042        public int PlugBoardJ
     
    7961046        }
    7971047
    798         [TaskPane("K", "Select the letter for connecting this plug.", "Plugboard", 50, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1048        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Vier")]
     1049        [TaskPane("K=", "Select the letter for connecting this plug.", "Plugboard", 50, false, DisplayLevel.Beginner, ControlType.ComboBox,
    7991050            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8001051        public int PlugBoardK
     
    8041055        }
    8051056
    806         [TaskPane("L", "Select the letter for connecting this plug.", "Plugboard", 51, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1057        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Vier")]
     1058        [TaskPane("L=", "Select the letter for connecting this plug.", "Plugboard", 51, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8071059            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8081060        public int PlugBoardL
     
    8121064        }
    8131065
    814         [TaskPane("M", "Select the letter for connecting this plug.", "Plugboard", 52, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1066        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Fuenf")]
     1067        [TaskPane("M=", "Select the letter for connecting this plug.", "Plugboard", 52, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8151068            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8161069        public int PlugBoardM
     
    8201073        }
    8211074
    822         [TaskPane("N", "Select the letter for connecting this plug.", "Plugboard", 53, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1075        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Fuenf")]
     1076        [TaskPane("N=", "Select the letter for connecting this plug.", "Plugboard", 53, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8231077            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8241078        public int PlugBoardN
     
    8281082        }
    8291083
    830         [TaskPane("O", "Select the letter for connecting this plug.", "Plugboard", 54, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1084        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Fuenf")]
     1085        [TaskPane("O=", "Select the letter for connecting this plug.", "Plugboard", 54, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8311086            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8321087        public int PlugBoardO
     
    8361091        }
    8371092
    838         [TaskPane("P", "Select the letter for connecting this plug.", "Plugboard", 55, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1093        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sechs")]
     1094        [TaskPane("P=", "Select the letter for connecting this plug.", "Plugboard", 55, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8391095            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8401096        public int PlugBoardP
     
    8441100        }
    8451101
    846         [TaskPane("Q", "Select the letter for connecting this plug.", "Plugboard", 56, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1102        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sechs")]
     1103        [TaskPane("Q=", "Select the letter for connecting this plug.", "Plugboard", 56, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8471104            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8481105        public int PlugBoardQ
     
    8521109        }
    8531110
    854         [TaskPane("R", "Select the letter for connecting this plug.", "Plugboard", 57, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1111        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sechs")]
     1112        [TaskPane("R=", "Select the letter for connecting this plug.", "Plugboard", 57, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8551113            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8561114        public int PlugBoardR
     
    8601118        }
    8611119
    862         [TaskPane("S", "Select the letter for connecting this plug.", "Plugboard", 58, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1120        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sieben")]
     1121        [TaskPane("S=", "Select the letter for connecting this plug.", "Plugboard", 58, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8631122            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8641123        public int PlugBoardS
     
    8681127        }
    8691128
    870         [TaskPane("T", "Select the letter for connecting this plug.", "Plugboard", 59, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1129        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sieben")]
     1130        [TaskPane("T=", "Select the letter for connecting this plug.", "Plugboard", 59, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8711131            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8721132        public int PlugBoardT
     
    8761136        }
    8771137
    878         [TaskPane("U", "Select the letter for connecting this plug.", "Plugboard", 60, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1138        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Sieben")]
     1139        [TaskPane("U=", "Select the letter for connecting this plug.", "Plugboard", 60, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8791140            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8801141        public int PlugBoardU
     
    8841145        }
    8851146
    886         [TaskPane("V", "Select the letter for connecting this plug.", "Plugboard", 61, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1147        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Acht")]
     1148        [TaskPane("V=", "Select the letter for connecting this plug.", "Plugboard", 61, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8871149            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8881150        public int PlugBoardV
     
    8921154        }
    8931155
    894         [TaskPane("W", "Select the letter for connecting this plug.", "Plugboard", 62, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1156        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto","*", "Acht")]
     1157        [TaskPane("W=", "Select the letter for connecting this plug.", "Plugboard", 62, false, DisplayLevel.Beginner, ControlType.ComboBox,
    8951158            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    8961159        public int PlugBoardW
     
    9001163        }
    9011164
    902         [TaskPane("X", "Select the letter for connecting this plug.", "Plugboard", 63, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1165        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal,"Auto","*" ,"Acht")]
     1166        [TaskPane("X=", "Select the letter for connecting this plug.", "Plugboard", 63, false, DisplayLevel.Beginner, ControlType.ComboBox,
    9031167            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    9041168        public int PlugBoardX
     
    9081172        }
    9091173
    910 
    911         [TaskPane("Y", "Select the letter for connecting this plug.", "Plugboard", 64, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1174        [SettingsFormat(0, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Neun")]
     1175        [TaskPane("Y=", "Select the letter for connecting this plug.", "Plugboard", 64, false, DisplayLevel.Beginner, ControlType.ComboBox,
    9121176            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    9131177        public int PlugBoardY
     
    9171181        }
    9181182
    919         [TaskPane("Z", "Select the letter for connecting this plug.", "Plugboard", 65, false, DisplayLevel.Beginner, ControlType.ComboBox,
     1183        [SettingsFormat(1, "Normal", "Normal", "Black", "White", System.Windows.Controls.Orientation.Horizontal, "Auto", "*", "Neun")]
     1184        [TaskPane("Z=", "Select the letter for connecting this plug.", "Plugboard", 65, false, DisplayLevel.Beginner, ControlType.ComboBox,
    9201185            new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" })]
    9211186        public int PlugBoardZ
Note: See TracChangeset for help on using the changeset viewer.