public static CharacterPositionInfo FromCharIndex(IntPtr ssa_struct, int char_index, CharacterPositionType pos_type) { if ((pos_type == CharacterPositionType.AfterEnd) || (pos_type == CharacterPositionType.BeforeBeginning) || (pos_type == CharacterPositionType.ClusterPart)) { throw new ArgumentException("Illegal parameter.", "pos_type"); } var trailing = (pos_type == CharacterPositionType.TrailingEdge); var x_offset = 0; var res = NativeScript.ScriptStringCPtoX (ssa_struct, char_index, trailing, ref x_offset); if (res != NativeScript.S_OK) { Marshal.ThrowExceptionForHR(res); } var ret = new CharacterPositionInfo(); ret.CharIndex = char_index; ret.PositionType = pos_type; ret.Xoffset = x_offset; return(ret); }
public static CharacterPositionInfo FromXoffset(IntPtr ssa_struct, int x_offset) { var char_pos = 0; var char_trailing = 0; if (ssa_struct == IntPtr.Zero) { x_offset = 0; return(new CharacterPositionInfo()); } var res = NativeScript.ScriptStringXtoCP (ssa_struct, x_offset, ref char_pos, ref char_trailing); if (res != NativeScript.S_OK) { Marshal.ThrowExceptionForHR(res); } var chars_count = NativeScript.GetPcOutChars(ssa_struct); var ret = new CharacterPositionInfo(); ret.CharIndex = char_pos; ret.Xoffset = x_offset; if (char_trailing == 0) { if (char_pos == chars_count) { ret.PositionType = CharacterPositionType.AfterEnd; } else { ret.PositionType = CharacterPositionType.LeadingEdge; } } else if (char_trailing == 1) { if (char_pos == -1) { ret.PositionType = CharacterPositionType.BeforeBeginning; } else { ret.PositionType = CharacterPositionType.TrailingEdge; } } else { ret.PositionType = CharacterPositionType.ClusterPart; ret.OffsetToNextCaretPosition = char_trailing; } return(ret); }
/// <summary> /// dispose obligatory!! /// </summary> public void Dispose() { if (ssa_struct_ptr != IntPtr.Zero) { int res = NativeScript.ScriptStringFree(ref ssa_struct_ptr); if (res != 0) { Marshal.ThrowExceptionForHR(res); } } }
public void Render(int select_first, int select_last) { int res0 = NativeScript.ScriptStringOut (ssa_struct_ptr, ReferensePoint.X, ReferensePoint.Y, GDI_ExtTextOutOption.None, IntPtr.Zero, select_first, select_last, false); if (res0 != NativeScript.S_OK) { Marshal.ThrowExceptionForHR(res0); } }
public void PrepareLayout(IntPtr hdc, IntPtr char_buffer, int max_char_len, int max_width) { ssa_struct_ptr = NativeScript.ScriptStringAnalyseCall (hdc, char_buffer, max_char_len, max_width, tab_def); //сколько поместилось int chars_clipped = NativeScript.GetPcOutChars(ssa_struct_ptr); //просматриваем с конца для поиска разрыва линии IntPtr attr_buffer = NativeScript.ScriptString_pLogAttr(ssa_struct_ptr); int line_break_ind = -1; //если вся строка уместилась в линию if (chars_clipped == max_char_len) { line_break_ind = chars_clipped - 1; } //если вся строка не уместилась, ищем крайний с конца SoftBreak if (line_break_ind == -1) { LogicalCharacterAttribute attr = LogicalCharacterAttribute.None; for (int i = chars_clipped - 1; i > 0; i--) { attr = NativeScript.GetCharacterAttribute(attr_buffer, i); if ((attr & LogicalCharacterAttribute.SoftBreak) == LogicalCharacterAttribute.SoftBreak) { line_break_ind = i - 1; break; } } } //если и softBreak не найден, рвем по умещению if (line_break_ind == -1) { line_break_ind = chars_clipped - 1; } //если разрываем, вторично вызываем обссчет с новой длиной строки if (line_break_ind + 1 != max_char_len) { //освобождаем предыдущий ssa_sctuct_ptr int res3 = NativeScript.ScriptStringFree(ref ssa_struct_ptr); if (res3 != 0) { Marshal.ThrowExceptionForHR(res3); } //и обновляем ssa_struct_ptr = NativeScript.ScriptStringAnalyseCall (hdc, char_buffer, line_break_ind + 1, tab_def); } //debug //string actual_string = Marshal.PtrToStringAuto(char_buffer, line_break_ind + 1); //char[] actual_chars = actual_string.ToCharArray(); //заполняем свойства Extent = NativeScript.GetScriptStringExtent(ssa_struct_ptr); CharLength = line_break_ind + 1; //debug //if (Extent.Width == 0) //{ // int debug = 0; //} }
public LogicalCharacterAttribute GetLogicalAttribute(int char_index) { IntPtr log_attr_buffer = NativeScript.ScriptString_pLogAttr(ssa_struct_ptr); return(NativeScript.GetCharacterAttribute(log_attr_buffer, char_index)); }
public int FindPreviousLineStart(IDeviceContext dev) { //для обсчета строки будет нужен контекст IntPtr hdc = dev.GetHdc(); IntPtr font_ptr = Font.ToHfont(); IntPtr old_font = NativeGdi.SelectObject(hdc, font_ptr); uint old_align = NativeGdi.SetTextAlign(hdc, 0); int line_height = (int)Math.Ceiling(Font.GetHeight()); IntPtr char_buffer = IntPtr.Zero; bool EOF = false; int chars_filled = 0; int ret = 0; //получаем буфер символов начиная от -max_chars_in_line OnFetchCharsToScreen (-max_chars_in_line, false, out char_buffer, out chars_filled, out EOF); if (chars_filled <= 0) { //то есть и так находимся в начале ret = 0; } else { //получаем ssa_sctruct IntPtr ssa_scruct = NativeScript.ScriptStringAnalyseCall (hdc, char_buffer, chars_filled, SCRIPT_TABDEF.GetDefault()); //берем logical wodths int[] widths = NativeScript.GetLogicalWidths(ssa_scruct); //освобождаем ssa_scruct NativeScript.ScriptStringFree(ref ssa_scruct); //суммируем полученные ширины символов с конца, пока не превысим //максимальную ширину или не встретим второй hard break char current_char = '\0'; int current_width = 0; int finding_ind = -1; for (int i = chars_filled - 1; i >= 0; i--) { current_char = get_char_from_buffer(char_buffer, i); current_width = current_width + widths[i]; //проверяем ширину if (current_width > Bounds.Width) { finding_ind = i; break; } //проверяем hard break (\n \r \r\n) начиная со второго шага if (i != chars_filled - 1) { if (current_char == '\n') { if (((i - 1) >= 0) && (get_char_from_buffer(char_buffer, i - 1) == '\r')) { finding_ind = i; break; } finding_ind = i; break; } else if ((current_char == '\r') && (i < chars_filled - 2)) { finding_ind = i; break; } } } //finding_ind теперь соответствует концу предыщей строки ret = -(chars_filled - finding_ind - 1); } font_ptr = NativeGdi.SelectObject(hdc, old_font); NativeGdi.DeleteObject(font_ptr); NativeGdi.SetTextAlign(hdc, old_align); dev.ReleaseHdc(); return(ret); }