Subversion Repositories DevTools

Rev

Rev 2128 | Rev 2134 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2126 ghuddy 1
using System;
2
using System.Collections;
3
using System.Text;
4
using Word;
2130 ghuddy 5
using Microsoft.Office.Core;
2126 ghuddy 6
 
2130 ghuddy 7
 
2126 ghuddy 8
// TODO
9
//
2130 ghuddy 10
// 1) Possible let user and a tag simply with </>
2126 ghuddy 11
 
12
 
13
 
14
namespace EA_DocGen
15
{
16
	/// <summary>
17
	/// Summary description for TextParser.
18
	/// </summary>
2130 ghuddy 19
   public class TextParser
20
   {
2126 ghuddy 21
      // An embedded formatting tag can be one of two types
22
      // * An EA_DocGen special format
23
      // * An MS-Word Style based format
24
      private enum style_type_e
25
      {
2130 ghuddy 26
         STYLE_EA_DOCGEN = 0,    // style is an EA_DocGen specific style or pattern 
27
         STYLE_MS_WORD,          // style is an MS-WORD style of character/font attribute
2126 ghuddy 28
         STYLE_UNKNOWN = -1
29
      };
2130 ghuddy 30
 
31
      private enum style_handling_e
32
      {
33
         STYLE_POST_FORMAT,      // text will require formatting AFTER the entire string has been serialised.
34
         STYLE_USE_TAG_STYLE,    // text will require the tag-implied style to be applied to it.
35
         STYLE_USE_CALLER_STYLE  // text will require the callers specified style to be applied to it.
36
      };
37
 
38
      // IDs for all of the styles we will process.
39
      // Note that the arrangement of enum values in the following type, has been made to allow
40
      // for some simple comparison tests during parsing, so do not re-arrange these enums without
41
      // addressing the necessary code changes in the parsing function.
42
      private enum style_id_e
43
      {
44
         // EA_DocGen styles (0..99)
45
         STYLE_ID_TABLE = 0,
46
         // add more EA_DocGen styles here when we need to
47
 
48
         // MS-WORD styles (100..)
49
         STYLE_ID_BODY1 = 100,
50
         STYLE_ID_BOLD,
51
         STYLE_ID_ITALIC,
52
         STYLE_ID_UNDERLINE,
53
         STYLE_ID_NORMAL,
54
         STYLE_ID_WARNING,
55
         STYLE_ID_NOTE,
56
         STYLE_ID_CODETEXT,
57
         // add more MS-WORD styles here when we need to
58
 
59
         // ALL bullet/list styles must be >= 200 for easy detection during post-formatting
60
         STYLE_ID_LIST_BULLET_0 = 200,
61
         STYLE_ID_LIST_BULLET_1,
62
         STYLE_ID_LIST_BULLET_2,
63
         STYLE_ID_LIST_BULLET_3,
64
         STYLE_ID_LIST_BULLET_4,
65
         STYLE_ID_LIST_INDENT_0,
66
         STYLE_ID_LIST_INDENT_1,
67
         STYLE_ID_LIST_INDENT_2,
68
         STYLE_ID_LIST_INDENT_3,
69
         STYLE_ID_LIST_INDENT_4,
70
         // Below here go lists that display numbering or lettering and so "restart numbering"
71
         // attributes are important
72
         STYLE_ID_LIST_NUMBER_0,
73
         STYLE_ID_LIST_NUMBER_1,
74
         STYLE_ID_LIST_NUMBER_2,
75
         STYLE_ID_LIST_NUMBER_3,
76
         STYLE_ID_LIST_NUMBER_4,
77
         STYLE_ID_LIST_ALPHA_0,
78
         STYLE_ID_LIST_ALPHA_1,
79
         STYLE_ID_LIST_ALPHA_2,
80
         STYLE_ID_LIST_ALPHA_3,
81
         STYLE_ID_LIST_ALPHA_4
82
         // do not put anything below here
83
      };
84
 
2126 ghuddy 85
      // A token is a block of text associated with a tag (style) name and type
86
      private struct token_type
87
      {
2130 ghuddy 88
         public string txt;                     // This is the text content enclosed by the tag
89
         public style_type_e styleType;         // The type MS-WORD or EA_DocGen
90
         public string styleName;               // The name of the style
91
         public style_id_e styleId;             // The id of the style
92
         public int level;                      // level (for list items only)
93
         public style_handling_e styleHandling; // Handling attribute for the style
2126 ghuddy 94
      };
95
 
2130 ghuddy 96
      // Some formatting has to be applied after ALL the text of a description has been
2126 ghuddy 97
      // appended to the word document. For this formatting, we need to remember the word
2130 ghuddy 98
      // ranges that denote the text and the style name to apply. So we do it in a list of
99
      // the following item.
2126 ghuddy 100
      private struct postFormat_type
101
      {
102
         public postFormat_type(Word.Range wr, token_type tk)
103
         {
104
            m_wr = wr;
105
            m_tk = tk;
106
         }
107
         public Word.Range m_wr;
108
         public token_type m_tk;
109
      };
110
 
111
      // Use a hash table for recording the allowed tags and their attributes, facilitating rapid
112
      // lookup during parsing.
113
      private static Hashtable styleDefs = null;
114
 
115
 
116
      /// <summary>
117
      /// Class initialisation function
118
      /// </summary>
119
      public static void initialise()
120
      {
121
         // initialsie the hash table
122
         styleDefs = new Hashtable();
123
 
124
         // This list dictates what tags a user can use in the notes text of an EA element. When adding new items
2130 ghuddy 125
         // to this list, we may have to update the parsing function obviously.
2126 ghuddy 126
 
2130 ghuddy 127
         // The hash key is the short tag name that end-users will use in their descriptions. Tags found in
2126 ghuddy 128
         // user text is matched to these keys, and the style definition if found can then be used.
129
 
130
         // EA_DocGen tags
2130 ghuddy 131
         styleDefs.Add( EA_Constants.EA_DocGenTable, formStyleDef( style_type_e.STYLE_EA_DOCGEN, style_id_e.STYLE_ID_TABLE, EA_Constants.EA_DocGenTable, 0, style_handling_e.STYLE_USE_TAG_STYLE ) );
2126 ghuddy 132
 
133
         // MS-Word formatting tags
2130 ghuddy 134
         styleDefs.Add( "b", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_BOLD, EA_Constants.styleName_Bold      , 0, style_handling_e.STYLE_POST_FORMAT) );
135
         styleDefs.Add( "i", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_ITALIC, EA_Constants.styleName_Italic    , 0, style_handling_e.STYLE_POST_FORMAT) );
136
         styleDefs.Add( "u", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_UNDERLINE, EA_Constants.styleName_Underline , 0, style_handling_e.STYLE_POST_FORMAT) );
2126 ghuddy 137
 
2130 ghuddy 138
         styleDefs.Add( "lb0", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_BULLET_0, EA_Constants.styleName_ListBullet0,1, style_handling_e.STYLE_POST_FORMAT ) );
139
         styleDefs.Add( "lb1", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_BULLET_1, EA_Constants.styleName_ListBullet1,2, style_handling_e.STYLE_POST_FORMAT ) );
140
         styleDefs.Add( "lb2", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_BULLET_2, EA_Constants.styleName_ListBullet2,3, style_handling_e.STYLE_POST_FORMAT ) );
141
         styleDefs.Add( "lb3", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_BULLET_3, EA_Constants.styleName_ListBullet3,4, style_handling_e.STYLE_POST_FORMAT ) );
142
         styleDefs.Add( "lb4", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_BULLET_4, EA_Constants.styleName_ListBullet4,5, style_handling_e.STYLE_POST_FORMAT ) );
143
         styleDefs.Add( "ln0", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_NUMBER_0, EA_Constants.styleName_ListNumber0,1, style_handling_e.STYLE_POST_FORMAT ) );
144
         styleDefs.Add( "ln1", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_NUMBER_1, EA_Constants.styleName_ListNumber1,2, style_handling_e.STYLE_POST_FORMAT ) );
145
         styleDefs.Add( "ln2", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_NUMBER_2, EA_Constants.styleName_ListNumber2,3, style_handling_e.STYLE_POST_FORMAT ) );
146
         styleDefs.Add( "ln3", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_NUMBER_3, EA_Constants.styleName_ListNumber3,4, style_handling_e.STYLE_POST_FORMAT ) );
147
         styleDefs.Add( "ln4", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_NUMBER_4, EA_Constants.styleName_ListNumber4,5, style_handling_e.STYLE_POST_FORMAT ) );
148
         styleDefs.Add( "li0", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_INDENT_0, EA_Constants.styleName_ListIndent0,1, style_handling_e.STYLE_POST_FORMAT ) );
149
         styleDefs.Add( "li1", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_INDENT_1, EA_Constants.styleName_ListIndent1,2, style_handling_e.STYLE_POST_FORMAT ) );
150
         styleDefs.Add( "li2", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_INDENT_2, EA_Constants.styleName_ListIndent2,3, style_handling_e.STYLE_POST_FORMAT ) );
151
         styleDefs.Add( "li3", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_INDENT_3, EA_Constants.styleName_ListIndent3,4, style_handling_e.STYLE_POST_FORMAT ) );
152
         styleDefs.Add( "li4", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_INDENT_4, EA_Constants.styleName_ListIndent4,5, style_handling_e.STYLE_POST_FORMAT ) );
153
         styleDefs.Add( "la0", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_ALPHA_0, EA_Constants.styleName_AlphaList0, 1, style_handling_e.STYLE_POST_FORMAT ) );
154
         styleDefs.Add( "la1", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_ALPHA_1, EA_Constants.styleName_AlphaList1, 2, style_handling_e.STYLE_POST_FORMAT ) );
155
         styleDefs.Add( "la2", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_ALPHA_2, EA_Constants.styleName_AlphaList2, 3, style_handling_e.STYLE_POST_FORMAT ) );
156
         styleDefs.Add( "la3", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_ALPHA_3, EA_Constants.styleName_AlphaList3, 4, style_handling_e.STYLE_POST_FORMAT ) );
157
         styleDefs.Add( "la4", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_LIST_ALPHA_4, EA_Constants.styleName_AlphaList4, 5, style_handling_e.STYLE_POST_FORMAT ) );
2126 ghuddy 158
 
2130 ghuddy 159
         styleDefs.Add( "code", formStyleDef( style_type_e.STYLE_MS_WORD,   style_id_e.STYLE_ID_CODETEXT, EA_Constants.styleName_CodeText, 0, style_handling_e.STYLE_USE_TAG_STYLE ) );
160
         styleDefs.Add( "normal", formStyleDef( style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_NORMAL,   EA_Constants.styleName_Normal  , 0, style_handling_e.STYLE_USE_TAG_STYLE ) );
161
         styleDefs.Add( "note", formStyleDef( style_type_e.STYLE_MS_WORD,   style_id_e.STYLE_ID_NOTE,     EA_Constants.styleName_Note    , 0, style_handling_e.STYLE_USE_TAG_STYLE ) );
162
         styleDefs.Add( "warn", formStyleDef( style_type_e.STYLE_MS_WORD,   style_id_e.STYLE_ID_WARNING,  EA_Constants.styleName_Warning , 0, style_handling_e.STYLE_USE_TAG_STYLE ) );
2126 ghuddy 163
 
164
      }
165
 
166
      /// <summary>
167
      /// Helper for initialise() function
168
      /// </summary>
169
      /// <param name="styleName"></param>
2130 ghuddy 170
      /// <param name="styleName"></param>
2126 ghuddy 171
      /// <returns></returns>
2130 ghuddy 172
      private static token_type formStyleDef(style_type_e styleType, style_id_e styleId, string styleName, int levelvar, style_handling_e styleHandling)
2126 ghuddy 173
      {
174
         token_type tokenType = new token_type();
2130 ghuddy 175
         tokenType.styleType = styleType; // The kind of style (ms-word or ea_docgen)
176
         tokenType.styleId   = styleId;   // The specific type of style
177
         tokenType.styleName = styleName; // The name of the style
178
         tokenType.txt = null;            // This is the actual text to be formatted
179
         tokenType.level = levelvar;      // used to record level numbering - only really useful for bullet/list styles
180
         tokenType.styleHandling = styleHandling;
2126 ghuddy 181
         return tokenType;
182
      }
183
 
184
 
2130 ghuddy 185
      private static void initialiseToken(out token_type token)
186
      {
187
         token.styleName = EA_Constants.styleName_Body1;
188
         token.styleId   = style_id_e.STYLE_ID_BODY1;
189
         token.styleType = style_type_e.STYLE_MS_WORD;
190
         token.styleHandling = style_handling_e.STYLE_USE_CALLER_STYLE;
191
         token.txt = null;
192
         token.level = 0;
193
      }
2126 ghuddy 194
 
195
      /// <summary>
196
      /// Parse the notes of an element and use the results to form document content.
197
      /// </summary>
198
      /// <param name="theElement"></param>
2130 ghuddy 199
      /// <param name="callerStyle"></param>
2126 ghuddy 200
      /// <returns></returns>
2130 ghuddy 201
      public static bool parse(string s, int id, string callerStyle, float indent_pts, bool continuation)
2126 ghuddy 202
      {
203
         int pos;
204
         int pos_LeftBracket = 0;
205
         int pos_RightBracket = 0;
206
         int pos_tagName;
207
         int pos_ContentStart;
208
         int pos_ContentEnd;
209
         bool lookingForTagEnd;
210
         bool foundError = false;
211
         Word.Range wr_body;
212
 
2130 ghuddy 213
 
214
         // Begin to construct a range that will eventually encompass ALL of the text we will serialize during the execution
215
         // of this function. This is needed later only if the caller has specified a requirement style that needs to have 
216
         // global strikethrough or italicising applied to (all of) the text
217
         object startLocation;
218
         object endLocation;
219
         startLocation = createWordDoc.WordDocument.Content.End - 1;
220
 
221
         // Requirement element text must be indented according to the level number of the requirement tag. Caller
222
         // passes in absolute indentation value but for some items such as bullets/lists, we need a relative adjustment
223
         // since bullet/list styles have their own indentation settings and we only want to offset them rather than overwrite
224
         // them.
225
         // Get relative (to 2.5cm) indentation user has commanded. The 2.5cm mark is the standard point where body 1 text
226
         // begins. At 2.5cm, the pts value is 70.866. We only indent, never outdent so end stop at 0. 
2126 ghuddy 227
         float relative_indent_adjustment = 0;
228
         if (indent_pts > 0)
229
         {
230
            relative_indent_adjustment = indent_pts - (float)70.866;
231
            if (relative_indent_adjustment < 0)
232
               relative_indent_adjustment = 0;
233
         }
234
 
2130 ghuddy 235
         // A working variable and a list for completed tokens
2126 ghuddy 236
         token_type token;
237
         ArrayList tokens = new ArrayList();
238
 
239
         // default starting token - may be updated later
2130 ghuddy 240
         initialiseToken(out token);
2126 ghuddy 241
 
2130 ghuddy 242
 
2126 ghuddy 243
         lookingForTagEnd = false;
244
         pos_ContentStart = 0;
245
 
2130 ghuddy 246
         // PARSING LOOP -
247
         // Break up the input string into tokens that identify what kind of action is to be performed
248
         // with the token text. The default is as seen just above - apply Body1 MS-Word style. However,
249
         // if user has used formatting tags, the token style name, ID, and type will be updated accordingly.
250
         // This must be done iteratively until we have exhausted the input string.
251
 
2126 ghuddy 252
         // look for a tag
253
         pos = s.IndexOf("<", 0);
254
         while ((pos >= 0) && (pos < s.Length))
255
         {
2128 ghuddy 256
            if (createWordDoc.abortCreationThread)
257
               return false;
258
 
2126 ghuddy 259
            // record position of tag
260
            pos_LeftBracket = pos;
261
 
262
            // tag name begins at the next char
263
            pos_tagName = pos_LeftBracket + 1;
264
 
265
            // Check if this is a closing tag
266
            bool isEnding = false;
267
            if (pos < (s.Length-1))
268
            {
269
               if (s[pos+1] == '/')
270
               {
271
                  // skip past the / char
272
                  isEnding = true;
273
                  pos_tagName++;
274
               }
275
            }
2130 ghuddy 276
 
2126 ghuddy 277
            // We found a possible tag, now figure out if this is one of the tags we recognise
278
            bool found = false;
279
 
280
            // look for the closing bracket of the tag
281
            pos = s.IndexOf(">", pos+1);
282
            if (pos >= 0)
283
            {
2130 ghuddy 284
               // use hash table to identify the tag
2126 ghuddy 285
               found = styleDefs.Contains(s.Substring(pos_tagName, pos - pos_tagName));
286
            }
287
            else
288
            {
289
               // Cannot find any '>' so we should just exit the loop
290
               break;
291
            }
292
 
293
            // if the tag was recognised
294
            if (found)
295
            {
296
               // record position of the closing bracket of the tag
297
               pos_RightBracket = pos;
298
 
299
               // if this is an end tag, ie. </tagname>
300
               if (isEnding)
301
               {
302
                  pos_ContentEnd = pos_LeftBracket - 1;  // not sure if we really need to compute pos_ContentEnd
2130 ghuddy 303
 
2126 ghuddy 304
                  // check for out of sequence error
305
                  if (!lookingForTagEnd)
306
                  {
307
                     if (!foundError)
308
                     {
309
                        Main.WriteOutput( string.Format("ERROR, Found out of sequence style tag ({0}), generated document text may be formatted incorrectly.", s.Substring(pos_LeftBracket, pos_RightBracket - pos_LeftBracket + 1)), id);
310
                        foundError = true;
311
                     }
312
                  }
313
                  else
314
                  {
315
                     // Check that the end tag matches the start tag
2130 ghuddy 316
                     // NOTE: If we were to allow lazy end-tagging (ie using '</>' only) we would have to do away with this
317
                     // check.
2126 ghuddy 318
                     token_type tt = ((token_type)styleDefs[s.Substring(pos_tagName, pos_RightBracket-pos_tagName)]);
2130 ghuddy 319
                     if (token.styleType == tt.styleType &&
320
                        token.styleId == tt.styleId &&
321
                        token.styleName == tt.styleName)
2126 ghuddy 322
                     {
323
                        // Update the token's text field and add the now complete token to our list
324
                        // for processing a little later on.
325
                        token.txt = s.Substring(pos_ContentStart, pos_LeftBracket - pos_ContentStart);
326
                        tokens.Add(token);
327
 
328
                        // re-initialise token for next tag search
2130 ghuddy 329
                        initialiseToken(out token);
2126 ghuddy 330
 
331
                        lookingForTagEnd = false;
332
 
333
                        pos_ContentStart = pos_RightBracket + 1;
334
                     }
335
                     else
336
                     {
337
                        // end tag does not seem to be the same as the starting tag, so ignore it
338
                        if (!foundError)
339
                        {
340
                           Main.WriteOutput(string.Format("ERROR, Found unmatched style tag ({0}), generated document text may be formatted incorrectly.", s.Substring(pos_LeftBracket, pos_RightBracket - pos_LeftBracket + 1)), id);
341
                           foundError = true;
342
                        }
343
                     }
344
                  }
345
               }
346
               else
347
               {
348
                  // If there is content prior to now that has not been consumed, tokenise it now
349
                  if ((pos_LeftBracket - pos_ContentStart) > 0)
350
                  {
351
                     token.txt = s.Substring(pos_ContentStart, pos_LeftBracket - pos_ContentStart);
352
                     tokens.Add(token);
353
                  }
2130 ghuddy 354
 
2126 ghuddy 355
                  if (lookingForTagEnd)
356
                  {
357
                     if (!foundError)
358
                     {
359
                        Main.WriteOutput(string.Format("ERROR, Found nested style tag ({0}), generated document text may be formatted incorrectly.", s.Substring(pos_LeftBracket, pos_RightBracket - pos_LeftBracket + 1)), id);
360
                        foundError = true;
361
                     }
362
                  }
363
                  else
364
                  {
2130 ghuddy 365
                     // update the token variable with this tags atributes from the hash table lookup. This overwrites
366
                     // the default values assigned when parsing began, or when we resumed parsing after dealing with
367
                     // the previous token found.
368
                     token_type lookupToken = ((token_type)styleDefs[s.Substring(pos_tagName, pos_RightBracket-pos_tagName)]);
369
                     token.styleId   = lookupToken.styleId;
370
                     token.styleType = lookupToken.styleType;
371
                     token.styleName = lookupToken.styleName;
372
                     token.level     = lookupToken.level;
373
                     token.styleHandling = lookupToken.styleHandling;
2126 ghuddy 374
                     token.txt = null; // we dont know what the text content will be yet. This is obtained when we encounter the end tag
375
 
376
                     pos_ContentStart = pos_RightBracket + 1;
377
 
378
                     lookingForTagEnd = true;
379
                  }
380
               }
381
            }
382
            else
383
            {
384
               // the tag was not recognised so for now we just treat it as if it were plain text and continue
385
            }
386
 
387
            // look for next tag
388
            pos = s.IndexOf("<", pos);
389
 
390
         } // end of the loop
391
 
392
 
393
         // take care of the last token, if there is one
394
         if (pos_ContentStart < s.Length)
395
         {
396
            // Update the token's text field
397
            token.txt = s.Substring(pos_ContentStart, s.Length - pos_ContentStart);
398
            tokens.Add(token);
399
         }
400
 
401
         if (lookingForTagEnd)
402
         {
403
            if (!foundError)
404
            {
405
               Main.WriteOutput(string.Format("ERROR, Found incomplete style tag ({0}), generated document text may be formatted incorrectly.", s.Substring(pos_LeftBracket, pos_RightBracket - pos_LeftBracket + 1)), id);
406
               foundError = true;
407
            }
408
         }
409
 
2130 ghuddy 410
         // The way MS-Word works makes it necessary to do some formatting after we have serialised all of the text.
411
         // So, we need another list. This will contain elements that have the token AND the word range object that we
412
         // obtain when we serialise the text.
2126 ghuddy 413
         ArrayList postFormats = new ArrayList();
414
 
2130 ghuddy 415
         // SERIALISATION LOOP - Now process all the tokens we have found
416
         int tt_i = 0;
417
         for (tt_i = 0; tt_i < tokens.Count; tt_i++)
2126 ghuddy 418
         {
2130 ghuddy 419
            token_type tt = (token_type)tokens[tt_i];
420
 
2128 ghuddy 421
            if (createWordDoc.abortCreationThread)
422
               return false;
423
 
2126 ghuddy 424
            if (tt.txt != null && tt.txt.Length > 0)
425
            {
426
 
427
               switch (tt.styleType)
428
               {
429
                  case style_type_e.STYLE_EA_DOCGEN:
2130 ghuddy 430
                     switch (tt.styleId)
2126 ghuddy 431
                     {
2130 ghuddy 432
                        case style_id_e.STYLE_ID_TABLE:
2126 ghuddy 433
                           TabularContent.processTableElement(tt.txt, 0, indent_pts);
434
                           continuation = false;
435
 
436
                           // flag list numbering restart
437
                           postFormats.Add( new postFormat_type(null, tt) );
438
                           break;
439
 
440
                        default:
441
                           break;
442
                     }
443
                     break;
444
 
445
                  case style_type_e.STYLE_MS_WORD:
2130 ghuddy 446
                     switch (tt.styleHandling)
2126 ghuddy 447
                     {
2130 ghuddy 448
                        case style_handling_e.STYLE_POST_FORMAT:
449
                           // Replace <br> with actual required characters, and use the caller supplied style when serialising
450
                           // the text
451
                           tt.txt = tt.txt.Replace("<br>","\r\n");
452
 
453
                           // Serialise the text, initially applying callers style but since post-formatting will be
454
                           // done later, the texts appearance will change from what this initially applied style
455
                           // implies.
456
                           wr_body = TextualContent.appendAndSelectText( tt.txt, callerStyle, continuation );
2126 ghuddy 457
                           continuation = true;
2130 ghuddy 458
 
459
                           while (wr_body.Characters.Last.Text.Equals("\r") || wr_body.Characters.Last.Text.Equals("\n"))
460
                              wr_body.End = wr_body.End - 1;  // don't format the /n or \r char at the end - doing so causes wierd ms-word exceptions later on
2126 ghuddy 461
                           postFormats.Add( new postFormat_type(wr_body, tt) );
462
                           break;
463
 
2130 ghuddy 464
                        case style_handling_e.STYLE_USE_TAG_STYLE:
465
                           // Replace <br> with actual required characters, and use the caller supplied style when serialising
466
                           // the text
467
                           tt.txt = tt.txt.Replace("<br>","\r\n");
468
 
469
                           // Serialise the text, applying the tag's style 
2126 ghuddy 470
                           wr_body = TextualContent.appendAndSelectText( tt.txt, tt.styleName, continuation );
471
                           continuation = true;
2130 ghuddy 472
 
473
                           // Indent according to callers specified amount
2126 ghuddy 474
                           if (indent_pts > 0)
475
                              wr_body.ParagraphFormat.LeftIndent = indent_pts;
476
 
2130 ghuddy 477
                           // flag list numbering restart if this is printable text.
478
                           if (tt.txt.Trim().Length > 0)
479
                              postFormats.Add( new postFormat_type(null, tt) );
2126 ghuddy 480
                           break;
481
 
482
 
2130 ghuddy 483
                        case style_handling_e.STYLE_USE_CALLER_STYLE:
484
                           // Replace <br> with actual required characters, and use the caller supplied style when serialising
485
                           // the text
486
                           tt.txt = tt.txt.Replace("<br>","\r\n");
487
 
488
                           // Serialise the text, applying callers style 
489
                           wr_body = TextualContent.appendAndSelectText( tt.txt, callerStyle, continuation );
2126 ghuddy 490
                           continuation = true;
2130 ghuddy 491
 
492
                           // Indent according to callers specified amount
2126 ghuddy 493
                           if (indent_pts > 0)
494
                              wr_body.ParagraphFormat.LeftIndent = indent_pts;
495
 
496
                           // flag list numbering restart if this is printable text.
497
                           if (tt.txt.Trim().Length > 0)
498
                              postFormats.Add( new postFormat_type(null, tt) );
499
                           break;
500
 
501
                        default:
502
                           break;
503
                     }
504
                     break;
505
 
506
                  default:
507
                     break;
508
               }
509
            }
2130 ghuddy 510
         } // end of serialisation loop
2126 ghuddy 511
 
2130 ghuddy 512
 
513
         // POST-FORMATTING LOOP - Now apply post formatting commands to text already serialised in previous loop
2126 ghuddy 514
         int last_list_level = 0;
515
         foreach (postFormat_type pf in postFormats)
516
         {
517
            object style;
518
 
2128 ghuddy 519
            if (createWordDoc.abortCreationThread)
520
               return false;
521
 
2126 ghuddy 522
            // a null word range implies we must restart numbering for any lists
523
            if (pf.m_wr == null)
524
            {
525
               last_list_level = 0;
526
            }
527
            else
528
            {
2130 ghuddy 529
               switch (pf.m_tk.styleId)
2126 ghuddy 530
               {
2130 ghuddy 531
                  case style_id_e.STYLE_ID_BOLD:
2126 ghuddy 532
                     pf.m_wr.Select();
533
                     createWordDoc.WordApp.Selection.Range.Bold = 1;
534
                     last_list_level = 0;
535
                     break;
536
 
2130 ghuddy 537
                  case style_id_e.STYLE_ID_ITALIC:
2126 ghuddy 538
                     pf.m_wr.Select();
539
                     createWordDoc.WordApp.Selection.Range.Italic = 1;
540
                     last_list_level = 0;
541
                     break;
542
 
2130 ghuddy 543
                  case style_id_e.STYLE_ID_UNDERLINE:
2126 ghuddy 544
                     pf.m_wr.Select();
545
                     createWordDoc.WordApp.Selection.Range.Underline = Word.WdUnderline.wdUnderlineSingle;
546
                     last_list_level = 0;
547
                     break;
548
 
2130 ghuddy 549
                  default:
550
                     // Handle bullets/lists
551
                     if (pf.m_tk.styleId >= style_id_e.STYLE_ID_LIST_BULLET_0)
552
                     {
553
                        style = pf.m_tk.styleName;
554
                        pf.m_wr.Select();
555
                        createWordDoc.WordApp.Selection.Range.set_Style(ref style);
2126 ghuddy 556
 
2130 ghuddy 557
                        // Figure out if we have to restart numbering
558
                        if (last_list_level < pf.m_tk.level)
559
                        {
560
                           // only need to restart numbering if this list displays numbering - bullets and simple
561
                           // indents do not, but alpha and numeric lists do. The style_id_e type has been organised to
562
                           // make this a simple test.
563
                           if (pf.m_tk.styleId >= style_id_e.STYLE_ID_LIST_NUMBER_0)
564
                           {
565
                              // To restart numbering, the only way to do it is to (re-)apply the list template to the 
566
                              // selection with a "continue previous list" setting of false, and an "apply to"
567
                              // setting of "whole list". 
568
                              object continuePreviousList = false;
569
                              object applyTo = Word.WdListApplyTo.wdListApplyToWholeList;
570
                              object defListBehavour = Word.WdDefaultListBehavior.wdWord10ListBehavior;
571
 
572
                              Word.ListTemplate lt = createWordDoc.WordApp.Selection.Range.ListFormat.ListTemplate;
2126 ghuddy 573
 
2130 ghuddy 574
                              createWordDoc.WordApp.Selection.Range.ListFormat.ApplyListTemplate(
575
                                 lt, ref continuePreviousList, ref applyTo, ref defListBehavour);
576
                           }
577
                        }
578
 
579
                        // shift content right by relative indent adjustment we calculated earlier
580
                        if (relative_indent_adjustment > 0)
2126 ghuddy 581
                        {
2130 ghuddy 582
                           createWordDoc.WordApp.Selection.Range.ParagraphFormat.LeftIndent += relative_indent_adjustment;
2126 ghuddy 583
                        }
584
 
2130 ghuddy 585
                        last_list_level = pf.m_tk.level;
2126 ghuddy 586
                     }
587
                     break;
588
               }
589
            }
2130 ghuddy 590
         } // end of post-formatting loop
591
 
592
         // Special handling for Proposed and Rejected requirement sections - here the text must be italicies or
593
         // struck through (see definition of the styleName_ReqPropBody and styleName_ReqRejBody styles in StyleContent.cs).
594
         if (callerStyle.Equals(EA_Constants.styleName_ReqPropBody))
595
         {
596
            // Complete construction of a range that will encompass ALL of the text we will serialize during the execution
597
            // of this function
598
            endLocation = createWordDoc.WordDocument.Content.End;
599
            Word.Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
600
            while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
601
               wr_total.End = wr_total.End - 1;  // don't format the \r\n char at the end - doing so causes wierd ms-word exceptions later on
602
 
603
            // italicise
604
            wr_total.Font.Italic = (int)MsoTriState.msoTrue;
2126 ghuddy 605
         }
2130 ghuddy 606
         else if (callerStyle.Equals(EA_Constants.styleName_ReqRejBody))
607
         {
608
            // Complete construction of a range that will encompass ALL of the text we will serialize during the execution
609
            // of this function
610
            endLocation = createWordDoc.WordDocument.Content.End;
611
            Word.Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
612
            while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
613
               wr_total.End = wr_total.End - 1;  // don't format the \r\n char at the end - doing so causes wierd ms-word exceptions later on
614
 
615
            // strikethrough - use msoCTrue since msoTrue simply toggles strikethough attribute, or so it seems
616
            wr_total.Font.StrikeThrough = (int)MsoTriState.msoCTrue;
617
         }
618
 
2126 ghuddy 619
         return true;
620
      }
621
 
622
 
623
 
624
 
2130 ghuddy 625
 
626
   }
2126 ghuddy 627
}