You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
454 lines
15 KiB
454 lines
15 KiB
/* ====================================================================
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==================================================================== */
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using NPOI.HWPF.Model;
|
|
using NPOI.HWPF.UserModel;
|
|
using NPOI.POIFS.FileSystem;
|
|
using NPOI.Util;
|
|
|
|
|
|
namespace NPOI.HWPF.Converter
|
|
{
|
|
public class AbstractWordUtils
|
|
{
|
|
static POILogger logger = POILogFactory.GetLogger(typeof(AbstractWordUtils));
|
|
public static float TWIPS_PER_INCH = 1440.0f;
|
|
public static int TWIPS_PER_PT = 20;
|
|
|
|
|
|
/**
|
|
* Creates array of all possible cell edges. In HTML (and FO) cells from
|
|
* different rows and same column should have same width, otherwise spanning
|
|
* shall be used.
|
|
*
|
|
* @param table
|
|
* table to build cell edges array from
|
|
* @return array of cell edges (including leftest one) in twips
|
|
*/
|
|
public static int[] BuildTableCellEdgesArray(Table table)
|
|
{
|
|
SortedList<int, int> edges = new SortedList<int, int>();
|
|
|
|
for (int r = 0; r < table.NumRows; r++)
|
|
{
|
|
TableRow tableRow = table.GetRow(r);
|
|
for (int c = 0; c < tableRow.NumCells(); c++)
|
|
{
|
|
TableCell tableCell = tableRow.GetCell(c);
|
|
if (!edges.ContainsKey(tableCell.GetLeftEdge()))
|
|
edges.Add(tableCell.GetLeftEdge(), 0);
|
|
if (!edges.ContainsKey(tableCell.GetLeftEdge() + tableCell.GetWidth()))
|
|
edges.Add(tableCell.GetLeftEdge() + tableCell.GetWidth(), 0);
|
|
}
|
|
}
|
|
|
|
int[] result = new int[edges.Count];
|
|
|
|
edges.Keys.CopyTo(result, 0);
|
|
return result;
|
|
}
|
|
static bool CanBeMerged(XmlNode node1, XmlNode node2, String requiredTagName)
|
|
{
|
|
if (node1.NodeType != XmlNodeType.Element || node2.NodeType != XmlNodeType.Element)
|
|
return false;
|
|
|
|
XmlElement element1 = (XmlElement)node1;
|
|
XmlElement element2 = (XmlElement)node2;
|
|
|
|
if (!StringEquals(requiredTagName, element1.Name)
|
|
|| !StringEquals(requiredTagName, element2.Name))
|
|
return false;
|
|
|
|
if (element1.Attributes.Count != element2.Attributes.Count)
|
|
return false;
|
|
|
|
for (int i = 0; i < element1.Attributes.Count; i++)
|
|
{
|
|
XmlAttribute attr1 = (XmlAttribute)element1.Attributes[i];
|
|
XmlAttribute attr2;
|
|
if (string.IsNullOrEmpty(attr1.NamespaceURI))
|
|
attr2 = (XmlAttribute)element2.Attributes.GetNamedItem(attr1.LocalName, attr1.NamespaceURI);
|
|
else
|
|
attr2 = (XmlAttribute)element2.Attributes.GetNamedItem(attr1.Name);
|
|
|
|
if (attr2 == null || !StringEquals(attr1.InnerText, attr2.InnerText))
|
|
//if (attr2 == null || !equals(attr1.getTextContent(), attr2.getTextContent()))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected static void CompactChildNodesR(XmlElement parentElement, String childTagName)
|
|
{
|
|
XmlNodeList childNodes = parentElement.ChildNodes;
|
|
for (int i = 0; i < childNodes.Count - 1; i++)
|
|
{
|
|
XmlNode child1 = childNodes[i];
|
|
XmlNode child2 = childNodes[i + 1];
|
|
if (!CanBeMerged(child1, child2, childTagName))
|
|
continue;
|
|
|
|
// merge
|
|
while (child2.ChildNodes.Count > 0)
|
|
child1.AppendChild(child2.FirstChild);
|
|
child2.ParentNode.RemoveChild(child2);
|
|
i--;
|
|
}
|
|
|
|
childNodes = parentElement.ChildNodes;
|
|
for (int i = 0; i < childNodes.Count - 1; i++)
|
|
{
|
|
XmlNode child = childNodes[i];
|
|
if (child is XmlElement)
|
|
{
|
|
CompactChildNodesR((XmlElement)child, childTagName);
|
|
}
|
|
}
|
|
}
|
|
static bool StringEquals(String str1, String str2)
|
|
{
|
|
return str1 == null ? str2 == null : str1.Equals(str2);
|
|
}
|
|
public static String GetBorderType(BorderCode borderCode)
|
|
{
|
|
if (borderCode == null)
|
|
throw new ArgumentNullException("borderCode is null");
|
|
|
|
switch (borderCode.BorderType)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
return "solid";
|
|
case 3:
|
|
return "double";
|
|
case 5:
|
|
return "solid";
|
|
case 6:
|
|
return "dotted";
|
|
case 7:
|
|
case 8:
|
|
return "dashed";
|
|
case 9:
|
|
return "dotted";
|
|
case 10:
|
|
case 11:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
case 16:
|
|
case 17:
|
|
case 18:
|
|
case 19:
|
|
return "double";
|
|
case 20:
|
|
return "solid";
|
|
case 21:
|
|
return "double";
|
|
case 22:
|
|
return "dashed";
|
|
case 23:
|
|
return "dashed";
|
|
case 24:
|
|
return "ridge";
|
|
case 25:
|
|
return "grooved";
|
|
default:
|
|
return "solid";
|
|
}
|
|
}
|
|
|
|
public static String GetBorderWidth(BorderCode borderCode)
|
|
{
|
|
int lineWidth = borderCode.LineWidth;
|
|
int pt = lineWidth / 8;
|
|
int pte = lineWidth - pt * 8;
|
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
stringBuilder.Append(pt);
|
|
stringBuilder.Append(".");
|
|
stringBuilder.Append(1000 / 8 * pte);
|
|
stringBuilder.Append("pt");
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
public static String GetBulletText(ListTables listTables,
|
|
Paragraph paragraph, int listId)
|
|
{
|
|
ListLevel listLevel = listTables.GetLevel(listId,
|
|
paragraph.GetIlvl());
|
|
|
|
if (listLevel.GetNumberText() == null)
|
|
return string.Empty;
|
|
|
|
StringBuilder bulletBuffer = new StringBuilder();
|
|
char[] xst = listLevel.GetNumberText().ToCharArray();
|
|
foreach (char element in xst)
|
|
{
|
|
if (element < 9)//todo:review_antony
|
|
{
|
|
ListLevel numLevel = listTables.GetLevel(listId, element);
|
|
|
|
int num = numLevel.GetStartAt();
|
|
bulletBuffer.Append(NumberFormatter.GetNumber(num,
|
|
listLevel.GetNumberFormat()));
|
|
|
|
if (numLevel == listLevel)
|
|
{
|
|
numLevel.SetStartAt(numLevel.GetStartAt() + 1);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bulletBuffer.Append(element);
|
|
}
|
|
}
|
|
|
|
byte follow = listLevel.GetTypeOfCharFollowingTheNumber();
|
|
switch (follow)
|
|
{
|
|
case 0:
|
|
bulletBuffer.Append("\t");
|
|
break;
|
|
case 1:
|
|
bulletBuffer.Append(" ");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return bulletBuffer.ToString();
|
|
}
|
|
|
|
public static String GetColor(int ico)
|
|
{
|
|
switch (ico)
|
|
{
|
|
case 1:
|
|
return "black";
|
|
case 2:
|
|
return "blue";
|
|
case 3:
|
|
return "cyan";
|
|
case 4:
|
|
return "green";
|
|
case 5:
|
|
return "magenta";
|
|
case 6:
|
|
return "red";
|
|
case 7:
|
|
return "yellow";
|
|
case 8:
|
|
return "white";
|
|
case 9:
|
|
return "darkblue";
|
|
case 10:
|
|
return "darkcyan";
|
|
case 11:
|
|
return "darkgreen";
|
|
case 12:
|
|
return "darkmagenta";
|
|
case 13:
|
|
return "darkred";
|
|
case 14:
|
|
return "darkyellow";
|
|
case 15:
|
|
return "darkgray";
|
|
case 16:
|
|
return "lightgray";
|
|
default:
|
|
return "black";
|
|
}
|
|
}
|
|
|
|
public static String GetOpacity(int argbValue)
|
|
{
|
|
int opacity = (int)((argbValue & 0xFF000000L) >> 24);// todo: review code, java use operater >>>
|
|
if (opacity == 0 || opacity == 0xFF)
|
|
return ".0";
|
|
|
|
return "" + (opacity / (float)0xFF);
|
|
}
|
|
|
|
public static String GetColor24(int argbValue)
|
|
{
|
|
if (argbValue == -1)
|
|
throw new ArgumentException("This colorref is empty");
|
|
|
|
int bgrValue = argbValue & 0x00FFFFFF;
|
|
int rgbValue = (bgrValue & 0x0000FF) << 16 | (bgrValue & 0x00FF00)
|
|
| (bgrValue & 0xFF0000) >> 16;
|
|
|
|
// http://www.w3.org/TR/REC-html40/types.html#h-6.5
|
|
switch (rgbValue)
|
|
{
|
|
case 0xFFFFFF:
|
|
return "white";
|
|
case 0xC0C0C0:
|
|
return "silver";
|
|
case 0x808080:
|
|
return "gray";
|
|
case 0x000000:
|
|
return "black";
|
|
case 0xFF0000:
|
|
return "red";
|
|
case 0x800000:
|
|
return "maroon";
|
|
case 0xFFFF00:
|
|
return "yellow";
|
|
case 0x808000:
|
|
return "olive";
|
|
case 0x00FF00:
|
|
return "lime";
|
|
case 0x008000:
|
|
return "green";
|
|
case 0x00FFFF:
|
|
return "aqua";
|
|
case 0x008080:
|
|
return "teal";
|
|
case 0x0000FF:
|
|
return "blue";
|
|
case 0x000080:
|
|
return "navy";
|
|
case 0xFF00FF:
|
|
return "fuchsia";
|
|
case 0x800080:
|
|
return "purple";
|
|
}
|
|
|
|
StringBuilder result = new StringBuilder("#");
|
|
String hex = rgbValue.ToString("x");
|
|
for (int i = hex.Length; i < 6; i++)
|
|
{
|
|
result.Append('0');
|
|
}
|
|
result.Append(hex);
|
|
return result.ToString();
|
|
}
|
|
|
|
public static String GetJustification(int js)
|
|
{
|
|
switch (js)
|
|
{
|
|
case 0:
|
|
return "start";
|
|
case 1:
|
|
return "center";
|
|
case 2:
|
|
return "end";
|
|
case 3:
|
|
case 4:
|
|
return "justify";
|
|
case 5:
|
|
return "center";
|
|
case 6:
|
|
return "left";
|
|
case 7:
|
|
return "start";
|
|
case 8:
|
|
return "end";
|
|
case 9:
|
|
return "justify";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
public static String GetLanguage(int languageCode)
|
|
{
|
|
switch (languageCode)
|
|
{
|
|
case 1024:
|
|
return string.Empty;
|
|
case 1033:
|
|
return "en-us";
|
|
case 1049:
|
|
return "ru-ru";
|
|
case 2057:
|
|
return "en-uk";
|
|
default:
|
|
logger.Log(POILogger.WARN, "Uknown or unmapped language code: ", languageCode);
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public static String GetListItemNumberLabel(int number, int format)
|
|
{
|
|
|
|
if (format != 0)
|
|
System.Console.WriteLine("NYI: toListItemNumberLabel(): " + format);
|
|
|
|
return number.ToString();
|
|
}
|
|
|
|
public static HWPFDocumentCore LoadDoc(DirectoryNode root)
|
|
{
|
|
try
|
|
{
|
|
return new HWPFDocument(root);
|
|
}
|
|
catch (OldWordFileFormatException exc)
|
|
{
|
|
return new HWPFOldDocument(root);
|
|
}
|
|
}
|
|
public static HWPFDocumentCore LoadDoc(POIFSFileSystem poifsFileSystem)
|
|
{
|
|
return LoadDoc( poifsFileSystem.Root );
|
|
}
|
|
public static HWPFDocumentCore LoadDoc(Stream inputStream)
|
|
{
|
|
return LoadDoc(HWPFDocumentCore.VerifyAndBuildPOIFS(inputStream));
|
|
}
|
|
public static HWPFDocumentCore LoadDoc(string docFile)
|
|
{
|
|
FileStream istream = new FileStream(docFile, FileMode.Open);
|
|
try
|
|
{
|
|
return LoadDoc(istream);
|
|
}
|
|
finally
|
|
{
|
|
if (istream != null)
|
|
istream.Close();
|
|
istream = null;
|
|
}
|
|
}
|
|
|
|
public static String SubstringBeforeLast(String str, String separator)
|
|
{
|
|
if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(separator))
|
|
{
|
|
return str;
|
|
}
|
|
int pos = str.LastIndexOf(separator);
|
|
if (pos == -1)
|
|
{
|
|
return str;
|
|
}
|
|
return str.Substring(0, pos);
|
|
}
|
|
|
|
}
|
|
}
|