aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs447
1 files changed, 228 insertions, 219 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
index ffc4e84d..0c1aa312 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
@@ -18,8 +18,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB 18 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
19 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) 19 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
20 20
21 private static readonly char[] ColonCharacter = new[] { ':' };
22
23 public CreateOutputFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper) 21 public CreateOutputFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper)
24 { 22 {
25 this.Messaging = messaging; 23 this.Messaging = messaging;
@@ -54,171 +52,174 @@ namespace WixToolset.Core.WindowsInstaller.Bind
54 52
55 private void AddSectionToOutput() 53 private void AddSectionToOutput()
56 { 54 {
55 var cellsByTableAndRowId = new Dictionary<string, List<WixCustomTableCellTuple>>();
56
57 foreach (var tuple in this.Section.Tuples) 57 foreach (var tuple in this.Section.Tuples)
58 { 58 {
59 var unknownTuple = false; 59 var unknownTuple = false;
60 switch (tuple.Definition.Type) 60 switch (tuple.Definition.Type)
61 { 61 {
62 case TupleDefinitionType.AppSearch: 62 case TupleDefinitionType.AppSearch:
63 this.AddTupleDefaultly(tuple); 63 this.AddTupleDefaultly(tuple);
64 this.Output.EnsureTable(this.TableDefinitions["Signature"]); 64 this.Output.EnsureTable(this.TableDefinitions["Signature"]);
65 break; 65 break;
66 66
67 case TupleDefinitionType.Assembly: 67 case TupleDefinitionType.Assembly:
68 this.AddAssemblyTuple((AssemblyTuple)tuple); 68 this.AddAssemblyTuple((AssemblyTuple)tuple);
69 break; 69 break;
70 70
71 case TupleDefinitionType.BBControl: 71 case TupleDefinitionType.BBControl:
72 this.AddBBControlTuple((BBControlTuple)tuple); 72 this.AddBBControlTuple((BBControlTuple)tuple);
73 break; 73 break;
74 74
75 case TupleDefinitionType.Class: 75 case TupleDefinitionType.Class:
76 this.AddClassTuple((ClassTuple)tuple); 76 this.AddClassTuple((ClassTuple)tuple);
77 break; 77 break;
78 78
79 case TupleDefinitionType.Control: 79 case TupleDefinitionType.Control:
80 this.AddControlTuple((ControlTuple)tuple); 80 this.AddControlTuple((ControlTuple)tuple);
81 break; 81 break;
82 82
83 case TupleDefinitionType.Component: 83 case TupleDefinitionType.Component:
84 this.AddComponentTuple((ComponentTuple)tuple); 84 this.AddComponentTuple((ComponentTuple)tuple);
85 break; 85 break;
86 86
87 case TupleDefinitionType.CustomAction: 87 case TupleDefinitionType.CustomAction:
88 this.AddCustomActionTuple((CustomActionTuple)tuple); 88 this.AddCustomActionTuple((CustomActionTuple)tuple);
89 break; 89 break;
90 90
91 case TupleDefinitionType.Dialog: 91 case TupleDefinitionType.Dialog:
92 this.AddDialogTuple((DialogTuple)tuple); 92 this.AddDialogTuple((DialogTuple)tuple);
93 break; 93 break;
94 94
95 case TupleDefinitionType.Directory: 95 case TupleDefinitionType.Directory:
96 this.AddDirectoryTuple((DirectoryTuple)tuple); 96 this.AddDirectoryTuple((DirectoryTuple)tuple);
97 break; 97 break;
98 98
99 case TupleDefinitionType.Environment: 99 case TupleDefinitionType.Environment:
100 this.AddEnvironmentTuple((EnvironmentTuple)tuple); 100 this.AddEnvironmentTuple((EnvironmentTuple)tuple);
101 break; 101 break;
102 102
103 case TupleDefinitionType.Error: 103 case TupleDefinitionType.Error:
104 this.AddErrorTuple((ErrorTuple)tuple); 104 this.AddErrorTuple((ErrorTuple)tuple);
105 break; 105 break;
106 106
107 case TupleDefinitionType.Feature: 107 case TupleDefinitionType.Feature:
108 this.AddFeatureTuple((FeatureTuple)tuple); 108 this.AddFeatureTuple((FeatureTuple)tuple);
109 break; 109 break;
110 110
111 case TupleDefinitionType.File: 111 case TupleDefinitionType.File:
112 this.AddFileTuple((FileTuple)tuple); 112 this.AddFileTuple((FileTuple)tuple);
113 break; 113 break;
114 114
115 case TupleDefinitionType.IniFile: 115 case TupleDefinitionType.IniFile:
116 this.AddIniFileTuple((IniFileTuple)tuple); 116 this.AddIniFileTuple((IniFileTuple)tuple);
117 break; 117 break;
118 118
119 case TupleDefinitionType.Media: 119 case TupleDefinitionType.Media:
120 this.AddMediaTuple((MediaTuple)tuple); 120 this.AddMediaTuple((MediaTuple)tuple);
121 break; 121 break;
122 122
123 case TupleDefinitionType.ModuleConfiguration: 123 case TupleDefinitionType.ModuleConfiguration:
124 this.AddModuleConfigurationTuple((ModuleConfigurationTuple)tuple); 124 this.AddModuleConfigurationTuple((ModuleConfigurationTuple)tuple);
125 break; 125 break;
126 126
127 case TupleDefinitionType.MsiEmbeddedUI: 127 case TupleDefinitionType.MsiEmbeddedUI:
128 this.AddMsiEmbeddedUITuple((MsiEmbeddedUITuple)tuple); 128 this.AddMsiEmbeddedUITuple((MsiEmbeddedUITuple)tuple);
129 break; 129 break;
130 130
131 case TupleDefinitionType.MsiServiceConfig: 131 case TupleDefinitionType.MsiServiceConfig:
132 this.AddMsiServiceConfigTuple((MsiServiceConfigTuple)tuple); 132 this.AddMsiServiceConfigTuple((MsiServiceConfigTuple)tuple);
133 break; 133 break;
134 134
135 case TupleDefinitionType.MsiServiceConfigFailureActions: 135 case TupleDefinitionType.MsiServiceConfigFailureActions:
136 this.AddMsiServiceConfigFailureActionsTuple((MsiServiceConfigFailureActionsTuple)tuple); 136 this.AddMsiServiceConfigFailureActionsTuple((MsiServiceConfigFailureActionsTuple)tuple);
137 break; 137 break;
138 138
139 case TupleDefinitionType.MoveFile: 139 case TupleDefinitionType.MoveFile:
140 this.AddMoveFileTuple((MoveFileTuple)tuple); 140 this.AddMoveFileTuple((MoveFileTuple)tuple);
141 break; 141 break;
142 142
143 case TupleDefinitionType.ProgId: 143 case TupleDefinitionType.ProgId:
144 this.AddTupleDefaultly(tuple); 144 this.AddTupleDefaultly(tuple);
145 this.Output.EnsureTable(this.TableDefinitions["Extension"]); 145 this.Output.EnsureTable(this.TableDefinitions["Extension"]);
146 break; 146 break;
147 147
148 case TupleDefinitionType.Property: 148 case TupleDefinitionType.Property:
149 this.AddPropertyTuple((PropertyTuple)tuple); 149 this.AddPropertyTuple((PropertyTuple)tuple);
150 break; 150 break;
151 151
152 case TupleDefinitionType.RemoveFile: 152 case TupleDefinitionType.RemoveFile:
153 this.AddRemoveFileTuple((RemoveFileTuple)tuple); 153 this.AddRemoveFileTuple((RemoveFileTuple)tuple);
154 break; 154 break;
155 155
156 case TupleDefinitionType.Registry: 156 case TupleDefinitionType.Registry:
157 this.AddRegistryTuple((RegistryTuple)tuple); 157 this.AddRegistryTuple((RegistryTuple)tuple);
158 break; 158 break;
159 159
160 case TupleDefinitionType.RegLocator: 160 case TupleDefinitionType.RegLocator:
161 this.AddRegLocatorTuple((RegLocatorTuple)tuple); 161 this.AddRegLocatorTuple((RegLocatorTuple)tuple);
162 break; 162 break;
163 163
164 case TupleDefinitionType.RemoveRegistry: 164 case TupleDefinitionType.RemoveRegistry:
165 this.AddRemoveRegistryTuple((RemoveRegistryTuple)tuple); 165 this.AddRemoveRegistryTuple((RemoveRegistryTuple)tuple);
166 break; 166 break;
167 167
168 case TupleDefinitionType.ServiceControl: 168 case TupleDefinitionType.ServiceControl:
169 this.AddServiceControlTuple((ServiceControlTuple)tuple); 169 this.AddServiceControlTuple((ServiceControlTuple)tuple);
170 break; 170 break;
171 171
172 case TupleDefinitionType.ServiceInstall: 172 case TupleDefinitionType.ServiceInstall:
173 this.AddServiceInstallTuple((ServiceInstallTuple)tuple); 173 this.AddServiceInstallTuple((ServiceInstallTuple)tuple);
174 break; 174 break;
175 175
176 case TupleDefinitionType.Shortcut: 176 case TupleDefinitionType.Shortcut:
177 this.AddShortcutTuple((ShortcutTuple)tuple); 177 this.AddShortcutTuple((ShortcutTuple)tuple);
178 break; 178 break;
179 179
180 case TupleDefinitionType.TextStyle: 180 case TupleDefinitionType.TextStyle:
181 this.AddTextStyleTuple((TextStyleTuple)tuple); 181 this.AddTextStyleTuple((TextStyleTuple)tuple);
182 break; 182 break;
183 183
184 case TupleDefinitionType.Upgrade: 184 case TupleDefinitionType.Upgrade:
185 this.AddUpgradeTuple((UpgradeTuple)tuple); 185 this.AddUpgradeTuple((UpgradeTuple)tuple);
186 break; 186 break;
187 187
188 case TupleDefinitionType.WixAction: 188 case TupleDefinitionType.WixAction:
189 this.AddWixActionTuple((WixActionTuple)tuple); 189 this.AddWixActionTuple((WixActionTuple)tuple);
190 break; 190 break;
191 191
192 case TupleDefinitionType.WixMediaTemplate: 192 case TupleDefinitionType.WixMediaTemplate:
193 this.AddWixMediaTemplateTuple((WixMediaTemplateTuple)tuple); 193 this.AddWixMediaTemplateTuple((WixMediaTemplateTuple)tuple);
194 break; 194 break;
195 195
196 case TupleDefinitionType.WixCustomRow: 196 case TupleDefinitionType.WixCustomTableCell:
197 this.AddWixCustomRowTuple((WixCustomRowTuple)tuple); 197 this.IndexCustomTableCellTuple((WixCustomTableCellTuple)tuple, cellsByTableAndRowId);
198 break; 198 break;
199 199
200 case TupleDefinitionType.WixEnsureTable: 200 case TupleDefinitionType.WixEnsureTable:
201 this.AddWixEnsureTableTuple((WixEnsureTableTuple)tuple); 201 this.AddWixEnsureTableTuple((WixEnsureTableTuple)tuple);
202 break; 202 break;
203 203
204 // ignored. 204 // ignored.
205 case TupleDefinitionType.WixComponentGroup: 205 case TupleDefinitionType.WixComponentGroup:
206 case TupleDefinitionType.WixDeltaPatchFile: 206 case TupleDefinitionType.WixDeltaPatchFile:
207 case TupleDefinitionType.WixFeatureGroup: 207 case TupleDefinitionType.WixFeatureGroup:
208 case TupleDefinitionType.WixPatchBaseline: 208 case TupleDefinitionType.WixPatchBaseline:
209 break; 209 break;
210 210
211 // Already processed. 211 // Already processed by LoadTableDefinitions.
212 case TupleDefinitionType.WixCustomTable: 212 case TupleDefinitionType.WixCustomTable:
213 break; 213 case TupleDefinitionType.WixCustomTableColumn:
214 break;
214 215
215 case TupleDefinitionType.MustBeFromAnExtension: 216 case TupleDefinitionType.MustBeFromAnExtension:
216 unknownTuple = !this.AddTupleFromExtension(tuple); 217 unknownTuple = !this.AddTupleFromExtension(tuple);
217 break; 218 break;
218 219
219 default: 220 default:
220 unknownTuple = !this.AddTupleDefaultly(tuple); 221 unknownTuple = !this.AddTupleDefaultly(tuple);
221 break; 222 break;
222 } 223 }
223 224
224 if (unknownTuple) 225 if (unknownTuple)
@@ -226,6 +227,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
226 this.Messaging.Write(WarningMessages.TupleNotTranslatedToOutput(tuple)); 227 this.Messaging.Write(WarningMessages.TupleNotTranslatedToOutput(tuple));
227 } 228 }
228 } 229 }
230
231 this.AddIndexedCellTuples(cellsByTableAndRowId);
229 } 232 }
230 233
231 private void AddAssemblyTuple(AssemblyTuple tuple) 234 private void AddAssemblyTuple(AssemblyTuple tuple)
@@ -383,16 +386,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
383 private void AddDialogTuple(DialogTuple tuple) 386 private void AddDialogTuple(DialogTuple tuple)
384 { 387 {
385 var attributes = tuple.Visible ? WindowsInstallerConstants.MsidbDialogAttributesVisible : 0; 388 var attributes = tuple.Visible ? WindowsInstallerConstants.MsidbDialogAttributesVisible : 0;
386 attributes|= tuple.Modal ? WindowsInstallerConstants.MsidbDialogAttributesModal : 0; 389 attributes |= tuple.Modal ? WindowsInstallerConstants.MsidbDialogAttributesModal : 0;
387 attributes|= tuple.Minimize ? WindowsInstallerConstants.MsidbDialogAttributesMinimize : 0; 390 attributes |= tuple.Minimize ? WindowsInstallerConstants.MsidbDialogAttributesMinimize : 0;
388 attributes|= tuple.CustomPalette ? WindowsInstallerConstants.MsidbDialogAttributesUseCustomPalette: 0; 391 attributes |= tuple.CustomPalette ? WindowsInstallerConstants.MsidbDialogAttributesUseCustomPalette : 0;
389 attributes|= tuple.ErrorDialog ? WindowsInstallerConstants.MsidbDialogAttributesError : 0; 392 attributes |= tuple.ErrorDialog ? WindowsInstallerConstants.MsidbDialogAttributesError : 0;
390 attributes|= tuple.LeftScroll ? WindowsInstallerConstants.MsidbDialogAttributesLeftScroll : 0; 393 attributes |= tuple.LeftScroll ? WindowsInstallerConstants.MsidbDialogAttributesLeftScroll : 0;
391 attributes|= tuple.KeepModeless ? WindowsInstallerConstants.MsidbDialogAttributesKeepModeless : 0; 394 attributes |= tuple.KeepModeless ? WindowsInstallerConstants.MsidbDialogAttributesKeepModeless : 0;
392 attributes|= tuple.RightAligned ? WindowsInstallerConstants.MsidbDialogAttributesRightAligned : 0; 395 attributes |= tuple.RightAligned ? WindowsInstallerConstants.MsidbDialogAttributesRightAligned : 0;
393 attributes|= tuple.RightToLeft ? WindowsInstallerConstants.MsidbDialogAttributesRTLRO : 0; 396 attributes |= tuple.RightToLeft ? WindowsInstallerConstants.MsidbDialogAttributesRTLRO : 0;
394 attributes|= tuple.SystemModal ? WindowsInstallerConstants.MsidbDialogAttributesSysModal : 0; 397 attributes |= tuple.SystemModal ? WindowsInstallerConstants.MsidbDialogAttributesSysModal : 0;
395 attributes|= tuple.TrackDiskSpace ? WindowsInstallerConstants.MsidbDialogAttributesTrackDiskSpace : 0; 398 attributes |= tuple.TrackDiskSpace ? WindowsInstallerConstants.MsidbDialogAttributesTrackDiskSpace : 0;
396 399
397 var row = this.CreateRow(tuple, "Dialog"); 400 var row = this.CreateRow(tuple, "Dialog");
398 row[0] = tuple.Id.Id; 401 row[0] = tuple.Id.Id;
@@ -419,7 +422,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
419 targetName = "."; 422 targetName = ".";
420 } 423 }
421 424
422 var defaultDir = String.IsNullOrEmpty(sourceName) ? targetName : targetName + ":" + sourceName ; 425 var defaultDir = String.IsNullOrEmpty(sourceName) ? targetName : targetName + ":" + sourceName;
423 426
424 var row = this.CreateRow(tuple, "Directory"); 427 var row = this.CreateRow(tuple, "Directory");
425 row[0] = tuple.Id.Id; 428 row[0] = tuple.Id.Id;
@@ -436,25 +439,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
436 439
437 switch (tuple.Action) 440 switch (tuple.Action)
438 { 441 {
439 case EnvironmentActionType.Create: 442 case EnvironmentActionType.Create:
440 action = "+"; 443 action = "+";
441 break; 444 break;
442 case EnvironmentActionType.Set: 445 case EnvironmentActionType.Set:
443 action = "="; 446 action = "=";
444 break; 447 break;
445 case EnvironmentActionType.Remove: 448 case EnvironmentActionType.Remove:
446 action = "!"; 449 action = "!";
447 break; 450 break;
448 } 451 }
449 452
450 switch (tuple.Part) 453 switch (tuple.Part)
451 { 454 {
452 case EnvironmentPartType.First: 455 case EnvironmentPartType.First:
453 value = String.Concat(value, tuple.Separator, "[~]"); 456 value = String.Concat(value, tuple.Separator, "[~]");
454 break; 457 break;
455 case EnvironmentPartType.Last: 458 case EnvironmentPartType.Last:
456 value = String.Concat("[~]", tuple.Separator, value); 459 value = String.Concat("[~]", tuple.Separator, value);
457 break; 460 break;
458 } 461 }
459 462
460 var row = this.CreateRow(tuple, "Environment"); 463 var row = this.CreateRow(tuple, "Environment");
@@ -661,40 +664,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind
661 664
662 switch (tuple.ValueType) 665 switch (tuple.ValueType)
663 { 666 {
664 case RegistryValueType.Binary: 667 case RegistryValueType.Binary:
665 value = String.Concat("#x", value); 668 value = String.Concat("#x", value);
666 break;
667 case RegistryValueType.Expandable:
668 value = String.Concat("#%", value);
669 break;
670 case RegistryValueType.Integer:
671 value = String.Concat("#", value);
672 break;
673 case RegistryValueType.MultiString:
674 switch (tuple.ValueAction)
675 {
676 case RegistryValueActionType.Append:
677 value = String.Concat("[~]", value);
678 break; 669 break;
679 case RegistryValueActionType.Prepend: 670 case RegistryValueType.Expandable:
680 value = String.Concat(value, "[~]"); 671 value = String.Concat("#%", value);
681 break; 672 break;
682 case RegistryValueActionType.Write: 673 case RegistryValueType.Integer:
683 default: 674 value = String.Concat("#", value);
684 if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal)) 675 break;
676 case RegistryValueType.MultiString:
677 switch (tuple.ValueAction)
685 { 678 {
686 value = String.Format(CultureInfo.InvariantCulture, "[~]{0}[~]", value); 679 case RegistryValueActionType.Append:
680 value = String.Concat("[~]", value);
681 break;
682 case RegistryValueActionType.Prepend:
683 value = String.Concat(value, "[~]");
684 break;
685 case RegistryValueActionType.Write:
686 default:
687 if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
688 {
689 value = String.Format(CultureInfo.InvariantCulture, "[~]{0}[~]", value);
690 }
691 break;
692 }
693 break;
694 case RegistryValueType.String:
695 // escape the leading '#' character for string registry keys
696 if (null != value && value.StartsWith("#", StringComparison.Ordinal))
697 {
698 value = String.Concat("#", value);
687 } 699 }
688 break; 700 break;
689 }
690 break;
691 case RegistryValueType.String:
692 // escape the leading '#' character for string registry keys
693 if (null != value && value.StartsWith("#", StringComparison.Ordinal))
694 {
695 value = String.Concat("#", value);
696 }
697 break;
698 } 701 }
699 702
700 var row = this.CreateRow(tuple, "Registry"); 703 var row = this.CreateRow(tuple, "Registry");
@@ -757,7 +760,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
757 row[3] = tuple.Arguments; 760 row[3] = tuple.Arguments;
758 if (tuple.Wait.HasValue) 761 if (tuple.Wait.HasValue)
759 { 762 {
760 row[4] = tuple.Wait.Value ? 1 : 0; 763 row[4] = tuple.Wait.Value ? 1 : 0;
761 } 764 }
762 row[5] = tuple.ComponentRef; 765 row[5] = tuple.ComponentRef;
763 } 766 }
@@ -938,83 +941,89 @@ namespace WixToolset.Core.WindowsInstaller.Bind
938 row[2] = tuple.Sequence; 941 row[2] = tuple.Sequence;
939 } 942 }
940 } 943 }
941
942 private void AddWixCustomRowTuple(WixCustomRowTuple tuple)
943 {
944 var customTableDefinition = this.TableDefinitions[tuple.Table];
945 944
946 if (customTableDefinition.Unreal) 945 private void IndexCustomTableCellTuple(WixCustomTableCellTuple wixCustomTableCellTuple, Dictionary<string, List<WixCustomTableCellTuple>> cellsByTableAndRowId)
946 {
947 var tableAndRowId = wixCustomTableCellTuple.TableRef + "/" + wixCustomTableCellTuple.RowId;
948 if (!cellsByTableAndRowId.TryGetValue(tableAndRowId, out var cells))
947 { 949 {
948 950 cells = new List<WixCustomTableCellTuple>();
949 return; 951 cellsByTableAndRowId.Add(tableAndRowId, cells);
950 } 952 }
951 953
952 var customRow = this.CreateRow(tuple, customTableDefinition); 954 cells.Add(wixCustomTableCellTuple);
955 }
953 956
954#if TODO // SectionId seems like a good thing to preserve. 957 private void AddIndexedCellTuples(Dictionary<string, List<WixCustomTableCellTuple>> cellsByTableAndRowId)
955 customRow.SectionId = tuple.SectionId; 958 {
956#endif 959 foreach (var rowOfCells in cellsByTableAndRowId.Values)
960 {
961 var firstCellTuple = rowOfCells[0];
962 var customTableDefinition = this.TableDefinitions[firstCellTuple.TableRef];
957 963
958 var data = tuple.FieldDataSeparated; 964 if (customTableDefinition.Unreal)
965 {
966 return;
967 }
959 968
960 for (var i = 0; i < data.Length; ++i) 969 var customRow = this.CreateRow(firstCellTuple, customTableDefinition);
961 { 970 var customRowFieldsByColumnName = customRow.Fields.ToDictionary(f => f.Column.Name);
962 var foundColumn = false;
963 var item = data[i].Split(ColonCharacter, 2);
964 971
965 for (var j = 0; j < customRow.Fields.Length; ++j) 972#if TODO // SectionId seems like a good thing to preserve.
973 customRow.SectionId = tuple.SectionId;
974#endif
975 foreach (var cell in rowOfCells)
966 { 976 {
967 if (customRow.Fields[j].Column.Name == item[0]) 977 var data = cell.Data;
978
979 if (customRowFieldsByColumnName.TryGetValue(cell.ColumnRef, out var rowField))
968 { 980 {
969 if (0 < item[1].Length) 981 if (!String.IsNullOrEmpty(data))
970 { 982 {
971 if (ColumnType.Number == customRow.Fields[j].Column.Type) 983 if (rowField.Column.Type == ColumnType.Number)
972 { 984 {
973 try 985 try
974 { 986 {
975 customRow.Fields[j].Data = Convert.ToInt32(item[1], CultureInfo.InvariantCulture); 987 rowField.Data = Convert.ToInt32(data, CultureInfo.InvariantCulture);
976 } 988 }
977 catch (FormatException) 989 catch (FormatException)
978 { 990 {
979 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1])); 991 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(cell.SourceLineNumbers, rowField.Column.Name, customTableDefinition.Name, data));
980 } 992 }
981 catch (OverflowException) 993 catch (OverflowException)
982 { 994 {
983 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1])); 995 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(cell.SourceLineNumbers, rowField.Column.Name, customTableDefinition.Name, data));
984 } 996 }
985 } 997 }
986 else if (ColumnCategory.Identifier == customRow.Fields[j].Column.Category) 998 else if (rowField.Column.Category == ColumnCategory.Identifier)
987 { 999 {
988 if (Common.IsIdentifier(item[1]) || Common.IsValidBinderVariable(item[1]) || ColumnCategory.Formatted == customRow.Fields[j].Column.Category) 1000 if (Common.IsIdentifier(data) || Common.IsValidBinderVariable(data) || ColumnCategory.Formatted == rowField.Column.Category)
989 { 1001 {
990 customRow.Fields[j].Data = item[1]; 1002 rowField.Data = data;
991 } 1003 }
992 else 1004 else
993 { 1005 {
994 this.Messaging.Write(ErrorMessages.IllegalIdentifier(tuple.SourceLineNumbers, "Data", item[1])); 1006 this.Messaging.Write(ErrorMessages.IllegalIdentifier(cell.SourceLineNumbers, "Data", data));
995 } 1007 }
996 } 1008 }
997 else 1009 else
998 { 1010 {
999 customRow.Fields[j].Data = item[1]; 1011 rowField.Data = data;
1000 } 1012 }
1001 } 1013 }
1002 foundColumn = true; 1014 }
1003 break; 1015 else
1016 {
1017 this.Messaging.Write(ErrorMessages.UnexpectedCustomTableColumn(cell.SourceLineNumbers, cell.ColumnRef));
1004 } 1018 }
1005 } 1019 }
1006 1020
1007 if (!foundColumn) 1021 for (var i = 0; i < customTableDefinition.Columns.Length; ++i)
1008 {
1009 this.Messaging.Write(ErrorMessages.UnexpectedCustomTableColumn(tuple.SourceLineNumbers, item[0]));
1010 }
1011 }
1012
1013 for (var i = 0; i < customTableDefinition.Columns.Length; ++i)
1014 {
1015 if (!customTableDefinition.Columns[i].Nullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
1016 { 1022 {
1017 this.Messaging.Write(ErrorMessages.NoDataForColumn(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name)); 1023 if (!customTableDefinition.Columns[i].Nullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
1024 {
1025 this.Messaging.Write(ErrorMessages.NoDataForColumn(firstCellTuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name));
1026 }
1018 } 1027 }
1019 } 1028 }
1020 } 1029 }