// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
//
// Authors:
// Rolf Bjarne Kvinge <RKvinge@novell.com>
//
//
/*
Mask language:
0 Digit, required. This element will accept any single digit between 0 and 9.
9 Digit or space, optional.
# Digit or space, optional. If this position is blank in the mask, it will be rendered as a space in the Text property. Plus (+) and minus (-) signs are allowed.
L Letter, required. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z] in regular expressions.
? Letter, optional. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z]? in regular expressions.
& Character, required. If the AsciiOnly property is set to true, this element behaves like the "L" element.
C Character, optional. Any non-control character. If the AsciiOnly property is set to true, this element behaves like the "?" element.
* LAMESPEC: A is REQUIRED, not optional.
A Alphanumeric, optional. If the AsciiOnly property is set to true, the only characters it will accept are the ASCII letters a-z and A-Z.
a Alphanumeric, optional. If the AsciiOnly property is set to true, the only characters it will accept are the ASCII letters a-z and A-Z.
. Decimal placeholder. The actual display character used will be the decimal symbol appropriate to the format provider, as determined by the control's FormatProvider property.
, Thousands placeholder. The actual display character used will be the thousands placeholder appropriate to the format provider, as determined by the control's FormatProvider property.
: Time separator. The actual display character used will be the time symbol appropriate to the format provider, as determined by the control's FormatProvider property.
/ Date separator. The actual display character used will be the date symbol appropriate to the format provider, as determined by the control's FormatProvider property.
$ Currency symbol. The actual character displayed will be the currency symbol appropriate to the format provider, as determined by the control's FormatProvider property.
< Shift down. Converts all characters that follow to lowercase.
> Shift up. Converts all characters that follow to uppercase.
| Disable a previous shift up or shift down.
\ Escape. Escapes a mask character, turning it into a literal. "\\" is the escape sequence for a backslash.
* */
#if NET_2_0
using System.Globalization;
using System.Collections;
using System.Diagnostics;
using System.Text;
namespace System.ComponentModel{
public class MaskedTextProvider : ICloneable
{
#region Private fields
private bool allow_prompt_as_input;
private bool ascii_only;
private CultureInfo culture;
private bool include_literals;
private bool include_prompt;
private bool is_password;
private string mask;
private char password_char;
private char prompt_char;
private bool reset_on_prompt;
private bool reset_on_space;
private bool skip_literals;
private EditPosition [] edit_positions;
private static char default_prompt_char = '_';
private static char default_password_char = char.MinValue;
#endregion
#region Private classes
private enum EditState {
None,
UpperCase,
LowerCase
}
private enum EditType {
DigitRequired, // 0
DigitOrSpaceOptional, // 9
DigitOrSpaceOptional_Blank, // #
LetterRequired, // L
LetterOptional, // ?
CharacterRequired, // &
CharacterOptional, // C
AlphanumericRequired, // A
AlphanumericOptional, // a
DecimalPlaceholder, // .
ThousandsPlaceholder, // ,
TimeSeparator, // :
DateSeparator, // /
CurrencySymbol, // $
Literal
}
private class EditPosition {
public MaskedTextProvider Parent;
public EditType Type;
public EditState State;
public char MaskCharacter;
public char input;
public void Reset ()
{
input = char.MinValue;
}
internal EditPosition Clone () {
EditPosition result = new EditPosition ();
result.Parent = Parent;
result.Type = Type;
result.State = State;
result.MaskCharacter = MaskCharacter;
result.input = input;
return result;
}
public char Input {
get {
return input;
}
set {
switch (State) {
case EditState.LowerCase:
input = char.ToLower (value, Parent.Culture);
break;
case EditState.UpperCase:
input = char.ToUpper (value, Parent.Culture);
break;
default:// case EditState.None:
input = value;
break;
}
}
}
public bool IsAscii (char c)
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}
public bool Match (char c, out MaskedTextResultHint resultHint, bool only_test)
{
if (!MaskedTextProvider.IsValidInputChar (c)) {
resultHint = MaskedTextResultHint.InvalidInput;
return false;
}
if (Parent.ResetOnSpace && c == ' ' && Editable) {
resultHint = MaskedTextResultHint.CharacterEscaped;
if (FilledIn) {
resultHint = MaskedTextResultHint.Success;
if (!only_test && input != ' ') {
switch (Type) {
case EditType.AlphanumericOptional:
case EditType.AlphanumericRequired:
case EditType.CharacterOptional:
case EditType.CharacterRequired:
Input = c;
break;
default:
Input = char.MinValue;
break;
}
}
}
return true;
}
if (Type == EditType.Literal && MaskCharacter == c && Parent.SkipLiterals) {
resultHint = MaskedTextResultHint.Success;
return true;
}
if (!Editable) {
resultHint = MaskedTextResultHint.NonEditPosition;
return false;
}
switch (Type) {
case EditType.AlphanumericOptional:
case EditType.AlphanumericRequired:
if (char.IsLetterOrDigit (c)) {
if (Parent.AsciiOnly && !IsAscii (c)) {
resultHint = MaskedTextResultHint.AsciiCharacterExpected;
return false;
} else {
if (!only_test) {
Input = c;
}
resultHint = MaskedTextResultHint.Success;
return true;
}
} else {
resultHint = MaskedTextResultHint.AlphanumericCharacterExpected;
return false;
}
case EditType.CharacterOptional:
case EditType.CharacterRequired:
if (Parent.AsciiOnly && !IsAscii (c)) {
resultHint = MaskedTextResultHint.LetterExpected;
return false;
} else if (!char.IsControl (c)) {
if (!only_test) {
Input = c;
}
resultHint = MaskedTextResultHint.Success;
return true;
} else {
resultHint = MaskedTextResultHint.LetterExpected;
return false;
}
case EditType.DigitOrSpaceOptional:
case EditType.DigitOrSpaceOptional_Blank:
if (char.IsDigit (c) || c == ' ') {
if (!only_test) {
Input = c;
}
resultHint = MaskedTextResultHint.Success;
return true;
} else {
resultHint = MaskedTextResultHint.DigitExpected;
return false;
}
case EditType.DigitRequired:
if (char.IsDigit (c)) {
if (!only_test) {
Input = c;
}
resultHint = MaskedTextResultHint.Success;
return true;
} else {
resultHint = MaskedTextResultHint.DigitExpected;
return false;
}
case EditType.LetterOptional:
case EditType.LetterRequired:
if (!char.IsLetter (c)) {
resultHint = MaskedTextResultHint.LetterExpected;
return false;
} else if (Parent.AsciiOnly && !IsAscii (c)) {
resultHint = MaskedTextResultHint.LetterExpected;
return false;
} else {
if (!only_test) {
Input = c;
}
resultHint = MaskedTextResultHint.Success;
return true;
}
default:
resultHint = MaskedTextResultHint.Unknown;
return false;
}
}
public bool FilledIn {
get {
return Input != char.MinValue;
}
}
public bool Required {
get {
switch (MaskCharacter) {
case '0':
case 'L':
case '&':
case 'A':
return true;
default:
return false;
}
}
}
public bool Editable {
get {
switch (MaskCharacter) {
case '0':
case '9':
case '#':
case 'L':
case '?':
case '&':
case 'C':
case 'A':
case 'a':
return true;
default:
return false;
}
}
}
public bool Visible {
get {
switch (MaskCharacter) {
case '|':
case '<':
case '>':
return false;
default:
return true;
}
}
}
public string Text {
get {
if (Type == EditType.Literal) {
return MaskCharacter.ToString ();
}
switch (MaskCharacter) {
case '.': return Parent.Culture.NumberFormat.NumberDecimalSeparator;
case ',': return Parent.Culture.NumberFormat.NumberGroupSeparator;
case ':': return Parent.Culture.DateTimeFormat.TimeSeparator;
case '/': return Parent.Culture.DateTimeFormat.DateSeparator;
case '$': return Parent.Culture.NumberFormat.CurrencySymbol;
default:
return FilledIn ? Input.ToString () : Parent.PromptChar.ToString ();
}
}
}
private EditPosition ()
{
}
public EditPosition (MaskedTextProvider Parent, EditType Type, EditState State, char MaskCharacter)
{
this.Type = Type;
this.Parent = Parent;
this.State = State;
this.MaskCharacter = MaskCharacter;
}
}
#endregion
#region Private methods & properties
private void SetMask (string mask)
{
if (mask == null || mask == string.Empty)
throw new ArgumentException ("The Mask value cannot be null or empty.\r\nParameter name: mask");
this.mask = mask;
System.Collections.Generic.List <EditPosition> list = new System.Collections.Generic.List<EditPosition> (mask.Length);
EditState State = EditState.None;
bool escaped = false;
for (int i = 0; i < mask.Length; i++) {
if (escaped) {
list.Add (new EditPosition (this, EditType.Literal, State, mask [i]));
escaped = false;
continue;
}
switch (mask [i]) {
case '\\':
escaped = true;
break;
case '0':
list.Add (new EditPosition (this, EditType.DigitRequired, State, mask [i]));
break;
case '9':
list.Add (new EditPosition (this, EditType.DigitOrSpaceOptional, State, mask [i]));
break;
case '#':
list.Add (new EditPosition (this, EditType.DigitOrSpaceOptional_Blank, State, mask [i]));
break;
case 'L':
list.Add (new EditPosition (this, EditType.LetterRequired, State, mask [i]));
break;
case '?':
list.Add (new EditPosition (this, EditType.LetterOptional, State, mask [i]));
break;
case '&':
list.Add (new EditPosition (this, EditType.CharacterRequired, State, mask [i]));
break;
case 'C':
list.Add (new EditPosition (this, EditType.CharacterOptional, State, mask [i]));
break;
case 'A':
list.Add (new EditPosition (this, EditType.AlphanumericRequired, State, mask [i]));
break;
case 'a':
list.Add (new EditPosition (this, EditType.AlphanumericOptional, State, mask [i]));
break;
case '.':
list.Add (new EditPosition (this, EditType.DecimalPlaceholder, State, mask [i]));
break;
case ',':
list.Add (new EditPosition (this, EditType.ThousandsPlaceholder, State, mask [i]));
break;
case ':':
list.Add (new EditPosition (this, EditType.TimeSeparator, State, mask [i]));
break;
case '/':
list.Add (new EditPosition (this, EditType.DateSeparator, State, mask [i]));
break;
case '$':
list.Add (new EditPosition (this, EditType.CurrencySymbol, State, mask [i]));
break;
case '<':
State = EditState.LowerCase;
break;
case '>':
State = EditState.UpperCase;
break;
case '|':
State = EditState.None;
break;
default:
list.Add (new EditPosition (this, EditType.Literal, State, mask [i]));
break;
}
}
edit_positions = list.ToArray ();
}
private EditPosition [] ClonePositions ()
{
EditPosition [] result = new EditPosition [edit_positions.Length];
for (int i = 0; i < result.Length; i++) {
result [i] = edit_positions [i].Clone ();
}
return result;
}
private bool AddInternal (string str_input, out int testPosition, out MaskedTextResultHint resultHint, bool only_test)
{
EditPosition [] edit_positions;
if (only_test) {
edit_positions = ClonePositions ();
} else {
edit_positions = this.edit_positions;
}
if (str_input == null)
throw new ArgumentNullException ("input");
if (str_input.Length == 0) {
resultHint = MaskedTextResultHint.NoEffect;
testPosition = LastAssignedPosition + 1;
return true;
}
resultHint = MaskedTextResultHint.Unknown;
testPosition = 0;
int next_position = LastAssignedPosition;
MaskedTextResultHint tmpResult = MaskedTextResultHint.Unknown;
if (next_position >= edit_positions.Length) {
testPosition = next_position;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
for (int i = 0; i < str_input.Length; i++) {
char input = str_input [i];
next_position++;
testPosition = next_position;
if (tmpResult > resultHint) {
resultHint = tmpResult;
}
if (VerifyEscapeChar (input, next_position)) {
tmpResult = MaskedTextResultHint.CharacterEscaped;
continue;
}
next_position = FindEditPositionFrom (next_position, true);
testPosition = next_position;
if (next_position == InvalidIndex) {
testPosition = edit_positions.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
if (!IsValidInputChar (input)) {
testPosition = next_position;
resultHint = MaskedTextResultHint.InvalidInput;
return false;
}
if (!edit_positions [next_position].Match (input, out tmpResult, false)) {
testPosition = next_position;
resultHint = tmpResult;
return false;
}
}
if (tmpResult > resultHint) {
resultHint = tmpResult;
}
return true;
}
private bool AddInternal (char input, out int testPosition, out MaskedTextResultHint resultHint, bool check_available_positions_first, bool check_escape_char_first)
{
/*
* check_available_positions_first: when adding a char, MS first seems to check if there are any available edit positions, then if there are any
* they will try to add the char (meaning that if you add a char matching a literal char in the mask with SkipLiterals and there are no
* more available edit positions, it will fail).
*
* check_escape_char_first: When adding a char, MS doesn't check for escape char, they directly search for the first edit position.
* When adding a string, they check first for escape char, then if not successful they find the first edit position.
*/
int new_position;
testPosition = 0;
new_position = LastAssignedPosition + 1;
if (check_available_positions_first) {
int tmp = new_position;
bool any_available = false;
while (tmp < edit_positions.Length) {
if (edit_positions [tmp].Editable) {
any_available = true;
break;
}
tmp++;
}
if (!any_available) {
testPosition = tmp;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return GetOperationResultFromHint (resultHint);
}
}
if (check_escape_char_first) {
if (VerifyEscapeChar (input, new_position)) {
testPosition = new_position;
resultHint = MaskedTextResultHint.CharacterEscaped;
return true;
}
}
new_position = FindEditPositionFrom (new_position, true);
if (new_position > edit_positions.Length - 1 ||new_position == InvalidIndex) {
testPosition = new_position;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return GetOperationResultFromHint (resultHint);
}
if (!IsValidInputChar (input)) {
testPosition = new_position;
resultHint = MaskedTextResultHint.InvalidInput;
return GetOperationResultFromHint (resultHint);
}
if (!edit_positions [new_position].Match (input, out resultHint, false)) {
testPosition = new_position;
return GetOperationResultFromHint (resultHint);
}
testPosition = new_position;
return GetOperationResultFromHint (resultHint);
}
private bool VerifyStringInternal (string input, out int testPosition, out MaskedTextResultHint resultHint, int startIndex, bool only_test)
{
int previous_position = startIndex;
int current_position;
resultHint = MaskedTextResultHint.Unknown;
// Replace existing characters
for (int i = 0; i < input.Length; i++) {
MaskedTextResultHint tmpResult;
current_position = FindEditPositionFrom (previous_position, true);
if (current_position == InvalidIndex) {
testPosition = edit_positions.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
if (!VerifyCharInternal (input [i], current_position, out tmpResult, only_test)) {
testPosition = current_position;
resultHint = tmpResult;
return false;
}
if (tmpResult > resultHint) {
resultHint = tmpResult;
}
previous_position = current_position + 1;
}
// Remove characters not in the input.
if (!only_test) {
previous_position = FindEditPositionFrom (previous_position, true);
while (previous_position != InvalidIndex) {
if (edit_positions [previous_position].FilledIn) {
edit_positions [previous_position].Reset ();
if (resultHint != MaskedTextResultHint.NoEffect) {
resultHint = MaskedTextResultHint.Success;
}
}
previous_position = FindEditPositionFrom (previous_position + 1, true);
}
}
if (input.Length > 0) {
testPosition = startIndex + input.Length - 1;
} else {
testPosition = startIndex;
if (resultHint < MaskedTextResultHint.NoEffect) {
resultHint = MaskedTextResultHint.NoEffect;
}
}
return true;
}
private bool VerifyCharInternal (char input, int position, out MaskedTextResultHint hint, bool only_test)
{
hint = MaskedTextResultHint.Unknown;
if (position < 0 || position >= edit_positions.Length) {
hint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (!IsValidInputChar (input)) {
hint = MaskedTextResultHint.InvalidInput;
return false;
}
if (input == ' ' && ResetOnSpace && edit_positions [position].Editable && edit_positions [position].FilledIn) {
if (!only_test) {
edit_positions [position].Reset ();
}
hint = MaskedTextResultHint.SideEffect;
return true;
}
if (edit_positions [position].Editable && edit_positions [position].FilledIn && edit_positions [position].input == input) {
hint = MaskedTextResultHint.NoEffect;
return true;
}
if (SkipLiterals && !edit_positions [position].Editable && edit_positions [position].Text == input.ToString ()) {
hint = MaskedTextResultHint.CharacterEscaped;
return true;
}
return edit_positions [position].Match (input, out hint, only_test);
}
// Test to see if the input string can be inserted at the specified position.
// Does not try to move characters.
private bool IsInsertableString (string str_input, int position, out int testPosition, out MaskedTextResultHint resultHint)
{
int current_position = position;
int test_position;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = InvalidIndex;
for (int i = 0; i < str_input.Length; i++) {
char ch = str_input [i];
test_position = FindEditPositionFrom (current_position, true);
if (test_position != InvalidIndex && VerifyEscapeChar (ch, test_position)) {
current_position = test_position + 1;
continue;
}
if (VerifyEscapeChar (ch, current_position)) {
current_position = current_position + 1;
continue;
}
if (test_position == InvalidIndex) {
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = edit_positions.Length;
return false;
}
testPosition = test_position;
if (!edit_positions [test_position].Match (ch, out resultHint, true)) {
return false;
}
current_position = test_position + 1;
}
resultHint = MaskedTextResultHint.Success;
return true;
}
private bool ShiftPositionsRight (EditPosition [] edit_positions, int start, out int testPosition, out MaskedTextResultHint resultHint)
{
int index = start;
int last_assigned_index = FindAssignedEditPositionFrom (edit_positions.Length, false);
int endindex = FindUnassignedEditPositionFrom (last_assigned_index, true); // Find the first non-assigned edit position
testPosition = start;
resultHint = MaskedTextResultHint.Unknown;
if (endindex == InvalidIndex) {
// No more free edit positions.
testPosition = edit_positions.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
while (endindex > index) {
char char_to_assign;
int index_to_move;
index_to_move = FindEditPositionFrom (endindex - 1, false);
char_to_assign = edit_positions [index_to_move].input;
if (char_to_assign == char.MinValue) {
edit_positions [endindex].input = char_to_assign;
} else {
if (!edit_positions [endindex].Match (char_to_assign, out resultHint, false)) {
testPosition = endindex;
return false;
}
}
endindex = index_to_move;
}
if (endindex != InvalidIndex) {
edit_positions [endindex].Reset ();
}
return true;
}
private bool ReplaceInternal (string input, int startPosition, int endPosition, out int testPosition, out MaskedTextResultHint resultHint, bool only_test, bool dont_remove_at_end)
{
EditPosition [] edit_positions;
resultHint = MaskedTextResultHint.Unknown;
if (only_test) {
edit_positions = ClonePositions ();
} else {
edit_positions = this.edit_positions;
}
if (input == null)
throw new ArgumentNullException ("input");
if (endPosition >= edit_positions.Length) {
testPosition = endPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition < 0) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition >= edit_positions.Length) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition > endPosition) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (input.Length == 0) {
return RemoveAtInternal (startPosition, endPosition, out testPosition, out resultHint, only_test);
}
int previous_position = startPosition;
int current_position = previous_position;
MaskedTextResultHint tmpResult = MaskedTextResultHint.Unknown;
testPosition = InvalidIndex;
for (int i = 0; i < input.Length; i++) {
char current_input = input [i];
current_position = previous_position;
if (VerifyEscapeChar (current_input, current_position)) {
if (edit_positions [current_position].FilledIn &&
edit_positions [current_position].Editable &&
(current_input == ' ' && ResetOnSpace) || (current_input == PromptChar && ResetOnPrompt)) {
edit_positions [current_position].Reset ();
tmpResult = MaskedTextResultHint.SideEffect;
} else {
tmpResult = MaskedTextResultHint.CharacterEscaped;
}
} else if (current_position < edit_positions.Length && !edit_positions [current_position].Editable && FindAssignedEditPositionInRange (current_position, endPosition, true) == InvalidIndex) {
// If replacing over a literal, the replacement character is INSERTED at the next
// available edit position. Weird, huh?
current_position = FindEditPositionFrom (current_position, true);
if (current_position == InvalidIndex) {
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = edit_positions.Length;
return false;
}
if (!InsertAtInternal (current_input.ToString (), current_position, out testPosition, out tmpResult, only_test)) {
resultHint = tmpResult;
return false;
}
} else {
current_position = FindEditPositionFrom (current_position, true);
if (current_position == InvalidIndex) {
testPosition = edit_positions.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
if (!IsValidInputChar (current_input)) {
testPosition = current_position;
resultHint = MaskedTextResultHint.InvalidInput;
return false;
}
if (!ReplaceInternal (edit_positions, current_input, current_position, out testPosition, out tmpResult, false)) {
resultHint = tmpResult;
return false;
}
}
if (tmpResult > resultHint) {
resultHint = tmpResult;
}
previous_position = current_position + 1;
}
testPosition = current_position;
int tmpPosition;
if (!dont_remove_at_end && previous_position <= endPosition) {
if (!RemoveAtInternal (previous_position, endPosition, out tmpPosition, out tmpResult, only_test)) {
testPosition = tmpPosition;
resultHint = tmpResult;
return false;
}
}
if (tmpResult == MaskedTextResultHint.Success && resultHint < MaskedTextResultHint.SideEffect) {
resultHint = MaskedTextResultHint.SideEffect;
}
return true;
}
private bool ReplaceInternal (EditPosition [] edit_positions, char input, int position, out int testPosition, out MaskedTextResultHint resultHint, bool only_test)
{
testPosition = position;
if (!IsValidInputChar (input)) {
resultHint = MaskedTextResultHint.InvalidInput;
return false;
}
if (VerifyEscapeChar (input, position)) {
if (edit_positions [position].FilledIn && edit_positions [position].Editable && (input == ' ' && ResetOnSpace) || (input == PromptChar && ResetOnPrompt)) {
edit_positions [position].Reset ();
resultHint = MaskedTextResultHint.SideEffect;
} else {
resultHint = MaskedTextResultHint.CharacterEscaped;
}
testPosition = position;
return true;
}
if (!edit_positions [position].Editable) {
resultHint = MaskedTextResultHint.NonEditPosition;
return false;
}
bool is_filled = edit_positions [position].FilledIn;
if (is_filled && edit_positions [position].input == input) {
if (VerifyEscapeChar (input, position)) {
resultHint = MaskedTextResultHint.CharacterEscaped;
} else {
resultHint = MaskedTextResultHint.NoEffect;
}
} else if (input == ' ' && this.ResetOnSpace) {
if (is_filled) {
resultHint = MaskedTextResultHint.SideEffect;
edit_positions [position].Reset ();
} else {
resultHint = MaskedTextResultHint.CharacterEscaped;
}
return true;
} else if (VerifyEscapeChar (input, position)) {
resultHint = MaskedTextResultHint.SideEffect;
} else {
resultHint = MaskedTextResultHint.Success;
}
MaskedTextResultHint tmpResult;
if (!edit_positions [position].Match (input, out tmpResult, false)) {
resultHint = tmpResult;
return false;
}
return true;
}
private bool RemoveAtInternal (int startPosition, int endPosition, out int testPosition, out MaskedTextResultHint resultHint, bool only_testing)
{
EditPosition [] edit_positions;
testPosition = -1;
resultHint = MaskedTextResultHint.Unknown;
if (only_testing) {
edit_positions = ClonePositions ();
} else {
edit_positions = this.edit_positions;
}
if (endPosition < 0 || endPosition >= edit_positions.Length) {
testPosition = endPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition < 0 || startPosition >= edit_positions.Length) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition > endPosition) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
int edit_positions_in_range = 0;
for (int i = startPosition; i <= endPosition; i++) {
if (edit_positions [i].Editable) {
edit_positions_in_range++;
}
}
if (edit_positions_in_range == 0) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.NoEffect;
return true;
}
int current_edit_position = FindEditPositionFrom (startPosition, true);
while (current_edit_position != InvalidIndex) {
// Find the edit position that will reach the current position.
int next_index = FindEditPositionFrom (current_edit_position + 1, true);
for (int j = 1; j < edit_positions_in_range && next_index != InvalidIndex; j++) {
next_index = FindEditPositionFrom (next_index + 1, true);
}
if (next_index == InvalidIndex) {
if (edit_positions [current_edit_position].FilledIn) {
edit_positions [current_edit_position].Reset ();
resultHint = MaskedTextResultHint.Success;
} else {
if (resultHint < MaskedTextResultHint.NoEffect) {
resultHint = MaskedTextResultHint.NoEffect;
}
}
} else {
if (!edit_positions [next_index].FilledIn) {
if (edit_positions [current_edit_position].FilledIn) {
edit_positions [current_edit_position].Reset ();
resultHint = MaskedTextResultHint.Success;
} else {
if (resultHint < MaskedTextResultHint.NoEffect) {
resultHint = MaskedTextResultHint.NoEffect;
}
}
} else {
MaskedTextResultHint tmpResult = MaskedTextResultHint.Unknown;
if (edit_positions [current_edit_position].FilledIn) {
resultHint = MaskedTextResultHint.Success;
} else if (resultHint < MaskedTextResultHint.SideEffect) {
resultHint = MaskedTextResultHint.SideEffect;
}
if (!edit_positions [current_edit_position].Match (edit_positions [next_index].input, out tmpResult, false)) {
resultHint = tmpResult;
testPosition = current_edit_position;
return false;
}
}
edit_positions [next_index].Reset ();
}
current_edit_position = FindEditPositionFrom (current_edit_position + 1, true);
}
if (resultHint == MaskedTextResultHint.Unknown) {
resultHint = MaskedTextResultHint.NoEffect;
}
testPosition = startPosition;
return true;
}
private bool InsertAtInternal (string str_input, int position, out int testPosition, out MaskedTextResultHint resultHint, bool only_testing)
{
EditPosition [] edit_positions;
testPosition = -1;
resultHint = MaskedTextResultHint.Unknown;
if (only_testing) {
edit_positions = ClonePositions ();
} else {
edit_positions = this.edit_positions;
}
if (position < 0 || position >= edit_positions.Length) {
testPosition = 0;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (!IsInsertableString (str_input, position, out testPosition, out resultHint)) {
return false;
}
resultHint = MaskedTextResultHint.Unknown;
int next_position = position;
for (int i = 0; i < str_input.Length; i++) {
char input = str_input [i];
int index = FindEditPositionFrom (next_position, true); // Find the first edit position (here the input will go)
int endindex = FindUnassignedEditPositionFrom (next_position, true); // Find the first non-assigned edit position
bool escaped = false;
if (VerifyEscapeChar (input, next_position)) {
escaped = true;
if (input.ToString () == edit_positions [next_position].Text) {
if (FindAssignedEditPositionInRange (0, next_position - 1, true) != InvalidIndex && endindex == InvalidIndex) {
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = edit_positions.Length;
return false;
}
resultHint = MaskedTextResultHint.CharacterEscaped;
testPosition = next_position;
next_position++;
continue;
}
}
if (!escaped && index == InvalidIndex) {
// No edit positions left at all in the string
testPosition = edit_positions.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
if (index == InvalidIndex) {
index = next_position;
}
bool was_filled = edit_positions [index].FilledIn;
bool shift = was_filled;
if (shift) {
if (!ShiftPositionsRight (edit_positions, index, out testPosition, out resultHint)) {
return false;
}
}
testPosition = index;
if (escaped) {
if (was_filled) {
resultHint = MaskedTextResultHint.Success;
} else if (!edit_positions [index].Editable && input.ToString () == edit_positions [index].Text) {
resultHint = MaskedTextResultHint.CharacterEscaped;
testPosition = next_position;
} else {
int first_edit_position = FindEditPositionFrom (index, true);
if (first_edit_position == InvalidIndex) {
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = edit_positions.Length;
return false;
}
resultHint = MaskedTextResultHint.CharacterEscaped;
if (input.ToString () == edit_positions [next_position].Text) {
testPosition = next_position;
}
}
} else {
MaskedTextResultHint tmpResult;
if (!edit_positions [index].Match (input, out tmpResult, false)) {
resultHint = tmpResult;
return false;
}
if (resultHint < tmpResult) {
resultHint = tmpResult;
}
}
next_position = index + 1;
}
return true;
}
#endregion
#region Public constructors
static MaskedTextProvider()
{
}
public MaskedTextProvider(string mask)
: this (mask, null, true, default_prompt_char, default_password_char, false)
{
}
public MaskedTextProvider (string mask, bool restrictToAscii)
: this (mask, null, true, default_prompt_char, default_password_char, restrictToAscii)
{
}
public MaskedTextProvider (string mask, CultureInfo culture)
: this (mask, culture, true, default_prompt_char, default_password_char, false)
{
}
public MaskedTextProvider (string mask, char passwordChar, bool allowPromptAsInput)
: this (mask, null, allowPromptAsInput, default_prompt_char, passwordChar, false)
{
}
public MaskedTextProvider (string mask, CultureInfo culture, bool restrictToAscii)
: this (mask, culture, true, default_prompt_char, default_password_char, restrictToAscii)
{
}
public MaskedTextProvider(string mask, CultureInfo culture, char passwordChar, bool allowPromptAsInput)
: this (mask, culture, allowPromptAsInput, default_prompt_char, passwordChar, false)
{
}
public MaskedTextProvider(string mask, CultureInfo culture, bool allowPromptAsInput, char promptChar, char passwordChar, bool restrictToAscii)
{
SetMask (mask);
if (culture == null)
this.culture = Threading.Thread.CurrentThread.CurrentCulture;
else
this.culture = culture;
this.allow_prompt_as_input = allowPromptAsInput;
this.PromptChar = promptChar;
this.PasswordChar = passwordChar;
this.ascii_only = restrictToAscii;
include_literals = true;
reset_on_prompt = true;
reset_on_space = true;
skip_literals = true;
}
#endregion
#region Public methods
public bool Add(char input)
{
int testPosition;
MaskedTextResultHint resultHint;
return Add (input, out testPosition, out resultHint);
}
public bool Add (string input)
{
int testPosition;
MaskedTextResultHint resultHint;
return Add (input, out testPosition, out resultHint);
}
public bool Add (char input, out int testPosition, out MaskedTextResultHint resultHint)
{
return AddInternal (input, out testPosition, out resultHint, true, false);
}
public bool Add (string input, out int testPosition, out MaskedTextResultHint resultHint)
{
bool result;
result = AddInternal (input, out testPosition, out resultHint, true);
if (result) {
result = AddInternal (input, out testPosition, out resultHint, false);
}
return result;
}
public void Clear ()
{
MaskedTextResultHint resultHint;
Clear (out resultHint);
}
public void Clear (out MaskedTextResultHint resultHint)
{
resultHint = MaskedTextResultHint.NoEffect;
for (int i = 0; i < edit_positions.Length; i++) {
if (edit_positions [i].Editable && edit_positions [i].FilledIn) {
edit_positions [i].Reset ();
resultHint = MaskedTextResultHint.Success;
}
}
}
public object Clone ()
{
MaskedTextProvider result = new MaskedTextProvider (mask);
result.allow_prompt_as_input = allow_prompt_as_input;
result.ascii_only = ascii_only;
result.culture = culture;
result.edit_positions = ClonePositions ();
result.include_literals = include_literals;
result.include_prompt = include_prompt;
result.is_password = is_password;
result.mask = mask;
result.password_char = password_char;
result.prompt_char = prompt_char;
result.reset_on_prompt = reset_on_prompt;
result.reset_on_space = reset_on_space;
result.skip_literals = skip_literals;
return result;
}
public int FindAssignedEditPositionFrom (int position, bool direction)
{
if (direction) {
return FindAssignedEditPositionInRange (position, edit_positions.Length - 1, direction);
} else {
return FindAssignedEditPositionInRange (0, position, direction);
}
}
public int FindAssignedEditPositionInRange (int startPosition, int endPosition, bool direction)
{
int step;
int start, end;
if (startPosition < 0)
startPosition = 0;
if (endPosition >= edit_positions.Length)
endPosition = edit_positions.Length - 1;
if (startPosition > endPosition)
return InvalidIndex;
step = direction ? 1 : -1;
start = direction ? startPosition : endPosition;
end = (direction ? endPosition: startPosition) + step;
for (int i = start; i != end; i+=step) {
if (edit_positions [i].Editable && edit_positions [i].FilledIn)
return i;
}
return InvalidIndex;
}
public int FindEditPositionFrom (int position, bool direction)
{
if (direction) {
return FindEditPositionInRange (position, edit_positions.Length - 1, direction);
} else {
return FindEditPositionInRange (0, position, direction);
}
}
public int FindEditPositionInRange (int startPosition, int endPosition, bool direction)
{
int step;
int start, end;
if (startPosition < 0)
startPosition = 0;
if (endPosition >= edit_positions.Length)
endPosition = edit_positions.Length - 1;
if (startPosition > endPosition)
return InvalidIndex;
step = direction ? 1 : -1;
start = direction ? startPosition : endPosition;
end = (direction ? endPosition : startPosition) + step;
for (int i = start; i != end; i += step) {
if (edit_positions [i].Editable)
return i;
}
return InvalidIndex;
}
public int FindNonEditPositionFrom (int position, bool direction)
{
if (direction) {
return FindNonEditPositionInRange (position, edit_positions.Length - 1, direction);
} else {
return FindNonEditPositionInRange (0, position, direction);
}
}
public int FindNonEditPositionInRange (int startPosition, int endPosition, bool direction)
{
int step;
int start, end;
if (startPosition < 0)
startPosition = 0;
if (endPosition >= edit_positions.Length)
endPosition = edit_positions.Length - 1;
if (startPosition > endPosition)
return InvalidIndex;
step = direction ? 1 : -1;
start = direction ? startPosition : endPosition;
end = (direction ? endPosition : startPosition) + step;
for (int i = start; i != end; i += step) {
if (!edit_positions [i].Editable)
return i;
}
return InvalidIndex;
}
public int FindUnassignedEditPositionFrom (int position, bool direction)
{
if (direction) {
return FindUnassignedEditPositionInRange (position, edit_positions.Length - 1, direction);
} else {
return FindUnassignedEditPositionInRange (0, position, direction);
}
}
public int FindUnassignedEditPositionInRange (int startPosition, int endPosition, bool direction)
{
int step;
int start, end;
if (startPosition < 0)
startPosition = 0;
if (endPosition >= edit_positions.Length)
endPosition = edit_positions.Length - 1;
if (startPosition > endPosition)
return InvalidIndex;
step = direction ? 1 : -1;
start = direction ? startPosition : endPosition;
end = (direction ? endPosition : startPosition) + step;
for (int i = start; i != end; i += step) {
if (edit_positions [i].Editable && !edit_positions [i].FilledIn)
return i;
}
return InvalidIndex;
}
public static bool GetOperationResultFromHint (MaskedTextResultHint hint)
{
return (hint == MaskedTextResultHint.CharacterEscaped ||
hint == MaskedTextResultHint.NoEffect ||
hint == MaskedTextResultHint.SideEffect ||
hint == MaskedTextResultHint.Success);
}
public bool InsertAt (char input, int position)
{
int testPosition;
MaskedTextResultHint resultHint;
return InsertAt (input, position, out testPosition, out resultHint);
}
public bool InsertAt (string input, int position)
{
int testPosition;
MaskedTextResultHint resultHint;
return InsertAt (input, position, out testPosition, out resultHint);
}
public bool InsertAt (char input, int position, out int testPosition, out MaskedTextResultHint resultHint)
{
return InsertAt (input.ToString (), position, out testPosition, out resultHint);
}
public bool InsertAt (string input, int position, out int testPosition, out MaskedTextResultHint resultHint)
{
if (input == null)
throw new ArgumentNullException ("input");
if (position >= edit_positions.Length) {
testPosition = position;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (input == string.Empty) {
testPosition = position;
resultHint = MaskedTextResultHint.NoEffect;
return true;
}
bool result;
result = InsertAtInternal (input, position, out testPosition, out resultHint, true);
if (result) {
result = InsertAtInternal (input, position, out testPosition, out resultHint, false);
}
return result;
}
public bool IsAvailablePosition (int position)
{
if (position < 0 || position >= edit_positions.Length)
return false;
return edit_positions [position].Editable && !edit_positions [position].FilledIn;
}
public bool IsEditPosition (int position)
{
if (position < 0 || position >= edit_positions.Length)
return false;
return edit_positions [position].Editable;
}
public static bool IsValidInputChar (char c)
{
return char.IsLetterOrDigit (c) || char.IsPunctuation (c) || char.IsSymbol (c) || c == ' ';
}
public static bool IsValidMaskChar (char c)
{
return char.IsLetterOrDigit (c) || char.IsPunctuation (c) || char.IsSymbol (c) || c == ' ';
}
public static bool IsValidPasswordChar (char c)
{
return char.IsLetterOrDigit (c) || char.IsPunctuation (c) || char.IsSymbol (c) || c == ' ' || c == char.MinValue;
}
public bool Remove ()
{
int testPosition;
MaskedTextResultHint resultHint;
return Remove (out testPosition, out resultHint);
}
public bool Remove (out int testPosition, out MaskedTextResultHint resultHint)
{
if (LastAssignedPosition == InvalidIndex) {
resultHint = MaskedTextResultHint.NoEffect;
testPosition = 0;
return true;
}
testPosition = LastAssignedPosition;
resultHint = MaskedTextResultHint.Success;
edit_positions [LastAssignedPosition].input = char.MinValue;
return true;
}
public bool RemoveAt (int position)
{
return RemoveAt (position, position);
}
public bool RemoveAt (int startPosition, int endPosition)
{
int testPosition;
MaskedTextResultHint resultHint;
return RemoveAt (startPosition, endPosition, out testPosition, out resultHint);
}
public bool RemoveAt (int startPosition, int endPosition, out int testPosition, out MaskedTextResultHint resultHint)
{
bool result;
result = RemoveAtInternal (startPosition, endPosition, out testPosition, out resultHint, true);
if (result) {
result = RemoveAtInternal (startPosition, endPosition, out testPosition, out resultHint, false);
}
return result;
}
public bool Replace (char input, int position)
{
int testPosition;
MaskedTextResultHint resultHint;
return Replace (input, position, out testPosition, out resultHint);
}
public bool Replace (string input, int position)
{
int testPosition;
MaskedTextResultHint resultHint;
return Replace (input, position, out testPosition, out resultHint);
}
public bool Replace (char input, int position, out int testPosition, out MaskedTextResultHint resultHint)
{
if (position < 0 || position >= edit_positions.Length) {
testPosition = position;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (VerifyEscapeChar (input, position)) {
if (edit_positions [position].FilledIn && edit_positions [position].Editable && (input == ' ' && ResetOnSpace) || (input == PromptChar && ResetOnPrompt)) {
edit_positions [position].Reset ();
resultHint = MaskedTextResultHint.SideEffect;
} else {
resultHint = MaskedTextResultHint.CharacterEscaped;
}
testPosition = position;
return true;
}
int current_edit_position;
current_edit_position = FindEditPositionFrom (position, true);
if (current_edit_position == InvalidIndex) {
testPosition = position;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
return false;
}
if (!IsValidInputChar (input)) {
testPosition = current_edit_position;
resultHint = MaskedTextResultHint.InvalidInput;
return false;
}
return ReplaceInternal (edit_positions, input, current_edit_position, out testPosition, out resultHint, false);
}
public bool Replace (string input, int position, out int testPosition, out MaskedTextResultHint resultHint)
{
if (input == null)
throw new ArgumentNullException ("input");
if (position < 0 || position >= edit_positions.Length) {
testPosition = position;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (input.Length == 0) {
return RemoveAt (position, position, out testPosition, out resultHint);
}
bool result;
result = ReplaceInternal (input, position, edit_positions.Length - 1, out testPosition, out resultHint, true, true);
if (result) {
result = ReplaceInternal (input, position, edit_positions.Length - 1, out testPosition, out resultHint, false, true);
}
return result;
}
public bool Replace (char input, int startPosition, int endPosition, out int testPosition, out MaskedTextResultHint resultHint)
{
if (endPosition >= edit_positions.Length) {
testPosition = endPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition < 0) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition > endPosition) {
testPosition = startPosition;
resultHint = MaskedTextResultHint.PositionOutOfRange;
return false;
}
if (startPosition == endPosition) {
return ReplaceInternal (edit_positions, input, startPosition, out testPosition, out resultHint, false);
}
return Replace (input.ToString (), startPosition, endPosition, out testPosition, out resultHint);
}
public bool Replace (string input, int startPosition, int endPosition, out int testPosition, out MaskedTextResultHint resultHint)
{
bool result;
result = ReplaceInternal (input, startPosition, endPosition, out testPosition, out resultHint, true, false);
if (result) {
result = ReplaceInternal (input, startPosition, endPosition, out testPosition, out resultHint, false, false);
}
return result;
}
public bool Set (string input)
{
int testPosition;
MaskedTextResultHint resultHint;
return Set (input, out testPosition, out resultHint);
}
public bool Set (string input, out int testPosition, out MaskedTextResultHint resultHint)
{
bool result;
if (input == null) {
throw new ArgumentNullException ("input");
}
result = VerifyStringInternal (input, out testPosition, out resultHint, 0, true);
if (result) {
result = VerifyStringInternal (input, out testPosition, out resultHint, 0, false);
}
return result;
}
public string ToDisplayString ()
{
return ToString (false, true, true, 0, Length);
}
public override string ToString ()
{
return ToString (true, IncludePrompt, IncludeLiterals, 0, Length);
}
public string ToString (bool ignorePasswordChar)
{
return ToString (ignorePasswordChar, IncludePrompt, IncludeLiterals, 0, Length);
}
public string ToString (bool includePrompt, bool includeLiterals)
{
return ToString (true, includePrompt, includeLiterals, 0, Length);
}
public string ToString (int startPosition, int length)
{
return ToString (true, IncludePrompt, IncludeLiterals, startPosition, length);
}
public string ToString (bool ignorePasswordChar, int startPosition, int length)
{
return ToString (ignorePasswordChar, IncludePrompt, IncludeLiterals, startPosition, length);
}
public string ToString (bool includePrompt, bool includeLiterals, int startPosition, int length)
{
return ToString (true, includePrompt, includeLiterals, startPosition, length);
}
public string ToString (bool ignorePasswordChar, bool includePrompt, bool includeLiterals, int startPosition, int length)
{
if (startPosition < 0)
startPosition = 0;
if (length <= 0)
return string.Empty;
StringBuilder result = new StringBuilder ();
int start = startPosition;
int end = startPosition + length - 1;
if (end >= edit_positions.Length) {
end = edit_positions.Length - 1;
}
int last_assigned_position = FindAssignedEditPositionInRange (start, end, false);
// Find the last position in the mask to check for
if (!includePrompt) {
int last_non_edit_position;
last_non_edit_position = FindNonEditPositionInRange (start, end, false);
if (includeLiterals) {
end = last_assigned_position > last_non_edit_position ? last_assigned_position : last_non_edit_position;
} else {
end = last_assigned_position;
}
}
for (int i = start; i <= end; i++) {
EditPosition ed = edit_positions [i];
if (ed.Type == EditType.Literal) {
if (includeLiterals) {
result.Append (ed.Text);
}
} else if (ed.Editable) {
if (IsPassword) {
if (!ed.FilledIn) { // Nothing to hide or show.
if (includePrompt)
result.Append (PromptChar);
else
result.Append (" ");
} else if (ignorePasswordChar)
result.Append (ed.Input);
else
result.Append (PasswordChar);
} else if (!ed.FilledIn) {
if (includePrompt) {
result.Append (PromptChar);
} else if (includeLiterals) {
result.Append (" ");
} else if (last_assigned_position != InvalidIndex && last_assigned_position > i) {
result.Append (" ");
}
} else {
result.Append (ed.Text);
}
} else {
if (includeLiterals)
result.Append (ed.Text);
}
}
return result.ToString ();
}
public bool VerifyChar (char input, int position, out MaskedTextResultHint hint)
{
return VerifyCharInternal (input, position, out hint, true);
}
public bool VerifyEscapeChar (char input, int position)
{
if (position >= edit_positions.Length || position < 0) {
return false;
}
if (!edit_positions [position].Editable) {
if (SkipLiterals) {
return input.ToString () == edit_positions [position].Text;
} else {
return false;
}
}
if (ResetOnSpace && input == ' ') {
return true;
} else if (ResetOnPrompt && input == PromptChar) {
return true;
} else {
return false;
}
}
public bool VerifyString (string input)
{
int testPosition;
MaskedTextResultHint resultHint;
return VerifyString (input, out testPosition, out resultHint);
}
public bool VerifyString (string input, out int testPosition, out MaskedTextResultHint resultHint)
{
if (input == null || input.Length == 0) {
testPosition = 0;
resultHint = MaskedTextResultHint.NoEffect;
return true;
}
return VerifyStringInternal (input, out testPosition, out resultHint, 0, true);
}
#endregion
#region Public properties
public bool AllowPromptAsInput {
get {
return allow_prompt_as_input;
}
}
public bool AsciiOnly {
get {
return ascii_only;
}
}
public int AssignedEditPositionCount {
get {
int result = 0;
for (int i = 0; i < edit_positions.Length; i++) {
if (edit_positions [i].FilledIn) {
result++;
}
}
return result;
}
}
public int AvailableEditPositionCount {
get {
int result = 0;
foreach (EditPosition edit in edit_positions) {
if (!edit.FilledIn && edit.Editable) {
result++;
}
}
return result;
}
}
public CultureInfo Culture {
get {
return culture;
}
}
public static char DefaultPasswordChar {
get {
return '*';
}
}
public int EditPositionCount {
get {
int result = 0;
foreach (EditPosition edit in edit_positions) {
if (edit.Editable) {
result++;
}
}
return result;
}
}
public IEnumerator EditPositions {
get {
System.Collections.Generic.List <int> result = new System.Collections.Generic.List<int> ();
for (int i = 0; i < edit_positions.Length; i++) {
if (edit_positions [i].Editable) {
result.Add (i);
}
}
return result.GetEnumerator ();
}
}
public bool IncludeLiterals {
get {
return include_literals;
}
set {
include_literals = value;
}
}
public bool IncludePrompt {
get {
return include_prompt;
}
set {
include_prompt = value;
}
}
public static int InvalidIndex {
get {
return -1;
}
}
public bool IsPassword {
get {
return password_char != char.MinValue;
}
set {
password_char = value ? DefaultPasswordChar : char.MinValue;
}
}
public char this [int index] {
get {
if (index < 0 || index >= Length) {
throw new IndexOutOfRangeException (index.ToString ());
}
return ToString (true, true, true, 0, edit_positions.Length) [index];
}
}
public int LastAssignedPosition {
get {
return FindAssignedEditPositionFrom (edit_positions.Length - 1, false);
}
}
public int Length {
get {
int result = 0;
for (int i = 0; i < edit_positions.Length; i++) {
if (edit_positions [i].Visible)
result++;
}
return result;
}
}
public string Mask {
get {
return mask;
}
}
public bool MaskCompleted {
get {
for (int i = 0; i < edit_positions.Length; i++)
if (edit_positions [i].Required && !edit_positions [i].FilledIn)
return false;
return true;
}
}
public bool MaskFull {
get {
for (int i = 0; i < edit_positions.Length; i++)
if (edit_positions [i].Editable && !edit_positions [i].FilledIn)
return false;
return true;
}
}
public char PasswordChar {
get {
return password_char;
}
set {
password_char = value;
}
}
public char PromptChar {
get {
return prompt_char;
}
set {
prompt_char = value;
}
}
public bool ResetOnPrompt {
get {
return reset_on_prompt;
}
set {
reset_on_prompt = value;
}
}
public bool ResetOnSpace {
get {
return reset_on_space;
}
set {
reset_on_space = value;
}
}
public bool SkipLiterals {
get {
return skip_literals;
}
set {
skip_literals = value;
}
}
#endregion
}
}
#endif
|