| Line 1... |
Line 1... |
| 1 |
using System;
|
1 |
using System;
|
| 2 |
using System.Collections;
|
2 |
using System.Collections;
|
| 3 |
using System.Text;
|
3 |
using System.Text;
|
| - |
|
4 |
using System.Text.RegularExpressions;
|
| 4 |
using Word;
|
5 |
using Microsoft.Office.Interop.Word;
|
| 5 |
using Microsoft.Office.Core;
|
6 |
using Microsoft.Office.Core;
|
| 6 |
|
7 |
|
| 7 |
|
8 |
|
| 8 |
// TODO
|
9 |
// TODO
|
| 9 |
//
|
10 |
//
|
| Line 76... |
Line 77... |
| 76 |
STYLE_ID_LIST_NUMBER_4,
|
77 |
STYLE_ID_LIST_NUMBER_4,
|
| 77 |
STYLE_ID_LIST_ALPHA_0,
|
78 |
STYLE_ID_LIST_ALPHA_0,
|
| 78 |
STYLE_ID_LIST_ALPHA_1,
|
79 |
STYLE_ID_LIST_ALPHA_1,
|
| 79 |
STYLE_ID_LIST_ALPHA_2,
|
80 |
STYLE_ID_LIST_ALPHA_2,
|
| 80 |
STYLE_ID_LIST_ALPHA_3,
|
81 |
STYLE_ID_LIST_ALPHA_3,
|
| 81 |
STYLE_ID_LIST_ALPHA_4
|
82 |
STYLE_ID_LIST_ALPHA_4,
|
| 82 |
// do not put anything below here
|
83 |
// do not put anything below here
|
| - |
|
84 |
STYLE_ID_FONT_COLOR
|
| 83 |
};
|
85 |
};
|
| 84 |
|
86 |
|
| 85 |
// A token is a block of text associated with a tag (style) name and type
|
87 |
// A token is a block of text associated with a tag (style) name and type
|
| 86 |
private struct token_type
|
88 |
private struct token_type
|
| 87 |
{
|
89 |
{
|
| Line 97... |
Line 99... |
| 97 |
// appended to the word document. For this formatting, we need to remember the word
|
99 |
// appended to the word document. For this formatting, we need to remember the word
|
| 98 |
// ranges that denote the text and the style name to apply. So we do it in a list of
|
100 |
// ranges that denote the text and the style name to apply. So we do it in a list of
|
| 99 |
// the following item.
|
101 |
// the following item.
|
| 100 |
private struct postFormat_type
|
102 |
private struct postFormat_type
|
| 101 |
{
|
103 |
{
|
| 102 |
public postFormat_type(Word.Range wr, token_type tk)
|
104 |
public postFormat_type(Range wr, token_type tk)
|
| 103 |
{
|
105 |
{
|
| 104 |
m_wr = wr;
|
106 |
m_wr = wr;
|
| 105 |
m_tk = tk;
|
107 |
m_tk = tk;
|
| 106 |
}
|
108 |
}
|
| 107 |
public Word.Range m_wr;
|
109 |
public Range m_wr;
|
| 108 |
public token_type m_tk;
|
110 |
public token_type m_tk;
|
| 109 |
};
|
111 |
};
|
| 110 |
|
112 |
|
| 111 |
// Use a hash table for recording the allowed tags and their attributes, facilitating rapid
|
113 |
// Use a hash table for recording the allowed tags and their attributes, facilitating rapid
|
| 112 |
// lookup during parsing.
|
114 |
// lookup during parsing.
|
| Line 132... |
Line 134... |
| 132 |
|
134 |
|
| 133 |
// MS-Word formatting tags
|
135 |
// MS-Word formatting tags
|
| 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) );
|
136 |
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) );
|
137 |
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) );
|
138 |
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) );
|
| - |
|
139 |
styleDefs.Add("font", formStyleDef(style_type_e.STYLE_MS_WORD, style_id_e.STYLE_ID_FONT_COLOR, EA_Constants.styleName_Font_Color, 0, style_handling_e.STYLE_POST_FORMAT));
|
| 137 |
|
140 |
|
| 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 ) );
|
141 |
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 ) );
|
142 |
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 ) );
|
143 |
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 ) );
|
144 |
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 ) );
|
| Line 233... |
Line 236... |
| 233 |
int pos_tagName;
|
236 |
int pos_tagName;
|
| 234 |
int pos_ContentStart;
|
237 |
int pos_ContentStart;
|
| 235 |
int pos_ContentEnd;
|
238 |
int pos_ContentEnd;
|
| 236 |
bool lookingForTagEnd;
|
239 |
bool lookingForTagEnd;
|
| 237 |
bool foundError = false;
|
240 |
bool foundError = false;
|
| 238 |
Word.Range wr_body;
|
241 |
Range wr_body;
|
| 239 |
|
242 |
|
| 240 |
// Convert EA7.1 embedded RTF controls into EA_DocGen controls where possible
|
243 |
// Convert EA7.1 embedded RTF controls into EA_DocGen controls where possible
|
| 241 |
s = convert_EA7_1_RTF_ListTag(s, "<ol>\r\n", "</ol>", "<ln0>", "</ln0>");
|
244 |
s = convert_EA7_1_RTF_ListTag(s, "<ol>\r\n", "</ol>", "<ln0>", "</ln0>");
|
| 242 |
s = convert_EA7_1_RTF_ListTag(s, "<ul>\r\n", "</ul>", "<lb0>", "</lb0>");
|
245 |
s = convert_EA7_1_RTF_ListTag(s, "<ul>\r\n", "</ul>", "<lb0>", "</lb0>");
|
| 243 |
|
246 |
|
| Line 246... |
Line 249... |
| 246 |
// human users and so EAv7.1 converts < and > chars into a form such that they do not look like RTF tags.
|
249 |
// human users and so EAv7.1 converts < and > chars into a form such that they do not look like RTF tags.
|
| 247 |
// We have to convert EA's escaping mechanism back into ascii text chars otherwise the parser wont work.
|
250 |
// We have to convert EA's escaping mechanism back into ascii text chars otherwise the parser wont work.
|
| 248 |
// There may be issues to resolve with this parser if EAv7.1 users have used any of EA's RTF editing features
|
251 |
// There may be issues to resolve with this parser if EAv7.1 users have used any of EA's RTF editing features
|
| 249 |
// because if they do, the < and > chars there will not be escaped and the parser will find them and try to
|
252 |
// because if they do, the < and > chars there will not be escaped and the parser will find them and try to
|
| 250 |
// decode them. Most will probably not be decodable.
|
253 |
// decode them. Most will probably not be decodable.
|
| 251 |
s = s.Replace("<","<");
|
- |
|
| 252 |
s = s.Replace(">",">");
|
254 |
s = TextualContent.HtmlDecode(s);
|
| - |
|
255 |
|
| 253 |
|
256 |
|
| 254 |
// Begin to construct a range that will eventually encompass ALL of the text we will serialize during the execution
|
257 |
// Begin to construct a range that will eventually encompass ALL of the text we will serialize during the execution
|
| 255 |
// of this function. This is needed later only if the caller has specified a requirement style that needs to have
|
258 |
// of this function. This is needed later only if the caller has specified a requirement style that needs to have
|
| 256 |
// global strikethrough or italicising applied to (all of) the text
|
259 |
// global strikethrough or italicising applied to (all of) the text
|
| 257 |
object startLocation;
|
260 |
object startLocation;
|
| Line 319... |
Line 322... |
| 319 |
|
322 |
|
| 320 |
// look for the closing bracket of the tag
|
323 |
// look for the closing bracket of the tag
|
| 321 |
pos = s.IndexOf(">", pos+1);
|
324 |
pos = s.IndexOf(">", pos+1);
|
| 322 |
if (pos >= 0)
|
325 |
if (pos >= 0)
|
| 323 |
{
|
326 |
{
|
| - |
|
327 |
string sTag = s.Substring(pos_tagName, pos - pos_tagName);
|
| - |
|
328 |
|
| - |
|
329 |
if (!isEnding)
|
| - |
|
330 |
{
|
| - |
|
331 |
// check for font start tag with color attribute
|
| - |
|
332 |
Regex re = new Regex("font.*?color=\"#(?<color>[0-9A-F]*)\"",RegexOptions.IgnoreCase);
|
| - |
|
333 |
if (re.IsMatch(sTag))
|
| - |
|
334 |
sTag = "font";
|
| - |
|
335 |
}
|
| - |
|
336 |
|
| 324 |
// use hash table to identify the tag
|
337 |
// use hash table to identify the tag
|
| 325 |
found = styleDefs.Contains(s.Substring(pos_tagName, pos - pos_tagName));
|
338 |
found = styleDefs.Contains(sTag);
|
| 326 |
}
|
339 |
}
|
| 327 |
else
|
340 |
else
|
| 328 |
{
|
341 |
{
|
| 329 |
// Cannot find any '>' so we should just exit the loop
|
342 |
// Cannot find any '>' so we should just exit the loop
|
| 330 |
break;
|
343 |
break;
|
| Line 385... |
Line 398... |
| 385 |
}
|
398 |
}
|
| 386 |
else
|
399 |
else
|
| 387 |
{
|
400 |
{
|
| 388 |
// If there is content prior to now that has not been consumed, tokenise it now
|
401 |
// If there is content prior to now that has not been consumed, tokenise it now
|
| 389 |
if ((pos_LeftBracket - pos_ContentStart) > 0)
|
402 |
if ((pos_LeftBracket - pos_ContentStart) > 0)
|
| - |
|
403 |
|
| 390 |
{
|
404 |
{
|
| 391 |
token.txt = s.Substring(pos_ContentStart, pos_LeftBracket - pos_ContentStart);
|
405 |
token.txt = s.Substring(pos_ContentStart, pos_LeftBracket - pos_ContentStart);
|
| 392 |
tokens.Add(token);
|
406 |
tokens.Add(token);
|
| 393 |
}
|
407 |
}
|
| 394 |
|
408 |
|
| Line 403... |
Line 417... |
| 403 |
else
|
417 |
else
|
| 404 |
{
|
418 |
{
|
| 405 |
// update the token variable with this tags atributes from the hash table lookup. This overwrites
|
419 |
// update the token variable with this tags atributes from the hash table lookup. This overwrites
|
| 406 |
// the default values assigned when parsing began, or when we resumed parsing after dealing with
|
420 |
// the default values assigned when parsing began, or when we resumed parsing after dealing with
|
| 407 |
// the previous token found.
|
421 |
// the previous token found.
|
| - |
|
422 |
|
| 408 |
token_type lookupToken = ((token_type)styleDefs[s.Substring(pos_tagName, pos_RightBracket-pos_tagName)]);
|
423 |
string df = s.Substring(pos_tagName, pos_RightBracket-pos_tagName);
|
| - |
|
424 |
|
| - |
|
425 |
// check for font tag with color attribute
|
| - |
|
426 |
int iFontColor = -1;
|
| - |
|
427 |
Regex re = new Regex("font.*?color=\"#(?<color>[0-9A-F]*)\"", RegexOptions.IgnoreCase);
|
| - |
|
428 |
if (re.IsMatch(df))
|
| - |
|
429 |
{
|
| - |
|
430 |
// get color attribute value
|
| - |
|
431 |
string sColor = re.Matches(df)[0].Groups["color"].Value;
|
| - |
|
432 |
iFontColor = Convert.ToInt32(sColor,16);
|
| - |
|
433 |
df = "font";
|
| - |
|
434 |
}
|
| - |
|
435 |
|
| - |
|
436 |
token_type lookupToken = ((token_type)styleDefs[df]);
|
| 409 |
token.styleId = lookupToken.styleId;
|
437 |
token.styleId = lookupToken.styleId;
|
| 410 |
token.styleType = lookupToken.styleType;
|
438 |
token.styleType = lookupToken.styleType;
|
| 411 |
token.styleName = lookupToken.styleName;
|
439 |
token.styleName = lookupToken.styleName;
|
| - |
|
440 |
if (token.styleId == style_id_e.STYLE_ID_FONT_COLOR)
|
| - |
|
441 |
token.level = iFontColor;
|
| - |
|
442 |
else
|
| 412 |
token.level = lookupToken.level;
|
443 |
token.level = lookupToken.level;
|
| 413 |
token.styleHandling = lookupToken.styleHandling;
|
444 |
token.styleHandling = lookupToken.styleHandling;
|
| 414 |
token.txt = null; // we dont know what the text content will be yet. This is obtained when we encounter the end tag
|
445 |
token.txt = null; // we dont know what the text content will be yet. This is obtained when we encounter the end tag
|
| 415 |
|
446 |
|
| 416 |
pos_ContentStart = pos_RightBracket + 1;
|
447 |
pos_ContentStart = pos_RightBracket + 1;
|
| 417 |
|
448 |
|
| Line 580... |
Line 611... |
| 580 |
last_list_level = 0;
|
611 |
last_list_level = 0;
|
| 581 |
break;
|
612 |
break;
|
| 582 |
|
613 |
|
| 583 |
case style_id_e.STYLE_ID_UNDERLINE:
|
614 |
case style_id_e.STYLE_ID_UNDERLINE:
|
| 584 |
pf.m_wr.Select();
|
615 |
pf.m_wr.Select();
|
| 585 |
createWordDoc.WordApp.Selection.Range.Underline = Word.WdUnderline.wdUnderlineSingle;
|
616 |
createWordDoc.WordApp.Selection.Range.Underline = WdUnderline.wdUnderlineSingle;
|
| 586 |
last_list_level = 0;
|
617 |
last_list_level = 0;
|
| 587 |
break;
|
618 |
break;
|
| 588 |
|
619 |
|
| - |
|
620 |
case style_id_e.STYLE_ID_FONT_COLOR:
|
| - |
|
621 |
pf.m_wr.Select();
|
| - |
|
622 |
createWordDoc.WordApp.Selection.Range.Font.Color = (WdColor) ReverseRGB((UInt32)pf.m_tk.level);
|
| - |
|
623 |
last_list_level = 0;
|
| - |
|
624 |
break;
|
| - |
|
625 |
|
| 589 |
default:
|
626 |
default:
|
| 590 |
// Handle bullets/lists
|
627 |
// Handle bullets/lists
|
| 591 |
if (pf.m_tk.styleId >= style_id_e.STYLE_ID_LIST_BULLET_0)
|
628 |
if (pf.m_tk.styleId >= style_id_e.STYLE_ID_LIST_BULLET_0)
|
| 592 |
{
|
629 |
{
|
| 593 |
style = pf.m_tk.styleName;
|
630 |
style = pf.m_tk.styleName;
|
| Line 604... |
Line 641... |
| 604 |
{
|
641 |
{
|
| 605 |
// To restart numbering, the only way to do it is to (re-)apply the list template to the
|
642 |
// To restart numbering, the only way to do it is to (re-)apply the list template to the
|
| 606 |
// selection with a "continue previous list" setting of false, and an "apply to"
|
643 |
// selection with a "continue previous list" setting of false, and an "apply to"
|
| 607 |
// setting of "whole list".
|
644 |
// setting of "whole list".
|
| 608 |
object continuePreviousList = false;
|
645 |
object continuePreviousList = false;
|
| 609 |
object applyTo = Word.WdListApplyTo.wdListApplyToWholeList;
|
646 |
object applyTo = WdListApplyTo.wdListApplyToWholeList;
|
| 610 |
object defListBehavour = Word.WdDefaultListBehavior.wdWord10ListBehavior;
|
647 |
object defListBehavour = WdDefaultListBehavior.wdWord10ListBehavior;
|
| 611 |
|
648 |
|
| 612 |
Word.ListTemplate lt = createWordDoc.WordApp.Selection.Range.ListFormat.ListTemplate;
|
649 |
ListTemplate lt = createWordDoc.WordApp.Selection.Range.ListFormat.ListTemplate;
|
| 613 |
|
650 |
|
| 614 |
createWordDoc.WordApp.Selection.Range.ListFormat.ApplyListTemplate(
|
651 |
createWordDoc.WordApp.Selection.Range.ListFormat.ApplyListTemplate(
|
| 615 |
lt, ref continuePreviousList, ref applyTo, ref defListBehavour);
|
652 |
lt, ref continuePreviousList, ref applyTo, ref defListBehavour);
|
| 616 |
}
|
653 |
}
|
| 617 |
}
|
654 |
}
|
| Line 634... |
Line 671... |
| 634 |
if (callerStyle.Equals(EA_Constants.styleName_ReqPropBody))
|
671 |
if (callerStyle.Equals(EA_Constants.styleName_ReqPropBody))
|
| 635 |
{
|
672 |
{
|
| 636 |
// Complete construction of a range that will encompass ALL of the text we will serialize during the execution
|
673 |
// Complete construction of a range that will encompass ALL of the text we will serialize during the execution
|
| 637 |
// of this function
|
674 |
// of this function
|
| 638 |
endLocation = createWordDoc.WordDocument.Content.End;
|
675 |
endLocation = createWordDoc.WordDocument.Content.End;
|
| 639 |
Word.Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
|
676 |
Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
|
| 640 |
while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
|
677 |
while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
|
| 641 |
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
|
678 |
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
|
| 642 |
|
679 |
|
| 643 |
// italicise
|
680 |
// italicise
|
| 644 |
wr_total.Font.Italic = (int)MsoTriState.msoTrue;
|
681 |
wr_total.Font.Italic = (int)MsoTriState.msoTrue;
|
| Line 646... |
Line 683... |
| 646 |
else if (callerStyle.Equals(EA_Constants.styleName_ReqRejBody))
|
683 |
else if (callerStyle.Equals(EA_Constants.styleName_ReqRejBody))
|
| 647 |
{
|
684 |
{
|
| 648 |
// Complete construction of a range that will encompass ALL of the text we will serialize during the execution
|
685 |
// Complete construction of a range that will encompass ALL of the text we will serialize during the execution
|
| 649 |
// of this function
|
686 |
// of this function
|
| 650 |
endLocation = createWordDoc.WordDocument.Content.End;
|
687 |
endLocation = createWordDoc.WordDocument.Content.End;
|
| 651 |
Word.Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
|
688 |
Range wr_total = createWordDoc.WordDocument.Range(ref startLocation, ref endLocation);
|
| 652 |
while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
|
689 |
while (wr_total.Characters.Last.Text.Equals("\r") || wr_total.Characters.Last.Text.Equals("\n"))
|
| 653 |
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
|
690 |
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
|
| 654 |
|
691 |
|
| 655 |
// strikethrough - use msoCTrue since msoTrue simply toggles strikethough attribute, or so it seems
|
692 |
// strikethrough - use msoCTrue since msoTrue simply toggles strikethough attribute, or so it seems
|
| 656 |
wr_total.Font.StrikeThrough = (int)MsoTriState.msoCTrue;
|
693 |
wr_total.Font.StrikeThrough = (int)MsoTriState.msoCTrue;
|
| 657 |
}
|
694 |
}
|
| 658 |
|
695 |
|
| 659 |
return true;
|
696 |
return true;
|
| 660 |
}
|
697 |
}
|
| 661 |
|
698 |
|
| 662 |
|
- |
|
| - |
|
699 |
public static UInt32 ReverseRGB(UInt32 value)
|
| 663 |
|
700 |
{
|
| - |
|
701 |
UInt32 i = (value & 0x000000FFU) << 16 | (value & 0x0000FF00U) |
|
| - |
|
702 |
(value & 0x00FF0000U) >> 16;
|
| - |
|
703 |
return i;
|
| 664 |
|
704 |
}
|
| 665 |
|
705 |
|
| 666 |
}
|
706 |
}
|
| 667 |
}
|
707 |
}
|