# Text

> Select, find, replace and format text in C# with ServerTextControl: input positions, regular expressions, headers and text frames, inline styles and lines.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Document Processing > Text
- **9572 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/text/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/text/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/text/llms-full.txt

---

Replacing placeholders, highlighting amounts and reading what a document says all start with its text. With `ServerTextControl`, you select text by its position, find and replace it in the main text and in headers, footers and text frames, format characters, define inline styles and read the text line by line.

[Create a Document](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-processing/create/llms-full.txt) introduces the input position, the `Selection` class and twips, the unit of font sizes. Alignment, indents, paragraph styles and lists are described in [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/llms-full.txt). Each example below is a complete *Program.cs* of a console application.

### How Text Positions Work

[ServerTextControl.Text](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/text-property/llms-full.txt) gets or sets the text of the document. To work with part of the text, you select it:

- **Positions start at 0.** [Selection.Start](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/start-property/llms-full.txt) is the position of the first selected character, and the first position of the text is 0. [Selection.Length](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/length-property/llms-full.txt) is the number of selected characters. With a length of 0, nothing is selected and `Start` is the input position.
- **Select a range.** [ServerTextControl.Select](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/select-method/llms-full.txt) takes a start position and a length. [SelectAll](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/selectall-method/llms-full.txt) selects the whole text, and [SelectWord](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/selectword-method/llms-full.txt) the word at the input position. Setting `Selection.Start` alone keeps the current length.
- **Element positions start at 1.** `Paragraph.Start`, `Line.Start` and `TableCell.Start` are one-based. Subtract 1 before you pass them to `Select`.
- **Tables** are selected with their own methods, such as `TableCell.Select`, which [Tables](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/tables/llms-full.txt) describes.

### Move and Read the Input Position

[ServerTextControl.InputPosition](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/inputposition-property/llms-full.txt) sets the input position, where text, fields and other elements are inserted, and tells where it is. The following program moves it to a word of *Documents/sample.docx* and prints the page, section, line and column there:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/sample.docx", StreamType.WordprocessingML);

    int position = tx.Find("Total");

    if (position != -1)
    {
        // Move the input position to a zero-based text position
        tx.InputPosition = new InputPosition(position);

        InputPosition input = tx.InputPosition;
        Console.WriteLine($"Text position {input.TextPosition}: page {input.Page}, " +
            $"section {input.Section} (page {input.PageInSection} of the section), " +
            $"line {input.Line}, column {input.Column}");
    }
}
```

The [InputPosition](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/llms-full.txt) object you read has these properties:

| Property | Returns |
|---|---|
| [TextPosition](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/textposition-property/llms-full.txt) | The text position, starting at 0 |
| [Page](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/page-property/llms-full.txt), [PageInSection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/pageinsection-property/llms-full.txt) | The page number in the document and in the section |
| [Section](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/section-property/llms-full.txt) | The section number; the first section is 1 |
| [Line](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/line-property/llms-full.txt) | The line number on the page; the first line on top of the page is 1 |
| [Column](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/column-property/llms-full.txt) | The position in the line; the position in front of the first character is 0 |
| [Location](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/location-property/llms-full.txt) | The geometric location in twips, from the top-left corner of the document |

The [InputPosition constructor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inputposition/constructor/llms-full.txt) has further overloads. `new InputPosition(1, 3, 0)` stands for page 1, line 3, in front of the first character. `new InputPosition(position, TextFieldPosition.OutsideTextField)` decides whether a position at the start or end of a field with a doubled input position is inside or outside the field, with a value of [TextFieldPosition](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textfieldposition/enumeration/llms-full.txt).

### Select and Format Characters

Once text is selected, the properties of [ServerTextControl.Selection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/selection-property/llms-full.txt) change its character attributes. The following program formats the first words of a sentence and two amounts that it finds in the text:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "Order Confirmation: The total of 1,250.00 EUR is due on delivery. Regular price: 1,400.00 EUR.";

    // Select 19 characters from position 0: "Order Confirmation:"
    tx.Select(0, 19);
    tx.Selection.Bold = true;
    tx.Selection.FontName = "Arial";
    tx.Selection.FontSize = 280; // 280 twips = 14 pt
    tx.Selection.ForeColor = System.Drawing.Color.DarkBlue;

    // Find a text and format it
    string amount = "1,250.00 EUR";
    int position = tx.Find(amount);

    if (position != -1)
    {
        tx.Select(position, amount.Length);
        tx.Selection.TextBackColor = System.Drawing.Color.Yellow;
        tx.Selection.Underline = FontUnderlineStyle.Doubled;
    }

    string oldPrice = "1,400.00 EUR";
    position = tx.Find(oldPrice);

    if (position != -1)
    {
        tx.Select(position, oldPrice.Length);
        tx.Selection.Strikeout = true;
        tx.Selection.Italic = true;
    }

    tx.Save("formatted-text.docx", StreamType.WordprocessingML);
}
```

[Find](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/find-method/llms-full.txt) returns the position of the text, or `-1` if the text isn't found, and `Select` then selects it for formatting. The character attributes of a [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/llms-full.txt):

| Property | Sets | Default |
|---|---|---|
| [Bold](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/bold-property/llms-full.txt), [Italic](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/italic-property/llms-full.txt), [Strikeout](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/strikeout-property/llms-full.txt) | Bold, italic and struck-out text | `false` |
| [Underline](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/underline-property/llms-full.txt) | `None`, `Single`, `Doubled`, `SingleWordsOnly` or `DoubledWordsOnly` | `None` |
| [FontName](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/fontname-property/llms-full.txt), [FontSize](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/fontsize-property/llms-full.txt) | The font and its size in twips | Arial, 200 twips (10 pt) |
| [ForeColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/forecolor-property/llms-full.txt), [TextBackColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/textbackcolor-property/llms-full.txt) | The text color and the background color of the text, as `System.Drawing.Color` | System colors |
| [Baseline](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/baseline-property/llms-full.txt) | A shift of the text in twips, from -960 to 960: positive values raise the text, negative values lower it | `0` |
| [AutoBaseline](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/autobaseline-property/llms-full.txt) | Superscript or subscript text, scaled and shifted with values from the font | `None` |
| [Capitals](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/capitals-property/llms-full.txt) | `Capitals`, `SmallCapitals` or `PetiteCapitals` | `None` |
| [CharacterSpacing](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/characterspacing-property/llms-full.txt) | Twips added to the space of each character; negative values reduce it | `0` |
| [CharacterScaling](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/characterscaling-property/llms-full.txt) | The character width in percent of the average width | `100` |
| [Culture](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/culture-property/llms-full.txt) | The language of the text, as a `CultureInfo` | `null`, the neutral culture |

When a selection contains different values of an attribute, the property returns its default, and `FontName` an empty string. [IsCommonValueSelected](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/iscommonvalueselected-method/llms-full.txt) tells whether the whole selection has the same value. It takes a value of [Selection.Attribute](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/attribute-enumeration/llms-full.txt), such as `Bold`, `FontName`, `FontSize` or `ForeColor`, and other overloads take the `Attribute` enumerations of `ParagraphFormat`, `ListFormat`, `SectionFormat`, `PageMargins` and `PageSize`:

```csharp
tx.SelectAll();

// true if all selected text uses one font
if (tx.Selection.IsCommonValueSelected(Selection.Attribute.FontName))
{
    Console.WriteLine($"Font: {tx.Selection.FontName}");
}
else
{
    Console.WriteLine("The selection uses more than one font");
}
```

A few methods change the selected text in one step: [ChangeCapitalization](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/changecapitalization-method/llms-full.txt) changes the case of letters, [GrowFont](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/growfont-method/llms-full.txt) and [ShrinkFont](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/shrinkfont-method/llms-full.txt) change all font sizes, and [RemoveFormatting](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/removeformatting-method/llms-full.txt) resets the character attributes to their defaults.

#### Control-Level Character Properties

`ServerTextControl` has character properties of its own, besides those of the selection. They belong to the control, not to a selected text:

| Property | Sets | Reset with |
|---|---|---|
| [Font](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/font-property/llms-full.txt) | The font of the control, 10 pt Arial by default | [ResetFont](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/resetfont-method/llms-full.txt) |
| [ForeColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/forecolor-property/llms-full.txt) | The foreground color of the control | [ResetForeColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/resetforecolor-method/llms-full.txt) |
| [TextBackColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/textbackcolor-property/llms-full.txt) | The background color of the text | [ResetTextBackColor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/resettextbackcolor-method/llms-full.txt) |
| [FontUnderlineStyle](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/fontunderlinestyle-property/llms-full.txt) | The style of underlined text; whether text is underlined is set by `Font` | — |
| [Baseline](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/baseline-property/llms-full.txt) | A baseline shift in twips, from -960 to 960 | — |

To format part of a document, use the properties of `Selection` shown above.

### Insert Formatted Text

When you build text piece by piece, prepare a `Selection` object with the text and its attributes and assign it to `tx.Selection`. The text is inserted at the input position with its attributes in one step, which is faster than inserting the text first and formatting it afterward:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    // Each Selection object is inserted at the input position
    tx.Selection = new Selection { Text = "Office space: 120 m" };
    tx.Selection = new Selection { Text = "2", AutoBaseline = AutoBaseline.Superscript };
    tx.Selection = new Selection { Text = "\r\n" };

    tx.Selection = new Selection { Text = "Terms and Conditions\r\n", Capitals = Capitals.SmallCapitals };

    // 40 twips added to each character
    tx.Selection = new Selection { Text = "Expanded character spacing\r\n", CharacterSpacing = 40 };

    // 80 percent of the average character width
    tx.Selection = new Selection { Text = "Condensed characters\r\n", CharacterScaling = 80 };

    tx.Selection = new Selection
    {
        Text = "Dieser Absatz ist deutsch.\r\n",
        Culture = new System.Globalization.CultureInfo("de-DE")
    };

    tx.Save("character-attributes.docx", StreamType.WordprocessingML);
}
```

The blog article [Speed Up Document Generation by Factor 2 Using Selection Objects](https://www.textcontrol.com/blog/2026/07/17/speed-up-document-generation-selection-objects-dotnet-csharp/) measures the difference.

### Find and Replace Text

`Find(string)` searches the main text from the beginning. The overload `Find(string text, int start, FindOptions options)` starts at a position, or at the input position with `-1`, and takes values of [FindOptions](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/findoptions/enumeration/llms-full.txt), which can be combined:

| Value | Finds |
|---|---|
| `MatchCase` | Only text with the same uppercase and lowercase letters |
| `MatchWholeWord` | Only whole words |
| `Reverse` | Searches from the end toward the beginning |
| `NoHighlight`, `NoMessageBox` | Doesn't highlight the found text and shows no message boxes |

To replace every occurrence of a placeholder, find it, select it, set the new text and continue behind the inserted text:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "%%company_name%% confirms the order. Questions? Contact %%company_name%%.";

    int count = ReplaceAll(tx, "%%company_name%%", "Text Control, LLC");
    Console.WriteLine($"{count} occurrences replaced");

    tx.Save("replaced.docx", StreamType.WordprocessingML);
}

// Replaces every occurrence of searchText in the main text
static int ReplaceAll(ServerTextControl tx, string searchText, string replacementText)
{
    int count = 0;
    int start = 0;
    int position;

    while ((position = tx.Find(searchText, start, FindOptions.MatchCase)) != -1)
    {
        tx.Select(position, searchText.Length);
        tx.Selection.Text = replacementText;

        // Continue behind the inserted text
        start = position + replacementText.Length;
        count++;
    }

    return count;
}
```

To use a document instead of the sample text, replace the `tx.Text` line with `tx.Load("Documents/sample.docx", StreamType.WordprocessingML);`. The blog article [High-Performance Text Replacement in Large DOCX Files](https://www.textcontrol.com/blog/2025/07/30/high-performance-text-replacement-in-large-docx-files-using-csharp-dotnet/) replaces text in an 80-page document this way.

Placeholder text works for simple cases. For templates that are filled with data, merge fields are the structured alternative; see [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/fields/llms-full.txt).

### Find Text With Regular Expressions

`Find` searches for a fixed text. Patterns such as invoice numbers, dates or email addresses are found with a regular expression of .NET in the text of the document. In `ServerTextControl.Text`, every paragraph ends with a carriage return and a line feed, while a document position counts a paragraph break as one character. Replace each `\r\n` with `\n`, and the index of a match is its position in the document:

```csharp
using System.Drawing;
using System.Text.RegularExpressions;
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "Payment reminder\r\n" +
              "Invoice INV-2025-001 of May 27, 2025 is due.\r\n" +
              "Invoice INV-2025-014 of June 3, 2025 is due as well.";

    // One character per paragraph break, as in document positions
    string text = tx.Text.Replace("\r\n", "\n");

    Regex invoiceNumber = new Regex(@"INV-\d{4}-\d{3}");

    foreach (Match match in invoiceNumber.Matches(text))
    {
        tx.Select(match.Index, match.Length);
        tx.Selection.Bold = true;
        tx.Selection.TextBackColor = Color.Yellow;

        Console.WriteLine($"{match.Value} at position {match.Index}");
    }

    tx.Save("reminder.pdf", StreamType.AdobePDF);
}
```

The program prints the two invoice numbers with their positions and saves them bold on a yellow background. The same works for text in table cells. Formatting keeps the positions valid; if you replace matches with a text of another length, go through the matches from the last to the first. The blog article [Advanced Smart Search with Regular Expressions in .NET C#](https://www.textcontrol.com/blog/2025/01/29/advanced-smart-search-with-regular-expressions-in-net-csharp/) lists patterns for email addresses, URLs, phone numbers and dates.

### Replace Text in Headers, Footers and Text Frames

`ServerTextControl.Find` searches only the main text. Headers, footers and text frames are text parts of their own. [ServerTextControl.TextParts](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/textparts-property/llms-full.txt) contains all of them: the main text first, then the text frames, headers and footers. Each text part implements [IFormattedText](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/iformattedtext/llms-full.txt), which has its own [Find](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/iformattedtext/find-method/llms-full.txt) method and [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/iformattedtext/selection-property/llms-full.txt):

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "This contract is made with %%company_name%%.";

    tx.HeadersAndFooters.Add(HeaderFooterType.Header);
    HeaderFooter header = tx.HeadersAndFooters.GetItem(HeaderFooterType.Header);
    header.Selection.Text = "%%company_name%% - Confidential";

    string searchText = "%%company_name%%";
    string replacementText = "Text Control, LLC";
    int count = 0;

    // The main text, text frames, headers and footers
    foreach (IFormattedText textPart in tx.TextParts)
    {
        int start = 0;
        int position;

        while ((position = textPart.Find(searchText, start, FindOptions.MatchCase)) != -1)
        {
            textPart.Selection = new Selection(position, searchText.Length);
            textPart.Selection.Text = replacementText;

            start = position + replacementText.Length;
            count++;
        }
    }

    Console.WriteLine($"{count} occurrences replaced");
    tx.Save("replaced.pdf", StreamType.AdobePDF);
}
```

The program replaces the placeholder in the main text and in the header, and prints "2 occurrences replaced".

### Use Inline Styles

An [InlineStyle](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inlinestyle/llms-full.txt) is a named set of character attributes for words or phrases within a paragraph. When you change the style, all text that uses it changes. The following program defines a style for deadlines, applies it to every occurrence of a date and then adds a background color to the style:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "Please return the signed contract by March 31. Submissions after March 31 are not accepted.";

    // Define an inline style and add it to the document
    InlineStyle deadline = new InlineStyle("Deadline");
    deadline.Bold = true;
    deadline.ForeColor = System.Drawing.Color.DarkRed;
    tx.InlineStyles.Add(deadline);

    // Apply the style to every occurrence of the date
    string date = "March 31";
    int start = 0;
    int position;

    while ((position = tx.Find(date, start, FindOptions.MatchCase)) != -1)
    {
        tx.Select(position, date.Length);
        tx.Selection.FormattingStyle = "Deadline";
        start = position + date.Length;
    }

    // Change the style: all text that uses it changes
    InlineStyle style = tx.InlineStyles.GetItem("Deadline");
    style.TextBackColor = System.Drawing.Color.LightYellow;
    style.Apply();

    tx.Save("inline-style.docx", StreamType.WordprocessingML);
}
```

The code works as follows:

- The [InlineStyle constructor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inlinestyle/constructor/llms-full.txt) with a name creates a style based on the root style `[Normal]`. Another overload takes the name of a base style.
- [InlineStyles.Add](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inlinestylecollection/add-method/llms-full.txt) adds the style to the document and returns `true` if it was added.
- [Selection.FormattingStyle](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/formattingstyle-property/llms-full.txt) applies the style to the selected text by its name.
- [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/inlinestylecollection/getitem-method/llms-full.txt) returns a style by its name, or `null` if the document has no such style. After changing a style, [Apply](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/formattingstyle/apply-method/llms-full.txt) applies its attributes to the document.

Text with an inline style keeps the attributes of its paragraph style except those that the inline style sets. [Selection.RemoveInlineStyles](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/removeinlinestyles-method/llms-full.txt) resets the selected text to the attributes of its paragraph style.

### Insert Special Characters

`\r\n` in a text ends a paragraph. [TextCharCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textcharcollection/add-method/llms-full.txt) of [ServerTextControl.TextChars](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/textchars-property/llms-full.txt) inserts other control characters, with a value of [ControlChars](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/controlchars/enumeration/llms-full.txt), at the input position or at a text position:

| Value | Inserts |
|---|---|
| `LineBreak` | A line break within the paragraph |
| `PageBreak` | A page break |
| `ColumnBreak` | A break to the next page column |
| `Tab` | A tab character |
| `NonBreakingSpace` | A space at which a line isn't broken |
| `NonVisibleHyphen` | A hyphen that is shown only when the word is broken at this position |

For example, `tx.TextChars.Add(ControlChars.LineBreak);` inserts a line break at the input position. A heading that must start on a new page is better served by the paragraph attribute `PageBreakBefore`, described in [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/llms-full.txt), because a forced page break can leave an empty page when the text before it changes.

### Read the Text of a Document

`ServerTextControl` gives you the text of a document as a whole, by lines and by characters. The following program prints the text of *Documents/sample.docx*, its lines with their page numbers and its first line as HTML:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/sample.docx", StreamType.WordprocessingML);

    Console.WriteLine(tx.Text);
    Console.WriteLine($"{tx.TextChars.Count} characters, {tx.Lines.Count} lines, {tx.Paragraphs.Count} paragraphs, {tx.Pages} pages");

    foreach (Line line in tx.Lines)
    {
        Console.WriteLine($"Page {line.Page}, line {line.Number}: {line.Text}");
    }

    // Characters and lines are numbered from 1
    Console.WriteLine($"First character: {tx.TextChars[1].Char}");

    // Line.Start is one-based, Select expects a zero-based position
    Line firstLine = tx.Lines[1];
    tx.Select(firstLine.Start - 1, firstLine.Length);

    string html;
    tx.Selection.Save(out html, StringStreamType.HTMLFormat);
    Console.WriteLine(html);
}
```

The code works as follows:

- [ServerTextControl.Lines](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/lines-property/llms-full.txt) contains the lines of the main text. Each [Line](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/llms-full.txt) has its [Text](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/text-property/llms-full.txt), its [Number](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/number-property/llms-full.txt) and the [Page](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/page-property/llms-full.txt) it's on.
- `TextChars` contains the characters of the main text, and the [Char](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textchar/char-property/llms-full.txt) property of each is the character.
- [ServerTextControl.Pages](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/pages-property/llms-full.txt) is the number of pages.
- [Selection.Save](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/selection/save-method/llms-full.txt) saves the selected text, here as an HTML string. It also saves to files and byte arrays in the other formats.

#### Positions and Sizes of Lines and Characters

Lines and characters also tell where they are on the page, in twips from the top-left corner of the document. The following lines, added to the program above, print the geometry of the first line and of its first character and save one line as HTML:

```csharp
// The line at a zero-based text position
Line line = tx.Lines.GetItem(0);
Console.WriteLine($"Baseline {line.Baseline}, bounds {line.TextBounds}");

TextChar character = tx.TextChars[line.Start];
Console.WriteLine($"'{character.Char}' at {character.Bounds}");

// Save a single line without selecting it
string lineHtml;
line.Save(out lineHtml, StringStreamType.HTMLFormat);
```

What the members return:

- [LineCollection.GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/linecollection/getitem-method/llms-full.txt) returns the line at a zero-based text position, or `null`. [Line.Start](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/start-property/llms-full.txt) is the one-based number of the line's first character, which is also its index in `TextChars`.
- [Line.Baseline](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/baseline-property/llms-full.txt) is the vertical position of the line's baseline, and [Line.TextBounds](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/textbounds-property/llms-full.txt) the rectangle around its text.
- [TextChar.Bounds](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textchar/bounds-property/llms-full.txt) is the rectangle around a character, and [TextChar.Number](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textchar/number-property/llms-full.txt) its one-based number.
- [Line.Save](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/line/save-method/llms-full.txt) saves the text of the line as a string or a byte array in a format, like `Selection.Save`.
- [TextCharCollection.Remove](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textcharcollection/remove-method/llms-full.txt) removes a character, also a control character. It returns `false` for characters other formatting depends on, such as the end of a table cell.

[TextCharCollection.GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/textcharcollection/getitem-method/llms-full.txt) and the `System.Drawing.Point` overload of `LineCollection.GetItem` find a character or a line at a geometric position instead. They expect the point in pixels from the top-left corner of the control, not in twips, and `GetItem` of `TextChars` returns the nearest character when its second parameter is `true`.

To get the plain text of a whole document, save it with `StringStreamType.PlainText`, as [Save as DOCX and PDF](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-processing/save-docx-pdf/#save-other-formats) shows.

### Next Steps

- [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/llms-full.txt): align paragraphs, set their spacing and create paragraph styles and lists.
- [Fields](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/fields/llms-full.txt): mark text that your code finds and changes later.
- [Creating Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/creating/llms-full.txt): build documents from text, documents and other content.
- [Pages](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/pages/llms-full.txt): find the page of a text and read the text page by page.
- [Editing Text](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/editing-text/llms-full.txt) in the Document Editor: change text from JavaScript.

---

## Nearby

- **Previous:** [Saving and Converting Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/saving-converting/llms-full.txt)
- **Next:** [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/llms-full.txt)
