const string DIGITS = "0123456789";
#define IS_DIGIT(d) (strstrofs(DIGITS, (d), 0) >= 0)
+
+// returns true if the caret at position pos is escaped
+ERASEABLE
+bool isCaretEscaped(string theText, float pos)
+{
+ // count all the previous carets
+ int carets = 0;
+ while(pos - carets >= 1 && substring(theText, pos - carets - 1, 1) == "^")
+ ++carets;
+ // if number of previous carets is odd then this carets is escaped
+ return (carets & 1);
+}
+
+ERASEABLE
+bool isValidColorCodeValue(string theText, int cc_len, int tag_start)
+{
+ if (cc_len == 2)
+ return IS_DIGIT(substring(theText, tag_start + 1, 1));
+ if (cc_len == 5)
+ return (IS_HEXDIGIT(substring(theText, tag_start + 2, 1))
+ && IS_HEXDIGIT(substring(theText, tag_start + 3, 1))
+ && IS_HEXDIGIT(substring(theText, tag_start + 4, 1)));
+ return false;
+}
+
+// it returns 0 if pos is NOT in the middle or at the end of a color code
+// otherwise it returns a 2-digit number with cc_len as the first digit
+// and the offset from '^' position to pos as the second digit
+// e.g.:
+// "a^2xy" | returns 0 if pos == 0 or 1 or 4
+// ^^ | returns 21 or 22 if pos == 2 or 3
+ERASEABLE
+int checkColorCode(string theText, int pos)
+{
+ int text_len = strlen(theText);
+ string tag_type = "^";
+ int cc_len = 2;
+ int tag_len = 1;
+
+ LABEL(check_color_tag)
+
+ for (int ofs = cc_len; ofs >= 1; ofs--)
+ {
+ if (!(pos >= ofs && text_len >= pos + (cc_len - ofs)))
+ continue;
+ if(substring(theText, pos - ofs, tag_len) == tag_type)
+ {
+ if (!isCaretEscaped(theText, pos - ofs) && isValidColorCodeValue(theText, cc_len, pos - ofs))
+ return cc_len * 10 + ofs;
+ }
+ }
+ if (cc_len == 2)
+ {
+ tag_type = "^x";
+ cc_len = 5;
+ tag_len = 2;
+ goto check_color_tag;
+ }
+ return 0;
+}
float XonoticColorpicker_mouseDrag(entity me, vector coords)
{
- float i, carets;
+ int i;
for (;;)
{
i = me.controlledTextbox.cursorPos;
- if(i >= 2)
- {
- if(substring(me.controlledTextbox.text, i-2, 1) == "^")
- {
- carets = 1;
- while (i - 2 - carets >= 0 && substring(me.controlledTextbox.text, i - 2 - carets, 1) == "^")
- ++carets;
- if (carets & 1)
- if(IS_DIGIT(substring(me.controlledTextbox.text, i-1, 1)))
- {
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- continue;
- }
- }
- }
- if(i >= 5)
+ int res = checkColorCode(me.controlledTextbox.text, i);
+ if (res)
{
- if(substring(me.controlledTextbox.text, i-5, 2) == "^x")
- {
- carets = 1;
- while (i - 5 - carets >= 0 && substring(me.controlledTextbox.text, i - 5 - carets, 1) == "^")
- ++carets;
- if (carets & 1)
- if(IS_HEXDIGIT(substring(me.controlledTextbox.text, i - 3, 1)))
- if(IS_HEXDIGIT(substring(me.controlledTextbox.text, i - 2, 1)))
- if(IS_HEXDIGIT(substring(me.controlledTextbox.text, i - 1, 1)))
- {
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
- continue;
- }
- }
+ int tag_length = floor(res / 10);
+ int ofs = res % 10;
+ for (int j = tag_length - ofs; j > 0; j--)
+ me.controlledTextbox.keyDown(me.controlledTextbox, K_RIGHTARROW, 8, 0);
+ for (int j = tag_length; j > 0; j--)
+ me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+ continue;
}
+
break;
}
if(substring(me.controlledTextbox.text, i-1, 1) == "^")
{
- carets = 1;
- while (i - 1 - carets >= 0 && substring(me.controlledTextbox.text, i - 1 - carets, 1) == "^")
- ++carets;
- if (carets & 1)
+ if(!isCaretEscaped(me.controlledTextbox.text, i-1))
me.controlledTextbox.enterText(me.controlledTextbox, "^"); // escape previous caret
}