/// <summary> /// 從堆疊中讀取字元,並轉成點字。只處理中文字和中文標點符號。 /// </summary> /// <param name="charStack">字元堆疊。</param> /// <param name="context">情境物件。</param> /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } bool done = false; char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; int idx = 0; int chineseStartIdx = -1; int chineseEndIdx = -1; while (!done && charStack.Count > 0) { ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; // 小於跟大於符號是情境標籤,不處理(交由 ControlTagConverter 負責)。 if (ch == '<' || ch == '>') { break; } // 全形英文字母要轉成半形,並且由英文點字元件處理。 if (CharHelper.IsFullShapeLetter(ch)) { charStack.Pop(); ch = CharHelper.FullShapeToAsciiLetter(ch); charStack.Push(ch); break; } // 全形數字要轉成半形,並且由英文點字元件處理。 if (CharHelper.IsFullShapeDigit(ch)) { charStack.Pop(); ch = CharHelper.FullShapeToAsciiDigit(ch); charStack.Push(ch); break; } text = ch.ToString(); // 處理雙字元的標點符號。 if (ch == '…' || ch == '-' || ch == '─' || ch == '╴' || ch == '﹏') { // 讀下一個字元,若是相同符號,則可略過;若不同,則下次迴圈仍需處理。 if (charStack.Count >= 2) { charStack.Pop(); char ch2 = charStack.Pop(); if (ch2 == ch) // 如果是連續兩個刪節號或破折號。 { text = text + text; isExtracted = true; } else { // 不是連續符號,把之前取出的字元放回堆疊。 charStack.Push(ch2); charStack.Push(ch); isExtracted = false; } } } else if (ch == '[') // 處理以半形中括號包住的特殊符號. { if (charStack.Count >= 3) { charStack.Pop(); char ch2 = charStack.Pop(); char ch3 = charStack.Pop(); if (ch3 == ']' && (ch2 == '↗' || ch2 == '↘')) { text = text + ch2.ToString() + ch3.ToString(); isExtracted = true; } else { // 不是中括號包住的特殊符號,把之前取出的字元放回堆疊。 charStack.Push(ch3); charStack.Push(ch2); charStack.Push(ch); isExtracted = false; } } } /* 特殊數字編號【1】已經改成直接定義在 xml 檔案 (2009-6-22). * else if (ch == '【') * { // 特殊數字編號,用於選擇題的答案編號,例如: 【1】,見 ChineseBrailleTable.xml。 * if (charStack.Count >= 3) * { * charStack.Pop(); * char ch2 = charStack.Pop(); * char ch3 = charStack.Pop(); * if (Char.IsDigit(ch2) && ch3 == '】') // 無論是半形或全形數字,Char.IsDigit 都會傳回 true。 * { * isExtracted = true; * if (CharHelper.IsFullShapeDigit(ch2)) * { * ch2 = CharHelper.FullShapeToAsciiDigit(ch2); * } * text = ch.ToString() + ch2.ToString() + ch3.ToString(); * } * else * { * charStack.Push(ch3); * charStack.Push(ch2); * charStack.Push(ch); * isExtracted = false; * } * } * } */ brWord = InternalConvert(text); if (brWord == null) { break; } if (!isExtracted) { charStack.Pop(); } if (!StrHelper.IsEmpty(text)) // 避免將空白字元也列入 Chinese。 { brWord.Language = BrailleLanguage.Chinese; } ApplyBrailleConfig(brWord); // 根據組態檔的設定調整點字轉換結果。 if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWordList.Add(brWord); // 記錄連續中文字元,以修正破音字的注音字根。 if (brWord.Text.IsCJK()) // 如果是中文字元,要記錄連續的中文字元區間 { if (chineseStartIdx < 0) { chineseStartIdx = idx; chineseEndIdx = idx; } else { chineseEndIdx = idx; } } else // 不是中文字,則把之前紀錄的連續中文字取出,並修正其注音字根 { FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx); chineseStartIdx = -1; chineseEndIdx = -1; } idx++; } // 處理這段中文字的最後一段連續中文字。 if (chineseStartIdx >= 0) { FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx); } return(brWordList); }