229 lines
7.9 KiB
C#
229 lines
7.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Office.Core;
|
|
using Microsoft.Office.Interop.Word;
|
|
using UtilLib;
|
|
|
|
namespace AIProofread.Model
|
|
{
|
|
/// <summary>
|
|
/// 文档信息 包含文档相关数据、面板及对文档的相关操作
|
|
/// </summary>
|
|
public class DocumentInfo
|
|
{
|
|
private static char[] ArticleSpecialChars = new char[4] { '\a', '\r', '\v', '\f' };
|
|
|
|
//private Document currentDocument;
|
|
public Document CurrentDocument { get; set; }
|
|
private string fileName;
|
|
private string uniqueId;
|
|
|
|
private List<Range> ranges = new List<Range>();
|
|
public string UniqueId
|
|
{
|
|
get { return uniqueId; }
|
|
|
|
}
|
|
|
|
// 计算uniqueId
|
|
private void ComputeUniqueId()
|
|
{
|
|
string filename = CurrentDocument.FullName;
|
|
if (!string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(filename))
|
|
{
|
|
return;
|
|
}
|
|
// 通过文档路径生成唯一id
|
|
uniqueId = filename.GetHashCode().ToString();
|
|
}
|
|
|
|
// 初始化
|
|
public DocumentInfo(Document doc)
|
|
{
|
|
this.CurrentDocument = doc;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
ranges.Clear();
|
|
ComputeUniqueId();
|
|
}
|
|
|
|
//处理文档选区时 判断当前选区是否有校对项 有则选择该范围
|
|
public void ProcessSelectionChange(Selection s)
|
|
{
|
|
// 判断选区内是否有书签
|
|
if (s.Bookmarks != null && s.Bookmarks.Count > 0)
|
|
{
|
|
// 判断是否时点击 点击的起始和结束位置相同
|
|
if (s.Range.Start == s.Range.End)
|
|
{
|
|
//
|
|
var count = s.Bookmarks.Count;
|
|
// 原则只有一个书签
|
|
//foreach (Microsoft.Office.Interop.Word.Bookmark item in s.Bookmarks)
|
|
//{
|
|
// int proofreadId = Config.GetBookmarkIdByName(item.Name);
|
|
// if (proofreadId > 0)
|
|
// {
|
|
// //Bridge.bridge.SelectMarkById(proofreadId, 0);
|
|
// return;
|
|
// }
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 获取当前文档文本
|
|
public string GetText()
|
|
{
|
|
return CurrentDocument.Range().Text;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取当前选中文本
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string GetSelectedText()
|
|
{
|
|
return CurrentDocument.Range().Text;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取指定选区的文本
|
|
/// </summary>
|
|
/// <param name="range"></param>
|
|
/// <returns></returns>
|
|
public string GetRangeText(Range range)
|
|
{
|
|
string text = range?.Text;
|
|
return string.IsNullOrEmpty(text) ? "" : text;
|
|
}
|
|
|
|
// 定位所有的校对项
|
|
public void LocateAllProofreadItems(List<CorrectContext> list)
|
|
{
|
|
// 获取所有的校对项
|
|
//List<Range> proofreadItems = GetProofreadItems();
|
|
var prevOffset = 0;
|
|
foreach (var item in list)
|
|
{
|
|
if (item.CorrectItems != null && item.CorrectItems.Count > 0)
|
|
{
|
|
foreach (var correct in item.CorrectItems)
|
|
{
|
|
var range = LocateProofreadItem(correct,item,ref prevOffset);
|
|
if (range == null) continue;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查找偏移量
|
|
/// </summary>
|
|
private static readonly int INSERT_FIND_OFFSET = 5;
|
|
/// <summary>
|
|
/// 定位校对项
|
|
/// </summary>
|
|
/// <param name="correct">校对项</param>
|
|
/// <param name="ctx">校对上下文</param>
|
|
/// <param name="prevOffset">上一步的</param>
|
|
/// <returns></returns>
|
|
private Range LocateProofreadItem(CorrectItem correct, CorrectContext ctx, ref int prevOffset)
|
|
{
|
|
var document = CurrentDocument;
|
|
// 校对项的段落号超过文档的段落数,直接返回
|
|
if (ctx.ParagraphNumber > document.Paragraphs.Count) return null;
|
|
// 获取当前段落
|
|
var paragraph = document.Paragraphs[ctx.ParagraphNumber];
|
|
if (paragraph == null) return null;
|
|
|
|
|
|
var paraRange = paragraph.Range;
|
|
var paraText = paraRange.Text;
|
|
var paraStart = paraRange.Start;
|
|
|
|
var offset = paraStart + ctx.SentenceOffset;
|
|
//var cutLength = Math.Min(c.InsertLen, paraText.Length - offset);
|
|
var sentence = paraText.Substring(ctx.SentenceOffset, ctx.InsertLength);
|
|
if (sentence == ctx.Insert)
|
|
{ // 比对原始内容与校对原文是否一致
|
|
var range = document.Range(offset + correct.Start, offset + correct.End);
|
|
//
|
|
if (range.Text == correct.Origin) return range;
|
|
}
|
|
|
|
var originText = ctx.Insert;
|
|
// 如果是新增 则查找定位
|
|
if (correct.Tag == "i")
|
|
{
|
|
// 找前缀
|
|
var prefix1 = correct.Start > 2 ? (
|
|
correct.Start > INSERT_FIND_OFFSET
|
|
? originText.Substring(correct.Start - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
|
: originText.Substring(0, correct.Start)
|
|
) : null;
|
|
// 找后缀
|
|
var suffix1 = prefix1 == null ? (
|
|
correct.End + INSERT_FIND_OFFSET < originText.Length
|
|
? originText.Substring(correct.Start, INSERT_FIND_OFFSET)
|
|
: originText.Substring(correct.Start, originText.Length - correct.Start)
|
|
) : null;
|
|
// 偏移量
|
|
var start1 = prefix1 != null || suffix1 != null
|
|
? paraText.IndexOf(prefix1 ?? suffix1, prevOffset)
|
|
: -1;
|
|
if (start1 != -1)
|
|
{
|
|
var findOffset = paraStart + start1 + (prefix1 != null ? prefix1.Length : 0);
|
|
return document.Range(findOffset, findOffset);
|
|
}
|
|
}
|
|
|
|
// 执行查找
|
|
int wordStart = correct.Start;
|
|
int wordEnd = correct.End;
|
|
|
|
// 找前缀
|
|
var prefix = wordStart > 2 ? (
|
|
wordStart > INSERT_FIND_OFFSET
|
|
? originText.Substring(wordStart - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
|
: originText.Substring(0, wordStart)
|
|
) : null;
|
|
|
|
// 找后缀
|
|
var suffix = prefix == null ? (
|
|
wordEnd + INSERT_FIND_OFFSET < originText.Length
|
|
? originText.Substring(wordStart, INSERT_FIND_OFFSET)
|
|
: originText.Substring(wordStart, originText.Length - wordStart)
|
|
) : null;
|
|
var start = prefix != null || suffix != null
|
|
? paraText.IndexOf(prefix ?? suffix, prevOffset) // item.start +
|
|
: -1;
|
|
if (start != -1)
|
|
{
|
|
var findOffset = paraRange.Start + start + (prefix != null ? prefix.Length : 0);
|
|
var range = document.Range(findOffset, findOffset + wordEnd - wordStart);
|
|
if (range.Text == correct.Origin) { return range; }
|
|
}
|
|
// 直接定位查找
|
|
start = paraText.IndexOf(correct.Origin, prevOffset);
|
|
if (start == -1) return null;
|
|
// 定位整体开始位置
|
|
start = paraStart + start;
|
|
return document.Range(start, start + correct.Origin.Length);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|