/cwxeditor_src/cwx/msgutils.d
D | 350 lines | 321 code | 6 blank | 23 comment | 78 complexity | 2eefa1e0bda0dbdd5fd909e55e0dab1e MD5 | raw file
Possible License(s): LGPL-2.1
- module cwx.msgutils;
- import cwx.utils;
- import std.conv;
- import std.exception;
- import std.path;
- import std.uni;
- import std.utf;
- import std.algorithm;
- import std.string;
- /// "font_X.bmp"??"X"?????????
- dchar decodeFontPath(string path) { mixin(S_TRACE);
- enforce(istartsWith(path, "font_"));
- auto dpath = to!dstring(path["font_".length .. $].stripExtension());
- enforce(1 == dpath.length);
- return std.uni.toUpper(dpath[0]);
- }
- /// c?"font_X.bmp"???????
- string encodeFontPath(dchar c, string ext) { mixin(S_TRACE);
- return ("font_" ~ to!string(c)).setExtension(ext);
- }
- /// ???????????????????????????????????
- /// ??????????????????????????????
- string formatMsg(in string text,
- string delegate(string) getFlag,
- string delegate(string) getStep,
- string delegate(char) getName,
- bool delegate(string) hasMaterial,
- out string[size_t] fonts,
- out char[size_t] colors) { mixin(S_TRACE);
- return formatMsgImpl(text, getFlag, getStep, getName, hasMaterial, fonts, colors, true);
- }
- /// ditto
- string simpleFormatMsg(in string text, string[string] flags, string[string] steps, string[char] names) { mixin(S_TRACE);
- string[size_t] fonts;
- char[size_t] colors;
- return formatMsgImpl(text, (string path) { mixin(S_TRACE);
- foreach (f, v; flags) { mixin(S_TRACE);
- if (0 == icmp(f, path)) { mixin(S_TRACE);
- return v;
- }
- }
- return "%" ~ path ~ "%";
- }, (string path) { mixin(S_TRACE);
- foreach (f, v; steps) { mixin(S_TRACE);
- if (0 == icmp(f, path)) { mixin(S_TRACE);
- return v;
- }
- }
- return "$" ~ path ~ "$";
- }, delegate string (char name) { mixin(S_TRACE);
- auto dc = std.ascii.toUpper(name);
- foreach (c, v; names) { mixin(S_TRACE);
- if (std.ascii.toUpper(c) == dc) { mixin(S_TRACE);
- return v;
- }
- }
- return "#" ~ name;
- }, (c) => false, fonts, colors, false);
- }
- private string formatMsgImpl(in string text,
- string delegate(string) getFlag,
- string delegate(string) getStep,
- string delegate(char) getName,
- bool delegate(string) hasMaterial,
- out string[size_t] fonts,
- out char[size_t] colors,
- bool full) { mixin(S_TRACE);
- dchar[] result;
- dstring dtext = to!dstring(text);
- for (size_t i = 0; i < dtext.length; i++) { mixin(S_TRACE);
- dchar c = dtext[i];
- bool flag_step(string delegate(string) get, dchar c) { mixin(S_TRACE);
- int next = .countUntil(dtext[i + 1 .. $], c);
- if (next < 0) return false;
- dstring fl = dtext[i + 1 .. i + 1 + next];
- i = i + 1 + next;
- result ~= to!dstring(get(to!string(fl)));
- return true;
- }
- switch (c) {
- case '#':
- if (i + 1 == dtext.length) goto default;
- if ('\n' == dtext[i + 1]) goto default;
- auto nc = std.ascii.toUpper(dtext[i + 1]);
- if (full) { mixin(S_TRACE);
- switch (nc) {
- case 'M', 'R', 'U', 'C', 'I', 'T', 'Y':
- result ~= to!dstring(getName(cast(char) nc));
- i++;
- continue;
- default:
- string path = encodeFontPath(dtext[i + 1], ".bmp");
- if (!hasMaterial || hasMaterial(path)) { mixin(S_TRACE);
- fonts[result.length] = path;
- }
- break;
- }
- } else { mixin(S_TRACE);
- switch (nc) {
- case 'M', 'R', 'U', 'T', 'Y':
- result ~= to!dstring(getName(cast(char) nc));
- i++;
- continue;
- default:
- break;
- }
- }
- goto default;
- case '%':
- if (!flag_step(getFlag, '%')) goto default;
- break;
- case '$':
- if (!flag_step(getStep, '$')) goto default;
- break;
- case '&':
- if (!full) goto default;
- if (i + 1 == dtext.length) goto default;
- if ('\n' == dtext[i + 1]) goto default;
- auto nc = std.ascii.toUpper(dtext[i + 1]);
- switch (nc) {
- case 'W', 'R', 'B', 'G', 'Y':
- case 'O', 'P', 'L', 'D': // CardWirth 1.50
- colors[result.length] = cast(char) nc;
- break;
- default:
- break;
- }
- goto default;
- default:
- result ~= c;
- break;
- }
- }
- return to!string(assumeUnique(result));
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- string[size_t] rFonts;
- char[size_t] rColors;
- string result = formatMsg("%flag1%, %flag2%, $step1$, $step2$, &R, &W, #m, #r, #v, #+", (string flag) { mixin(S_TRACE);
- if ("flag1" == flag) return "f1test";
- return "f2";
- }, (string step) { mixin(S_TRACE);
- if ("step1" == step) return "s1test";
- return " ";
- }, (char name) { mixin(S_TRACE);
- if (name == 'R') return "R_test";
- return "";
- }, null, rFonts, rColors);
- assert (result == "f1test, f2, s1test, , &R, &W, , R_test, #v, #+", result);
- assert (rFonts == [cast(size_t) 41:"font_v.bmp", cast(size_t) 45:"font_+.bmp"]);
- assert (rColors == [cast(size_t) 23:'R', cast(size_t) 27:'W'], .text(rColors));
- }
- /// ?????????????????????????????????
- void textUseItems(in string text,
- out string[] flags, out string[] steps, out string[] fonts) { mixin(S_TRACE);
- string[size_t] rFonts;
- char[size_t] rColors;
- formatMsg(text, (string flag) { mixin(S_TRACE);
- flags ~= flag;
- return "";
- }, (string step) { mixin(S_TRACE);
- steps ~= step;
- return "";
- }, (char name) { mixin(S_TRACE);
- return "";
- }, null, rFonts, rColors);
- fonts = rFonts.values;
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- string[] flags, steps, fonts;
- textUseItems("#M#R#U#C#I#T#Yaaa$test$$???\t2$$#tes%t3$%tes#t%#a#Z#1#2#33d$dd%aaa%%#%#;%vv%#?%#", flags, steps, fonts);
- assert(flags.sort == ["tes#t", "aaa", "#", "vv"].sort, .text(flags));
- assert(steps.sort == ["test", "???\t2", "#tes%t3"].sort, .text(steps));
- assert(fonts.sort == ["font_a.bmp", "font_Z.bmp", "font_1.bmp", "font_2.bmp", "font_3.bmp", "font_;.bmp", "font_?.bmp"].sort, .text(fonts));
- }
- private void __replOn(ref dstring dtext, ref dstring buf, ref size_t i, dstring dold, dstring dnew, dchar targC) { mixin(S_TRACE);
- int next = .countUntil(dtext[i + 1 .. $], targC);
- if (next >= 0) { mixin(S_TRACE);
- next = i + 1 + next;
- if (dtext[i + 1 .. next] == dold) { mixin(S_TRACE);
- buf ~= [targC] ~ dnew ~ [targC];
- } else { mixin(S_TRACE);
- buf ~= dtext[i .. next + 1];
- }
- if (next < dtext.length) { mixin(S_TRACE);
- dtext = dtext[next .. $];
- i = 0;
- }
- } else { mixin(S_TRACE);
- buf ~= dtext[i];
- }
- }
- private void __replOff(ref dstring dtext, ref dstring buf, ref size_t i, dchar targC) { mixin(S_TRACE);
- int next = .countUntil(dtext[i + 1 .. $], targC);
- if (next >= 0) { mixin(S_TRACE);
- next = i + 1 + next;
- buf ~= [targC] ~ dtext[i + 1 .. next] ~ [targC];
- if (next < dtext.length) { mixin(S_TRACE);
- dtext = dtext[next .. $];
- i = 0;
- }
- } else { mixin(S_TRACE);
- buf ~= dtext[i];
- }
- }
- private string __replTextFlagStep(char Ch1, char Ch2)
- (string text, string oldFlag, string newFlag) { mixin(S_TRACE);
- dstring dtext = toUTF32(text);
- dstring dold = toUTF32(oldFlag);
- dstring dnew = toUTF32(newFlag);
- dstring buf;
- for (size_t i; i < dtext.length; i++) { mixin(S_TRACE);
- dchar c = dtext[i];
- switch (c) {
- case '#':
- buf ~= c;
- if (i + 1 < dtext.length) { mixin(S_TRACE);
- buf ~= dtext[i + 1];
- i++;
- }
- break;
- case Ch1:
- __replOn(dtext, buf, i, dold, dnew, Ch1);
- break;
- case Ch2:
- __replOff(dtext, buf, i, Ch2);
- break;
- default:
- buf ~= c;
- break;
- }
- }
- return toUTF8(buf);
- }
- /// ??????????????????????????
- /// Params:
- /// text = ?????
- /// oldFlag = ??????????
- /// newFlag = ??????????
- string replTextUseFlag(string text, string oldFlag, string newFlag) { mixin(S_TRACE);
- return __replTextFlagStep!('%', '$')(text, oldFlag, newFlag);
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert(replTextUseFlag("?%? ? ?%?", "? ? ?", "? ? ?") == "?%? ? ?%?");
- assert(replTextUseFlag("aaa%aaa%$%???%$%???%a#%???%%aa$%???%", "???", "??no?")
- == "aaa%aaa%$%???%$%??no?%a#%???%%aa$%??no?%");
- }
- /// ???????????????????????????
- /// Params:
- /// text = ?????
- /// oldStep = ???????????
- /// newStep = ???????????
- string replTextUseStep(string text, string oldStep, string newStep) { mixin(S_TRACE);
- return __replTextFlagStep!('$', '%')(text, oldStep, newStep);
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert(replTextUseStep("?$? ? ?$?", "? ? ?", "? ? ?") == "?$? ? ?$?");
- assert(replTextUseStep("aaa$aaa$%$???$%$???$a#$???$$aa%$???$", "???", "??no?")
- == "aaa$aaa$%$???$%$??no?$a#$???$$aa%$??no?$");
- }
- /// ?????????????????????????
- /// Params:
- /// text = ?????
- /// oldFont = ?????????
- /// newFont = ?????????
- string replTextUseFont(string text, string oldFont, string newFont)
- in { mixin(S_TRACE);
- dstring dold = toUTF32(.toLower(oldFont.baseName()));
- dstring dnew = toUTF32(.toLower(newFont.baseName()));
- assert(dold.length == 10, .text(dold));
- assert(startsWith(dold, "font_"d));
- assert(endsWith(dold, ".bmp"d));
- assert(dnew.length == 10, .text(dnew));
- assert(startsWith(dnew, "font_"d));
- assert(endsWith(dnew, ".bmp"d));
- } body { mixin(S_TRACE);
- dstring dtext = toUTF32(text);
- dchar dold = toUTF32(oldFont.baseName())[5];
- dchar dnew = toUTF32(newFont.baseName())[5];
- dstring buf;
- for (size_t i; i < dtext.length; i++) { mixin(S_TRACE);
- dchar c = dtext[i];
- switch (c) {
- case '#':
- buf ~= c;
- if (i + 1 < dtext.length) { mixin(S_TRACE);
- if (.toLower([dtext[i + 1]]) == .toLower([dold])) { mixin(S_TRACE);
- buf ~= dnew;
- } else { mixin(S_TRACE);
- buf ~= dtext[i + 1];
- }
- i++;
- }
- break;
- case '%':
- __replOff(dtext, buf, i, '%');
- break;
- case '$':
- __replOff(dtext, buf, i, '$');
- break;
- default:
- buf ~= c;
- break;
- }
- }
- return toUTF8(buf);
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert(replTextUseFont("#a#?$#?$#b%#?%#?", "font_?.bmp", "Font_?.bmp")
- == "#a#?$#?$#b%#?%#?");
- assert(replTextUseFont("#a#c$#c$#b%#C%#C", "fonT_c.bmp", "font_F.Bmp")
- == "#a#F$#c$#b%#C%#F");
- }
- /// text?start .. end??????color????
- /// %%?$$????????????????
- dstring putColor(dstring text, dchar color, size_t start, size_t end) { mixin(S_TRACE);
- if (start == end) { mixin(S_TRACE);
- return text[0u .. start] ~ cast(dchar) '&' ~ color ~ text[end .. $];
- }
- dchar defColor = 'W';
- if (start >= 1) { mixin(S_TRACE);
- l: foreach_reverse (i, dchar c; text[1u .. start]) { mixin(S_TRACE);
- switch (c) {
- case 'W', 'R', 'B', 'G', 'Y':
- case 'O', 'P', 'L', 'D': // CardWirth 1.50
- if (text[i] == '&') { mixin(S_TRACE);
- defColor = c;
- break l;
- }
- break;
- default:
- }
- }
- }
- if (defColor == color) return text;
- return text[0u .. start] ~ cast(dchar) '&' ~ color
- ~ text[start .. end] ~ cast(dchar) '&' ~ defColor ~ text[end .. $];
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert (putColor("??????"d, 'R', 1, 4) == "?&R???&W??"d);
- assert (putColor("??????"d, 'B', 2, 5) == "??&B???&W?"d);
- assert (putColor("&R??????"d, 'Y', 4, 7) == "&R??&Y???&R?"d);
- assert (putColor("??????"d, 'B', 2, 2) == "??&B????"d);
- }