PageRenderTime 18ms CodeModel.GetById 5ms app.highlight 372ms RepoModel.GetById 1ms app.codeStats 2ms

/cwxeditor_src/cwx/editor/gui/dwt/replacedialog.d

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 4172 lines | 3962 code | 140 blank | 70 comment | 734 complexity | db2c64d38f688f2071e9751bd1eb210b MD5 | raw file
   1
   2module cwx.editor.gui.dwt.replacedialog;
   3
   4import cwx.area;
   5import cwx.summary;
   6import cwx.event;
   7import cwx.coupon;
   8import cwx.utils;
   9import cwx.card;
  10import cwx.motion;
  11import cwx.flag;
  12import cwx.usecounter;
  13import cwx.types;
  14import cwx.path;
  15import cwx.background;
  16import cwx.skin;
  17import cwx.msgutils;
  18import cwx.menu;
  19import cwx.jpy;
  20import cwx.cab;
  21import cwx.features;
  22import cwx.textholder;
  23import cwx.system;
  24import cwx.warning;
  25
  26import cwx.editor.gui.dwt.dprops;
  27import cwx.editor.gui.dwt.dutils;
  28import cwx.editor.gui.dwt.centerlayout;
  29import cwx.editor.gui.dwt.customtable;
  30import cwx.editor.gui.dwt.commons;
  31import cwx.editor.gui.dwt.dskin;
  32import cwx.editor.gui.dwt.splitpane;
  33import cwx.editor.gui.dwt.undo;
  34import cwx.editor.gui.dwt.dmenu;
  35import cwx.editor.gui.dwt.chooser;
  36import cwx.editor.gui.dwt.incsearch;
  37
  38import std.ascii;
  39import std.conv;
  40import std.array;
  41import std.string;
  42import std.file;
  43import std.path;
  44import std.regex : Regex, regex, RegexMatch, match;
  45import std.utf;
  46import std.algorithm : uniq, swap;
  47import std.traits;
  48import std.typecons : Tuple;
  49
  50import org.eclipse.swt.all;
  51
  52import java.lang.all;
  53
  54private class CWXPathString {
  55	string scPath;
  56	CWXPath path;
  57	string array;
  58	this (string scPath, CWXPath path, string array) { mixin(S_TRACE);
  59		this.scPath = scPath;
  60		this.path = path;
  61		this.array = array;
  62	}
  63}
  64private class FilePathString {
  65	string scPath;
  66	string array;
  67	this (string scPath, string array) { mixin(S_TRACE);
  68		this.scPath = scPath;
  69		this.array = array;
  70	}
  71}
  72
  73private class FKeyCodesUndo : TUndo!(FKeyCode[]) {
  74	this (FKeyCode[] old, FKeyCode[] n, void delegate(FKeyCode[]) set) { mixin(S_TRACE);
  75		super (old.dup, n.dup, set, (FKeyCode[] v) {return v.dup;});
  76	}
  77}
  78
  79/// ??????????????
  80class ReplaceDialog {
  81private:
  82	class UndoRepl : UndoArr {
  83		this (Undo[] array, bool rev = true) { mixin(S_TRACE);
  84			super (array, rev);
  85		}
  86		override void undo() { mixin(S_TRACE);
  87			reset(false);
  88			super.undo();
  89			refContentText();
  90			_status.setText(.tryFormat(_prop.msgs.replaceUndo, .formatNum(_result.getItemCount())));
  91			_comm.replText.call();
  92		}
  93		override void redo() { mixin(S_TRACE);
  94			reset(false);
  95			super.redo();
  96			refContentText();
  97			_status.setText(.tryFormat(_prop.msgs.replaceRedo, .formatNum(_result.getItemCount())));
  98			_comm.replText.call();
  99		}
 100	}
 101
 102	class RUndo : Undo {
 103		private CWXPath _path = null;
 104		private string _filePath = null;
 105		private Undo[] _uArr;
 106		this (CWXPath path, Undo[] uArr) { mixin(S_TRACE);
 107			_path = path;
 108			_uArr = uArr;
 109		}
 110		this (string filePath, Undo[] uArr) { mixin(S_TRACE);
 111			_filePath = filePath;
 112			_uArr = uArr;
 113		}
 114		void undo() { mixin(S_TRACE);
 115			size_t dmy = 0;
 116			foreach_reverse (u; _uArr) u.undo();
 117			if (_path) addResult(_path, dmy);
 118			if (_filePath) addResult(_filePath, dmy);
 119		}
 120		void redo() { mixin(S_TRACE);
 121			size_t dmy = 0;
 122			foreach_reverse (u; _uArr) u.redo();
 123			if (_path) addResult(_path, dmy);
 124			if (_filePath) addResult(_filePath, dmy);
 125		}
 126		void dispose() { mixin(S_TRACE);
 127			foreach (u; _uArr) u.dispose();
 128		}
 129	}
 130
 131	void store(string filePath, Undo[] uArr) { mixin(S_TRACE);
 132		_rUndo ~= new RUndo(filePath, uArr);
 133	}
 134	void store(CWXPath path, Undo[] uArr) { mixin(S_TRACE);
 135		_rUndo ~= new RUndo(path, uArr);
 136	}
 137	void store(CWXPath path, string o, string n, void delegate(string) set) { mixin(S_TRACE);
 138		_rUndo ~= new RUndo(path, [new StrUndo(o, n, set)]);
 139	}
 140	void store(CWXPath path, string[] o, string[] n, void delegate(string[]) set) { mixin(S_TRACE);
 141		_rUndo ~= new RUndo(path, [new StrArrUndo(o, n, set)]);
 142	}
 143	void store(CWXPath path, FKeyCode[] o, FKeyCode[] n, void delegate(FKeyCode[]) set) { mixin(S_TRACE);
 144		_rUndo ~= new RUndo(path, [new FKeyCodesUndo(o, n, set)]);
 145	}
 146	void storeID(User, Id)(CWXPath path, User u, Id from, Id to, void delegate(Id) set) { mixin(S_TRACE);
 147		_rUndo ~= new RUndo(path, [new TUndo!Id(from, to, set)]);
 148	}
 149
 150	bool _inProc = false;
 151	bool _inUndo = false;
 152	Undo[] _rUndo;
 153	void delegate()[] _after;
 154	core.thread.Thread _uiThread;
 155
 156	Commons _comm;
 157	Props _prop;
 158	Summary _summ;
 159	UndoManager _undo;
 160
 161	Summary _grepSumm = null;
 162	int _grepCount = -1;
 163	Skin _grepSkin = null;
 164	string _grepFile = "";
 165	bool _inGrep = false;
 166
 167	bool _cancel = false;
 168
 169	Shell _win;
 170	Composite _parent;
 171	CTabFolder _tabf;
 172	CTabItem _tabText;
 173	CTabItem _tabID;
 174	CTabItem _tabPath;
 175	CTabItem _tabContents;
 176	CTabItem _tabCoupon;
 177	CTabItem _tabUnuse;
 178	CTabItem _tabError;
 179	CTabItem _tabGrep;
 180	CTabItem _lastFind = null;
 181	Button _find;
 182	Button _replace;
 183	Button _close;
 184	Button _rangeAllCheck;
 185
 186	bool ignoreMod = false;
 187
 188	Composite _textGrp1, _textGrp2, _textFromComp, _grepFromComp;
 189	Combo _from;
 190	Combo _to;
 191	IncSearch _fromIncSearch = null;
 192	IncSearch _toIncSearch = null;
 193
 194	Combo _idKind;
 195	Combo _fromID;
 196	Composite _fromIDComp;
 197	Spinner _fromIDVal;
 198	ulong[int] _fromIDTbl;
 199	Combo _toID;
 200	Composite _toIDComp;
 201	Spinner _toIDVal;
 202	ulong[int] _toIDTbl;
 203	IncSearch _fromIDIncSearch = null;
 204	IncSearch _toIDIncSearch = null;
 205
 206	Combo _fromPath;
 207	Combo _toPath;
 208	IncSearch _fromPathIncSearch = null;
 209	IncSearch _toPathIncSearch = null;
 210
 211	Combo _grepDir;
 212	Button _grepSubDir;
 213
 214	Button _notIgnoreCase;
 215	Button _useRegex;
 216	Button _useWildcard;
 217	Button _exact;
 218	Button _ignoreReturnCode;
 219	class SelRegex : SelectionAdapter {
 220		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 221			if (_useRegex.getSelection()) { mixin(S_TRACE);
 222				_useWildcard.setSelection(false);
 223			}
 224		}
 225	}
 226	class SelWildcard : SelectionAdapter {
 227		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 228			if (_useWildcard.getSelection()) { mixin(S_TRACE);
 229				_useRegex.setSelection(false);
 230			}
 231		}
 232	}
 233	class SelIgnoreReturnCode : SelectionAdapter {
 234		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 235			_comm.refreshToolBar();
 236		}
 237	}
 238	@property
 239	const
 240	bool catchMod() {return !ignoreMod;}
 241
 242	/// ???
 243	Button _summary;
 244	/// ????????
 245	Button _rCoupon;
 246	/// ?????
 247	Button _msg;
 248	/// ????
 249	Button _cardName;
 250	/// ?????
 251	Button _cardDesc;
 252	/// ????????
 253	Button _event;
 254	/// ?????
 255	Button _start;
 256	/// ???/????
 257	Button _flag;
 258	/// ????
 259	Button _coupon;
 260	/// ????
 261	Button _gossip;
 262	/// ???
 263	Button _end;
 264	/// ???/???/??????
 265	Button _area;
 266	/// ?????
 267	Button _keyCode;
 268	/// ????
 269	Button _file;
 270	/// ????
 271	Button _comment;
 272	/// JPTX????
 273	Button _jptx;
 274
 275	Button[] _noSummText;
 276
 277	Button _unuseFlag;
 278	Button _unuseStep;
 279	Button _unuseArea;
 280	Button _unuseBattle;
 281	Button _unusePackage;
 282	Button _unuseCast;
 283	Button _unuseSkill;
 284	Button _unuseItem;
 285	Button _unuseBeast;
 286	Button _unuseInfo;
 287	Button _unuseStart;
 288	Button _unusePath;
 289
 290	Button _cCoupon;
 291	Button _cGossip;
 292	Button _cEnd;
 293	Button _cKeyCode;
 294	// FIXME: CardWirth 1.60 ????
 295/+	Button _cCellName;
 296+/
 297	Table _result;
 298	TableTextEdit _edit;
 299	Tree _range;
 300
 301	Composite[CTabItem] _comps;
 302
 303	ToolItem[CType] _contents;
 304
 305	Label _status;
 306
 307	bool _notIgnoreCaseSel;
 308	bool _exactSel;
 309	bool _ignoreReturnCodeSel;
 310	bool _summarySel;
 311	bool _msgSel;
 312	bool _cardNameSel;
 313	bool _cardDescSel;
 314	bool _eventSel;
 315	bool _startSel;
 316	bool _flagSel;
 317	bool _couponSel;
 318	bool _gossipSel;
 319	bool _endSel;
 320	bool _areaSel;
 321	bool _keyCodeSel;
 322	bool _fileSel;
 323	bool _commentSel;
 324	bool _jptxSel;
 325	string _fromText;
 326	string _toText;
 327
 328	bool _flagDirOnRange = false;
 329
 330	bool _resultRedraw = true;
 331	void resultRedraw(bool val) { mixin(S_TRACE);
 332		if (!_win || _win.isDisposed()) return;
 333		if (_resultRedraw !is val) { mixin(S_TRACE);
 334			_resultRedraw = val;
 335			_result.setRedraw(val);
 336		}
 337	}
 338
 339	class AddResultPath : Runnable {
 340		size_t count = 0;
 341		string path;
 342		string desc;
 343		void run() { mixin(S_TRACE);
 344			if (cancel) return;
 345			if (!_win || _win.isDisposed()) return;
 346			if (_inProc && !_prop.var.etc.searchResultRealtime) resultRedraw(false);
 347			auto itm = new TableItem(_result, SWT.NONE);
 348			auto summ = _grepSumm ? _grepSumm : _summ;
 349			auto fullPath = std.path.buildPath(summ.scenarioPath, path);
 350			if (_grepSumm) { mixin(S_TRACE);
 351				if (!_grepSkin) _grepSkin = findSkin(_comm, _prop, summ);
 352				itm.setImage(fimage(fullPath, _grepSkin));
 353			} else { mixin(S_TRACE);
 354				itm.setImage(fimage(fullPath, _comm.skin));
 355			}
 356			string scPath = null;
 357			string text = encodePath(path);
 358			itm.setText(0, text);
 359			if (desc.length) { mixin(S_TRACE);
 360				itm.setText(2, desc);
 361				itm.setImage(2, _prop.images.warning);
 362			}
 363			if (_grepSumm) { mixin(S_TRACE);
 364				scPath = _grepSumm.useTemp ? _grepSumm.zipName : _grepSumm.scenarioPath;
 365				text = .tryFormat(_prop.msgs.grepScenario, _grepSumm.scenarioName, scPath);
 366				itm.setText(2, text);
 367				itm.setImage(2, _prop.images.summary);
 368			}
 369			itm.setData(new FilePathString(scPath, path));
 370			refResultStatus(count, false);
 371		}
 372	}
 373	class AddResultCWXPath : Runnable {
 374		CWXPath path;
 375		int index;
 376		string desc;
 377		size_t count = 0;
 378		void run() { mixin(S_TRACE);
 379			if (cancel) return;
 380			if (!_win || _win.isDisposed()) return;
 381			if (_inProc && !_prop.var.etc.searchResultRealtime) resultRedraw(false);
 382			auto itm = new TableItem(_result, SWT.NONE, -1 == index ? _result.getItemCount() : index);
 383			string text1, text2;
 384			Image img1, img2;
 385			getPathParams(path, text1, text2, img1, img2);
 386			itm.setImage(0, img1);
 387			itm.setText(0, text1);
 388			itm.setImage(1, img2);
 389			itm.setText(1, text2);
 390			if (desc.length) { mixin(S_TRACE);
 391				itm.setText(2, desc);
 392				itm.setImage(2, _prop.images.warning);
 393			}
 394			string scPath = null;
 395			if (_grepSumm) { mixin(S_TRACE);
 396				scPath = _grepSumm.useTemp ? _grepSumm.zipName : _grepSumm.scenarioPath;
 397				itm.setText(2, .tryFormat(_prop.msgs.grepScenario, _grepSumm.scenarioName, scPath));
 398				itm.setImage(2, _prop.images.summary);
 399			}
 400			itm.setData(new CWXPathString(scPath, _grepSumm ? null : path, path.cwxPath(true)));
 401			refResultStatus(count, false);
 402		}
 403	}
 404	class AddResultMsg : Runnable {
 405		string name;
 406		Image delegate() image;
 407		int index;
 408		size_t count = 0;
 409		void run() { mixin(S_TRACE);
 410			if (cancel) return;
 411			if (!_win || _win.isDisposed()) return;
 412			if (_inProc && !_prop.var.etc.searchResultRealtime) resultRedraw(false);
 413			auto itm = new TableItem(_result, SWT.NONE, -1 == index ? _result.getItemCount() : index);
 414			itm.setText(name);
 415			itm.setImage(image());
 416			refResultStatus(count, false);
 417		}
 418	}
 419	class AddResultUse : Runnable {
 420		string name;
 421		uint use;
 422		Image delegate() image;
 423		int index;
 424		size_t count = 0;
 425		void run() { mixin(S_TRACE);
 426			if (cancel) return;
 427			if (!_win || _win.isDisposed()) return;
 428			if (_inProc && !_prop.var.etc.searchResultRealtime) resultRedraw(false);
 429			auto itm = new TableItem(_result, SWT.NONE, -1 == index ? _result.getItemCount() : index);
 430			itm.setText(0, name);
 431			itm.setImage(0, image());
 432			itm.setText(1, .text(use));
 433			refResultStatus(count, false);
 434		}
 435	}
 436	Display _display;
 437
 438	class ML : MouseAdapter {
 439		public override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
 440			if (_result.isFocusControl() && e.button == 1) { mixin(S_TRACE);
 441				openPath();
 442			}
 443		}
 444	}
 445	class KL : KeyAdapter {
 446		public override void keyPressed(KeyEvent e) { mixin(S_TRACE);
 447			if (_result.isFocusControl() && e.character == SWT.CR) { mixin(S_TRACE);
 448				openPath();
 449			}
 450		}
 451	}
 452	static const ID_AREA = 0;
 453	static const ID_BATTLE = 1;
 454	static const ID_PACKAGE = 2;
 455	static const ID_CAST = 3;
 456	static const ID_SKILL = 4;
 457	static const ID_ITEM = 5;
 458	static const ID_BEAST = 6;
 459	static const ID_INFO = 7;
 460	static const ID_FLAG = 8;
 461	static const ID_STEP = 9;
 462	static const ID_COUPON = 10;
 463	static const ID_GOSSIP = 11;
 464	static const ID_COMPLETE_STAMP = 12;
 465	static const ID_KEY_CODE = 13;
 466	// FIXME: CardWirth 1.60 ????
 467/+	static const ID_CELL_NAME = 14;
 468+/	private void setupIDsImpl2(T)(T[] arr, Combo combo, Spinner spn, ref ulong[int] tbl, bool clear, IncSearch incSearch) { mixin(S_TRACE);
 469		ulong[int] tbl2;
 470		string oldSel = clear ? "" : combo.getText();
 471		combo.removeAll();
 472		static if (is(T:Flag) || is(T:Step)) {
 473			auto set = new HashSet!string;
 474			if (_summ) { mixin(S_TRACE);
 475				static if (is(T:Flag)) {
 476					foreach (key; _summ.useCounter.flag.keys) { mixin(S_TRACE);
 477						if (_prop.sys.randomValue == cast(string)key) continue;
 478						if (!incSearch.match(cast(string)key)) continue;
 479						set.add(cast(string)key);
 480					}
 481				} else static if (is(T:Step)) {
 482					foreach (key; _summ.useCounter.step.keys) { mixin(S_TRACE);
 483						if (_prop.sys.randomValue == cast(string)key) continue;
 484						if (!incSearch.match(cast(string)key)) continue;
 485						set.add(cast(string)key);
 486					}
 487				} else static assert (0);
 488			}
 489			foreach (i, a; arr) { mixin(S_TRACE);
 490				auto p = a.path;
 491				if (p == "") continue;
 492				if (!incSearch.match(p)) continue;
 493				combo.add(p);
 494				set.remove(p);
 495			}
 496			bool delegate(string a, string b) cmps;
 497			if (_prop.var.etc.logicalSort) { mixin(S_TRACE);
 498				cmps = (a, b) => incmp(a, b) < 0;
 499			} else { mixin(S_TRACE);
 500				cmps = (a, b) => icmp(a, b) < 0;
 501			}
 502			foreach (p; .sortDlg(set.array(), cmps)) { mixin(S_TRACE);
 503				if (p == "") continue;
 504				if (!incSearch.match(p)) continue;
 505				combo.add(p);
 506			}
 507			combo.setText(oldSel);
 508			if (combo.getText() == "" && combo.getItemCount()) { mixin(S_TRACE);
 509				combo.select(0);
 510			}
 511			spn.setEnabled(false);
 512		} else static if (is(T:CouponId) || is(T:GossipId) || is(T:CompleteStampId) || is(T:KeyCodeId) || is(T:CellNameId)) {
 513			string[] arr2;
 514			static if (is(T:CouponId)) {
 515				arr2 = .allCoupons(_comm, _summ, CouponComboType.AllCoupons);
 516			} else static if (is(T:GossipId)) {
 517				arr2 = .allGossips(_comm, _summ);
 518			} else static if (is(T:CompleteStampId)) {
 519				arr2 = .allCompleteStamps(_comm, _summ);
 520			} else static if (is(T:KeyCodeId)) {
 521				arr2 = .allKeyCodes(_comm, _summ);
 522			} else static if (is(T:CellNameId)) {
 523				arr2 = .allCellNames(_comm, _summ);
 524			} else static assert (0);
 525			foreach (a; arr2) {
 526				if (!incSearch.match(a)) continue;
 527				combo.add(a);
 528			}
 529			combo.setText(oldSel);
 530			if (combo.getText() == "" && combo.getItemCount()) { mixin(S_TRACE);
 531				combo.select(0);
 532			}
 533			spn.setEnabled(false);
 534		} else {
 535			combo.add(_prop.msgs.replSetID);
 536			foreach (i, a; arr) { mixin(S_TRACE);
 537				if (!incSearch.match(a.name)) continue;
 538				combo.add(to!(string)(a.id) ~ "." ~ a.name);
 539				tbl2[i + 1] = a.id;
 540			}
 541			combo.select(1 < combo.getItemCount() ? 1 : 0);
 542			if (oldSel) { mixin(S_TRACE);
 543				auto i = combo.indexOf(oldSel);
 544				if (i >= 0) combo.select(i);
 545			}
 546			spn.setEnabled(combo.getSelectionIndex() == 0);
 547		}
 548		tbl = tbl2;
 549	}
 550	private void setupIDsImpl1(T)(T[] arr, bool clear, bool from, bool to) { mixin(S_TRACE);
 551		if (from) setupIDsImpl2(arr, _fromID, _fromIDVal, _fromIDTbl, clear, _fromIDIncSearch);
 552		if (to) setupIDsImpl2(arr, _toID, _toIDVal, _toIDTbl, clear, _toIDIncSearch);
 553	}
 554	private void setupIDs(bool clear, bool from, bool to) { mixin(S_TRACE);
 555		if (!_summ) { mixin(S_TRACE);
 556			_fromID.removeAll();
 557			_fromID.setEnabled(false);
 558			_fromIDVal.setEnabled(false);
 559			_toID.removeAll();
 560			_toID.setEnabled(false);
 561			_toIDVal.setEnabled(false);
 562			return;
 563		}
 564		if (from) _fromID.setEnabled(true);
 565		if (to) _toID.setEnabled(true);
 566		switch (_idKind.getSelectionIndex()) {
 567		case ID_AREA: setupIDsImpl1(_summ.areas, clear, from, to); break;
 568		case ID_BATTLE: setupIDsImpl1(_summ.battles, clear, from, to); break;
 569		case ID_PACKAGE: setupIDsImpl1(_summ.packages, clear, from, to); break;
 570		case ID_CAST: setupIDsImpl1(_summ.casts, clear, from, to); break;
 571		case ID_SKILL: setupIDsImpl1(_summ.skills, clear, from, to); break;
 572		case ID_ITEM: setupIDsImpl1(_summ.items, clear, from, to); break;
 573		case ID_BEAST: setupIDsImpl1(_summ.beasts, clear, from, to); break;
 574		case ID_INFO: setupIDsImpl1(_summ.infos, clear, from, to); break;
 575		case ID_FLAG: setupIDsImpl1(_summ.flagDirRoot.allFlags, clear, from, to); break;
 576		case ID_STEP: setupIDsImpl1(_summ.flagDirRoot.allSteps, clear, from, to); break;
 577		case ID_COUPON: setupIDsImpl1(_summ.useCounter.coupon.keys, clear, from, to); break;
 578		case ID_GOSSIP: setupIDsImpl1(_summ.useCounter.gossip.keys, clear, from, to); break;
 579		case ID_COMPLETE_STAMP: setupIDsImpl1(_summ.useCounter.completeStamp.keys, clear, from, to); break;
 580		case ID_KEY_CODE: setupIDsImpl1(_summ.useCounter.keyCode.keys, clear, from, to); break;
 581		// FIXME: CardWirth 1.60 ????
 582/+		case ID_CELL_NAME: setupIDsImpl1(_summ.useCounter.cellName.keys, clear, from, to); break;
 583+/		default: assert (0);
 584		}
 585	}
 586	private void fromIDIncSearch() { mixin(S_TRACE);
 587		.forceFocus(_fromID, true);
 588		_fromIDIncSearch.startIncSearch();
 589	}
 590	private void toIDIncSearch() { mixin(S_TRACE);
 591		.forceFocus(_toID, true);
 592		_toIDIncSearch.startIncSearch();
 593	}
 594
 595	private string[] _lastMaterialPaths;
 596	private string[] allMaterials(bool scenarioOnly) { mixin(S_TRACE);
 597		if (!_summ) return [];
 598		return _summ.allMaterials(_comm.skin, _prop.var.etc.ignorePaths, _prop.var.etc.logicalSort, scenarioOnly);
 599	}
 600	private void setupPaths() { mixin(S_TRACE);
 601		bool oldIgnoreMod = ignoreMod;
 602		ignoreMod = true;
 603		scope (exit) ignoreMod = oldIgnoreMod;
 604
 605		_lastMaterialPaths = [""] ~ allMaterials(false);
 606		setupPathsImpl(true, true);
 607	}
 608	private void setupPathsImpl(bool from, bool to) {
 609		void setPaths(Combo combo, IncSearch incSearch) { mixin(S_TRACE);
 610			auto old = combo.getText();
 611			combo.removeAll();
 612			foreach (path; _lastMaterialPaths) {
 613				if (!incSearch.match(path)) continue;
 614				combo.add(path);
 615			}
 616			combo.setText(old);
 617		}
 618		if (from) setPaths(_fromPath, _fromPathIncSearch);
 619		if (to) setPaths(_toPath, _toPathIncSearch);
 620	}
 621	class SListener : ShellAdapter {
 622		override void shellActivated(ShellEvent e) { mixin(S_TRACE);
 623			setupIDs(false, true, true);
 624			setupPaths();
 625			_comm.refreshToolBar();
 626		}
 627	}
 628	class SelID : SelectionAdapter {
 629		private Spinner _spn;
 630		this (Spinner spn) {_spn = spn;}
 631		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 632			auto combo = cast(Combo) e.widget;
 633			_spn.setEnabled(combo.getSelectionIndex() == 0);
 634			_comm.refreshToolBar();
 635		}
 636	}
 637	class SelIDKind : SelectionAdapter {
 638		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 639			selIDKind();
 640		}
 641	}
 642	void selIDKind() {
 643		updateIDCombo();
 644		setupIDs(true, true, true);
 645		_prop.var.etc.searchIDKind = _idKind.getSelectionIndex();
 646		_comm.refreshToolBar();
 647	}
 648	@property
 649	private bool idKindIsString() {
 650		auto index = _idKind.getSelectionIndex();
 651		// FIXME: CardWirth 1.60 ???? ????
 652/+		return index == ID_FLAG || index == ID_STEP || index == ID_COUPON || index == ID_GOSSIP || index == ID_COMPLETE_STAMP || index == ID_KEY_CODE || index == ID_CELL_NAME;
 653+/		return index == ID_FLAG || index == ID_STEP || index == ID_COUPON || index == ID_GOSSIP || index == ID_COMPLETE_STAMP || index == ID_KEY_CODE;
 654		// FIXME: CardWirth 1.60 ???? ????
 655	}
 656	private void updateIDCombo() { mixin(S_TRACE);
 657		if (idKindIsString) { mixin(S_TRACE);
 658			if (_fromID && !(_fromID.getStyle() & SWT.READ_ONLY)) return;
 659			if (_fromID) { mixin(S_TRACE);
 660				_fromID.dispose();
 661				_toID.dispose();
 662			}
 663			
 664			_fromID = new Combo(_fromIDComp, SWT.BORDER | SWT.DROP_DOWN);
 665			_fromID.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 666			_toID = new Combo(_toIDComp, SWT.BORDER | SWT.DROP_DOWN);
 667			_toID.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 668		} else { mixin(S_TRACE);
 669			if (_fromID && (_fromID.getStyle() & SWT.READ_ONLY)) return;
 670			if (_fromID) { mixin(S_TRACE);
 671				_fromID.dispose();
 672				_toID.dispose();
 673			}
 674			_fromID = new Combo(_fromIDComp, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
 675			_fromID.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 676			_fromID.addSelectionListener(new SelID(_fromIDVal));
 677			_toID = new Combo(_toIDComp, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
 678			_toID.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 679			_toID.addSelectionListener(new SelID(_toIDVal));
 680		}
 681		auto fMenu = new Menu(_win, SWT.POP_UP);
 682		_fromID.setMenu(fMenu);
 683		createMenuItem(_comm, fMenu, MenuID.IncSearch, &fromIDIncSearch, null);
 684		new MenuItem(fMenu, SWT.SEPARATOR);
 685		createTextMenu!Combo(_comm, _prop, _fromID, &catchMod);
 686
 687		auto tMenu = new Menu(_win, SWT.POP_UP);
 688		_toID.setMenu(tMenu);
 689		createMenuItem(_comm, tMenu, MenuID.IncSearch, &toIDIncSearch, null);
 690		new MenuItem(tMenu, SWT.SEPARATOR);
 691		createTextMenu!Combo(_comm, _prop, _toID, &catchMod);
 692
 693		_fromIDIncSearch = new IncSearch(_comm, _fromID);
 694		_fromIDIncSearch.modEvent ~= () => setupIDs(false, true, false);
 695		_toIDIncSearch = new IncSearch(_comm, _toID);
 696		_toIDIncSearch.modEvent ~= () => setupIDs(false, false, true);
 697
 698		_fromIDComp.layout();
 699		_toIDComp.layout();
 700	}
 701	private void tabChanged() { mixin(S_TRACE);
 702		auto sel = _tabf.getSelection();
 703		if (!sel) return;
 704
 705		_parent.setRedraw(false);
 706		scope (exit) _parent.setRedraw(true);
 707
 708		_prop.var.etc.searchPlan = _tabf.getSelectionIndex();
 709		if (sel is _tabText || sel is _tabGrep) { mixin(S_TRACE);
 710			auto comp = _comps[sel is _tabGrep ? _tabGrep : _tabText];
 711			if (_textGrp1.getParent() !is comp) _textGrp1.setParent(comp);
 712			if (_textGrp2.getParent() !is comp) _textGrp2.setParent(comp);
 713			auto fromComp = sel is _tabGrep ? _grepFromComp : _textFromComp;
 714			if (_from.getParent() !is fromComp) { mixin(S_TRACE);
 715				_from.setParent(fromComp);
 716			}
 717		}
 718		foreach (tab, comp; _comps) { mixin(S_TRACE);
 719			auto gd = cast(GridData) comp.getLayoutData();
 720			if (tab is sel) { mixin(S_TRACE);
 721				gd.heightHint= SWT.DEFAULT;
 722			} else { mixin(S_TRACE);
 723				gd.heightHint= 0;
 724			}
 725		}
 726		_parent.layout(true);
 727		_replace.setEnabled(!(sel is _tabText && _ignoreReturnCode.getSelection()) && sel !is _tabContents && sel !is _tabCoupon && sel !is _tabUnuse && sel !is _tabError);
 728		_range.setEnabled(sel !is _tabUnuse && sel !is _tabGrep);
 729		_rangeAllCheck.setEnabled(_range.getEnabled());
 730		_comm.refreshToolBar();
 731	}
 732	class TSListener : SelectionAdapter {
 733		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 734			tabChanged();
 735		}
 736	}
 737	LCheck[] _checked;
 738	class LCheck : SelectionAdapter {
 739		Widget[] buttons;
 740		private Button _all = null;
 741		private void setSelection(Widget b, bool s) { mixin(S_TRACE);
 742			auto button = cast(Button) b;
 743			if (button) button.setSelection(s);
 744			auto ti = cast(ToolItem) b;
 745			if (ti) ti.setSelection(s);
 746		}
 747		private bool getSelection(Widget b) { mixin(S_TRACE);
 748			auto button = cast(Button) b;
 749			if (button) return button.getSelection();
 750			auto ti = cast(ToolItem) b;
 751			if (ti) return ti.getSelection();
 752			assert (0);
 753		}
 754		class AllCheck : SelectionAdapter {
 755			override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 756				foreach (b; buttons) { mixin(S_TRACE);
 757					setSelection(b, _all.getSelection());
 758				}
 759			}
 760		}
 761		void check() { mixin(S_TRACE);
 762			bool checked = true;
 763			foreach (b; buttons) { mixin(S_TRACE);
 764				checked &= getSelection(b);
 765			}
 766			_all.setSelection(checked);
 767		}
 768		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
 769			assert (_all);
 770			check();
 771		}
 772		void createAlls(Composite parent, string text) { mixin(S_TRACE);
 773			_all = new Button(parent, SWT.CHECK);
 774			_all.setText(text);
 775			_all.addSelectionListener(new AllCheck);
 776			check();
 777		}
 778	}
 779	Composite addButtonLine(Composite grp) { mixin(S_TRACE);
 780		auto comp = new Composite(grp, SWT.NONE);
 781		comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 782		auto rl = new RowLayout(SWT.HORIZONTAL);
 783		rl.wrap = true;
 784		rl.pack = false;
 785		comp.setLayout(rl);
 786		return comp;
 787	}
 788	void constructText(CTabFolder tabf) { mixin(S_TRACE);
 789		auto comp = new Composite(tabf, SWT.NONE);
 790		comp.setLayout(new GridLayout(1, true));
 791		auto comp2 = new Composite(comp, SWT.NONE);
 792		auto comp2gl = windowGridLayout(1, true);
 793		comp2gl.marginWidth = 0;
 794		comp2gl.marginHeight = 0;
 795		comp2.setLayout(comp2gl);
 796		{ mixin(S_TRACE);
 797			auto grp = new Group(comp2, SWT.NONE);
 798			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 799			grp.setText(_prop.msgs.replText);
 800			grp.setLayout(new GridLayout(2, false));
 801			auto fl = new Label(grp, SWT.NONE);
 802			fl.setText(_prop.msgs.replFrom);
 803			_textFromComp = new Composite(grp, SWT.NONE);
 804			_textFromComp.setLayout(new FillLayout);
 805			_from = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN);
 806			_from.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 807			auto gd = new GridData(GridData.FILL_HORIZONTAL);
 808			gd.widthHint = _prop.var.etc.nameWidth;
 809			_textFromComp.setLayoutData(gd);
 810			auto lt = new Label(grp, SWT.NONE);
 811			lt.setText(_prop.msgs.replTo);
 812			_to = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN);
 813			_to.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 814			_to.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 815
 816			auto fMenu = new Menu(_win, SWT.POP_UP);
 817			_from.setMenu(fMenu);
 818			createMenuItem(_comm, fMenu, MenuID.IncSearch, {
 819				.forceFocus(_from, true);
 820				_fromIncSearch.startIncSearch();
 821			}, null);
 822			new MenuItem(fMenu, SWT.SEPARATOR);
 823			createTextMenu!Combo(_comm, _prop, _from, &catchMod);
 824
 825			auto tMenu = new Menu(_win, SWT.POP_UP);
 826			_to.setMenu(tMenu);
 827			createMenuItem(_comm, tMenu, MenuID.IncSearch, {
 828				.forceFocus(_to, true);
 829				_toIncSearch.startIncSearch();
 830			}, null);
 831			new MenuItem(tMenu, SWT.SEPARATOR);
 832			createTextMenu!Combo(_comm, _prop, _to, &catchMod);
 833
 834			_fromIncSearch = new IncSearch(_comm, _from);
 835			_fromIncSearch.modEvent ~= &updateFromHistory;
 836			_toIncSearch = new IncSearch(_comm, _to);
 837			_toIncSearch.modEvent ~= &updateToHistory;
 838		}
 839		{ mixin(S_TRACE);
 840			auto grp = new Group(comp2, SWT.NONE);
 841			_textGrp1 = grp;
 842			auto gd = new GridData(GridData.FILL_HORIZONTAL);
 843			gd.widthHint = _prop.var.etc.searchResultTableWidth;
 844			grp.setLayoutData(gd);
 845			grp.setText(_prop.msgs.replCond);
 846			grp.setLayout(new GridLayout(3, false));
 847			_notIgnoreCase = new Button(grp, SWT.CHECK);
 848			_notIgnoreCase.setText(_prop.msgs.replNotIgnoreCase);
 849			_exact = new Button(grp, SWT.CHECK);
 850			_exact.setText(_prop.msgs.replExactMatch);
 851			_ignoreReturnCode = new Button(grp, SWT.CHECK);
 852			_ignoreReturnCode.setText(_prop.msgs.replIgnoreReturnCode);
 853			_ignoreReturnCode.addSelectionListener(new SelIgnoreReturnCode);
 854			_useWildcard = new Button(grp, SWT.CHECK);
 855			_useWildcard.setText(_prop.msgs.replWildcard);
 856			_useWildcard.addSelectionListener(new SelWildcard);
 857			auto gdw = new GridData;
 858			gdw.horizontalSpan = 3;
 859			_useWildcard.setLayoutData(gdw);
 860			_useRegex = new Button(grp, SWT.CHECK);
 861			_useRegex.setText(_prop.msgs.replRegExp);
 862			_useRegex.addSelectionListener(new SelRegex);
 863			auto gdr = new GridData;
 864			gdr.horizontalSpan = 3;
 865			_useRegex.setLayoutData(gdr);
 866		}
 867		{ mixin(S_TRACE);
 868			auto grp = new Group(comp2, SWT.NONE);
 869			_textGrp2 = grp;
 870			auto gd = new GridData(GridData.FILL_HORIZONTAL);
 871			gd.widthHint = _prop.var.etc.searchResultTableWidth;
 872			grp.setLayoutData(gd);
 873			grp.setText(_prop.msgs.replTextTarget);
 874			grp.setLayout(zeroGridLayout(1, true));
 875			auto checked = new LCheck;
 876			_checked ~= checked;
 877			{ mixin(S_TRACE);
 878				auto btns = addButtonLine(grp);
 879				Button createB(string text, char accr, bool summ = false) { mixin(S_TRACE);
 880					auto b = new Button(btns, SWT.CHECK);
 881					b.setText(text ~ "(&" ~ accr ~ ")");
 882					checked.buttons ~= b;
 883					b.addSelectionListener(checked);
 884					if (!summ) _noSummText ~= b;
 885					return b;
 886				}
 887				_summary = createB(_prop.msgs.replTextSummary, '1', true);
 888				_msg = createB(_prop.msgs.replTextMessage, '2');
 889				_cardName = createB(_prop.msgs.replTextCardName, '3');
 890				_cardDesc = createB(_prop.msgs.replTextCardDesc, '4');
 891				_event = createB(_prop.msgs.replTextEventText, '5');
 892				_start = createB(_prop.msgs.replTextStart, '6');
 893				_flag = createB(_prop.msgs.replTextFlagAndStep, '7');
 894				_coupon = createB(_prop.msgs.replTextCoupon, '8');
 895				_gossip = createB(_prop.msgs.replTextGossip, '9');
 896				_end = createB(_prop.msgs.replTextEndScenario, 'A');
 897				_area = createB(_prop.msgs.replTextAreaName, 'B');
 898				_keyCode = createB(_prop.msgs.replTextKeyCode, 'D');
 899				_file = createB(_prop.msgs.replTextFile, 'E');
 900				_comment = createB(_prop.msgs.replTextComment, 'G');
 901				_jptx = createB(_prop.msgs.replTextJptx, 'H');
 902			}
 903			auto sep = new Label(grp, SWT.SEPARATOR | SWT.HORIZONTAL);
 904			sep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 905			{ mixin(S_TRACE);
 906				auto btns = addButtonLine(grp);
 907				checked.createAlls(btns, _prop.msgs.allCheck);
 908			}
 909		}
 910
 911		auto tab = new CTabItem(tabf, SWT.NONE);
 912		tab.setText(_prop.msgs.replForText);
 913		tab.setControl(comp);
 914		_tabText = tab;
 915
 916		auto gd = new GridData(GridData.FILL_BOTH);
 917		comp2.setLayoutData(gd);
 918		_comps[tab] = comp2;
 919	}
 920	void constructID(CTabFolder tabf) { mixin(S_TRACE);
 921		auto comp = new Composite(tabf, SWT.NONE);
 922		comp.setLayout(new GridLayout(1, true));
 923		auto comp2 = new Composite(comp, SWT.NONE);
 924		comp2.setLayout(zeroGridLayout(1, true));
 925		{ mixin(S_TRACE);
 926			auto grp = new Group(comp2, SWT.NONE);
 927			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 928			grp.setText(_prop.msgs.replID);
 929			grp.setLayout(new GridLayout(3, false));
 930			{ mixin(S_TRACE);
 931				auto l = new Label(grp, SWT.NONE);
 932				l.setText(_prop.msgs.replIDKind);
 933				_idKind = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
 934				_idKind.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
 935				_idKind.add(_prop.msgs.replIDArea);
 936				_idKind.add(_prop.msgs.replIDBattle);
 937				_idKind.add(_prop.msgs.replIDPackage);
 938				_idKind.add(_prop.msgs.replIDCast);
 939				_idKind.add(_prop.msgs.replIDSkill);
 940				_idKind.add(_prop.msgs.replIDItem);
 941				_idKind.add(_prop.msgs.replIDBeast);
 942				_idKind.add(_prop.msgs.replIDInfo);
 943				_idKind.add(_prop.msgs.replIDFlag);
 944				_idKind.add(_prop.msgs.replIDStep);
 945				_idKind.add(_prop.msgs.replIDCoupon);
 946				_idKind.add(_prop.msgs.replIDGossip);
 947				_idKind.add(_prop.msgs.replIDCompleteStamp);
 948				_idKind.add(_prop.msgs.replIDKeyCode);
 949				// FIXME: CardWirth 1.60 ????
 950/+				_idKind.add(_prop.msgs.replIDCellName);
 951+/				_idKind.select(0);
 952				if (0 <= _prop.var.etc.searchIDKind && _prop.var.etc.searchIDKind < _idKind.getItemCount()) { mixin(S_TRACE);
 953					_idKind.select(_prop.var.etc.searchIDKind);
 954				}
 955				auto gd = new GridData;
 956				gd.horizontalSpan = 2;
 957				_idKind.setLayoutData(gd);
 958				_idKind.addSelectionListener(new SelIDKind);
 959			}
 960			{ mixin(S_TRACE);
 961				auto sep = new Label(grp, SWT.SEPARATOR | SWT.HORIZONTAL);
 962				auto gd = new GridData(GridData.FILL_HORIZONTAL);
 963				gd.horizontalSpan = 3;
 964				sep.setLayoutData(gd);
 965			}
 966			void setupID(string text, ref Composite comboComp, ref Spinner spn) { mixin(S_TRACE);
 967				auto l = new Label(grp, SWT.NONE);
 968				l.setText(text);
 969				comboComp = new Composite(grp, SWT.NONE);
 970				auto cl = new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0);
 971				cl.fillHorizontal = true;
 972				cl.fillVertical = true;
 973				comboComp.setLayout(cl);
 974				auto gd = new GridData(GridData.FILL_HORIZONTAL);
 975				gd.widthHint = _prop.var.etc.nameWidth;
 976				comboComp.setLayoutData(gd);
 977				spn = new Spinner(grp, SWT.BORDER);
 978				initSpinner(spn);
 979				spn.setMinimum(1);
 980				spn.setMaximum(_prop.looks.idMax);
 981			}
 982			setupID(_prop.msgs.replFrom, _fromIDComp, _fromIDVal);
 983			setupID(_prop.msgs.replTo, _toIDComp, _toIDVal);
 984			updateIDCombo();
 985		}
 986
 987		auto tab = new CTabItem(tabf, SWT.NONE);
 988		tab.setText(_prop.msgs.replForID);
 989		tab.setControl(comp);
 990		_tabID = tab;
 991
 992		auto gd = new GridData(GridData.FILL_BOTH);
 993		gd.heightHint = 0;
 994		comp2.setLayoutData(gd);
 995		_comps[tab] = comp2;
 996	}
 997	void constructPath(CTabFolder tabf) { mixin(S_TRACE);
 998		auto comp = new Composite(tabf, SWT.NONE);
 999		comp.setLayout(new GridLayout(1, true));
1000		auto comp2 = new Composite(comp, SWT.NONE);
1001		comp2.setLayout(zeroGridLayout(1, true));
1002		{ mixin(S_TRACE);
1003			auto grp = new Group(comp2, SWT.NONE);
1004			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1005			grp.setText(_prop.msgs.replPath);
1006			grp.setLayout(new GridLayout(2, false));
1007			Combo setupPath(string text, ref IncSearch incSearch) { mixin(S_TRACE);
1008				auto l = new Label(grp, SWT.NONE);
1009				l.setText(text);
1010				auto combo = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN);
1011				combo.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
1012				auto gd = new GridData(GridData.FILL_HORIZONTAL);
1013				gd.widthHint = _prop.var.etc.nameWidth;
1014				combo.setLayoutData(gd);
1015
1016				auto menu = new Menu(_win, SWT.POP_UP);
1017				combo.setMenu(menu);
1018				createMenuItem(_comm, menu, MenuID.IncSearch, {
1019					.forceFocus(combo, true);
1020					incSearch.startIncSearch();
1021				}, null);
1022				new MenuItem(menu, SWT.SEPARATOR);
1023				createTextMenu!Combo(_comm, _prop, combo, &catchMod);
1024
1025				incSearch = new IncSearch(_comm, combo);
1026
1027				return combo;
1028			}
1029			_fromPath = setupPath(_prop.msgs.replFrom, _fromPathIncSearch);
1030			_fromPathIncSearch.modEvent ~= () => setupPathsImpl(true, false);
1031			_toPath = setupPath(_prop.msgs.replTo, _toPathIncSearch);
1032			_fromPathIncSearch.modEvent ~= () => setupPathsImpl(false, true);
1033		}
1034
1035		auto tab = new CTabItem(tabf, SWT.NONE);
1036		tab.setText(_prop.msgs.replForPath);
1037		tab.setControl(comp);
1038		_tabPath = tab;
1039
1040		auto gd = new GridData(GridData.FILL_BOTH);
1041		gd.heightHint = 0;
1042		comp2.setLayoutData(gd);
1043		_comps[tab] = comp2;
1044	}
1045	void constructContents(CTabFolder tabf) { mixin(S_TRACE);
1046		auto comp = new Composite(tabf, SWT.NONE);
1047		comp.setLayout(new GridLayout(1, true));
1048		auto comp2 = new Composite(comp, SWT.NONE);
1049		comp2.setLayout(zeroGridLayout(1, true));
1050		{ mixin(S_TRACE);
1051			auto grp = new Group(comp2, SWT.NONE);
1052			auto gd = new GridData(GridData.FILL_HORIZONTAL);
1053			gd.widthHint = _prop.var.etc.searchResultTableWidth;
1054			grp.setLayoutData(gd);
1055			grp.setText(_prop.msgs.searchRange);
1056			grp.setLayout(zeroGridLayout(1, true));
1057			auto checked = new LCheck;
1058			_checked ~= checked;
1059
1060			auto comp3 = new Composite(grp, SWT.NONE);
1061			comp3.setLayoutData(new GridData(GridData.FILL_BOTH));
1062			comp3.setLayout(windowGridLayout(1, true));
1063			auto bar = new ToolBar(comp3, SWT.HORIZONTAL | SWT.FLAT | SWT.WRAP);
1064			_comm.put(bar);
1065			bar.setLayoutData(new GridData(GridData.FILL_BOTH));
1066			foreach (cGrp, cs; CTYPE_GROUP) { mixin(S_TRACE);
1067				foreach (cType; cs) { mixin(S_TRACE);
1068					auto text = _prop.msgs.contentName(cType);
1069					auto img = _prop.images.content(cType);
1070					void delegate() func = null;
1071					auto ti = createToolItem2(_comm, bar, text, img, func, null, SWT.CHECK);
1072					_contents[cType] = ti;
1073					checked.buttons ~= ti;
1074					ti.addSelectionListener(checked);
1075				}
1076				if (cGrp < CTypeGroup.max) { mixin(S_TRACE);
1077					new ToolItem(bar, SWT.SEPARATOR);
1078				}
1079			}
1080			auto sep = new Label(grp, SWT.SEPARATOR | SWT.HORIZONTAL);
1081			sep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1082
1083			auto btns = addButtonLine(grp);
1084			checked.createAlls(btns, _prop.msgs.allSelect);
1085		}
1086
1087		auto tab = new CTabItem(tabf, SWT.NONE);
1088		tab.setText(_prop.msgs.replContents);
1089		tab.setControl(comp);
1090		_tabContents = tab;
1091
1092		auto gd = new GridData(GridData.FILL_BOTH);
1093		gd.heightHint = 0;
1094		comp2.setLayoutData(gd);
1095		_comps[tab] = comp2;
1096	}
1097	void constructCoupon(CTabFolder tabf) { mixin(S_TRACE);
1098		auto comp = new Composite(tabf, SWT.NONE);
1099		comp.setLayout(new GridLayout(1, true));
1100		auto comp2 = new Composite(comp, SWT.NONE);
1101		auto comp2gl = windowGridLayout(1, true);
1102		comp2gl.marginWidth = 0;
1103		comp2gl.marginHeight = 0;
1104		comp2.setLayout(comp2gl);
1105		{ mixin(S_TRACE);
1106			auto grp = new Group(comp2, SWT.NONE);
1107			auto gd = new GridData(GridData.FILL_HORIZONTAL);
1108			gd.widthHint = _prop.var.etc.searchResultTableWidth;
1109			grp.setLayoutData(gd);
1110			grp.setText(_prop.msgs.searchRange);
1111			grp.setLayout(zeroGridLayout(1, true));
1112			auto checked = new LCheck;
1113			_checked ~= checked;
1114			{ mixin(S_TRACE);
1115				auto btns = addButtonLine(grp);
1116				Button createB(string text, char accr) { mixin(S_TRACE);
1117					auto b = new Button(btns, SWT.CHECK);
1118					b.setText(text ~ "(&" ~ accr ~ ")");
1119					checked.buttons ~= b;
1120					b.addSelectionListener(checked);
1121					return b;
1122				}
1123				_cCoupon = createB(_prop.msgs.replTextCoupon, '1');
1124				_cGossip = createB(_prop.msgs.replTextGossip, '2');
1125				_cEnd = createB(_prop.msgs.replTextEndScenario, '3');
1126				_cKeyCode = createB(_prop.msgs.replTextKeyCode, '4');
1127				// FIXME: CardWirth 1.60 ????
1128/+				_cCellName = createB(_prop.msgs.replTextCellName, '5');
1129+/			}
1130			auto sep = new Label(grp, SWT.SEPARATOR | SWT.HORIZONTAL);
1131			sep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1132			{ mixin(S_TRACE);
1133				auto btns = addButtonLine(grp);
1134				checked.createAlls(btns, _prop.msgs.allCheck);
1135			}
1136		}
1137
1138		auto tab = new CTabItem(tabf, SWT.NONE);
1139		tab.setText(_prop.msgs.replForCoupon);
1140		tab.setControl(comp);
1141		_tabCoupon = tab;
1142
1143		auto gd = new GridData(GridData.FILL_BOTH);
1144		comp2.setLayoutData(gd);
1145		_comps[tab] = comp2;
1146	}
1147	void constructUnuse(CTabFolder tabf) { mixin(S_TRACE);
1148		auto comp = new Composite(tabf, SWT.NONE);
1149		comp.setLayout(new GridLayout(1, true));
1150		auto comp2 = new Composite(comp, SWT.NONE);
1151		comp2.setLayout(zeroGridLayout(1, true));
1152		{ mixin(S_TRACE);
1153			auto grp = new Group(comp2, SWT.NONE);
1154			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1155			grp.setText(_prop.msgs.replUnuseTarget);
1156			grp.setLayout(zeroGridLayout(1, true));
1157			auto checked = new LCheck;
1158			_checked ~= checked;
1159			{ mixin(S_TRACE);
1160				auto btns = addButtonLine(grp);
1161				Button createB(string text, char accr) { mixin(S_TRACE);
1162					auto b = new Button(btns, SWT.CHECK);
1163					b.setText(text ~ "(&" ~ accr ~ ")");
1164					checked.buttons ~= b;
1165					b.addSelectionListener(checked);
1166					return b;
1167				}
1168				_unuseFlag = createB(_prop.msgs.replUnuseFlag, '1');
1169				_unuseStep = createB(_prop.msgs.replUnuseStep, '2');
1170				_unuseArea = createB(_prop.msgs.replUnuseArea, '3');
1171				_unuseBattle = createB(_prop.msgs.replUnuseBattle, '4');
1172				_unusePackage = createB(_prop.msgs.replUnusePackage, '5');
1173				_unuseCast = createB(_prop.msgs.replUnuseCast, '6');
1174				_unuseSkill = createB(_prop.msgs.replUnuseSkill, '7');
1175				_unuseItem = createB(_prop.msgs.replUnuseItem, '8');
1176				_unuseBeast = createB(_prop.msgs.replUnuseBeast, '9');
1177				_unuseInfo = createB(_prop.msgs.replUnuseInfo, 'A');
1178				_unuseStart = createB(_prop.msgs.replUnuseStart, 'B');
1179				_unusePath = createB(_prop.msgs.replUnusePath, 'C');
1180			}
1181			auto sep = new Label(grp, SWT.SEPARATOR | SWT.HORIZONTAL);
1182			sep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1183			{ mixin(S_TRACE);
1184				auto btns = addButtonLine(grp);
1185				checked.createAlls(btns, _prop.msgs.allCheck);
1186			}
1187		}
1188
1189		auto tab = new CTabItem(tabf, SWT.NONE);
1190		tab.setText(_prop.msgs.replForUnuse);
1191		tab.setControl(comp);
1192		_tabUnuse = tab;
1193
1194		auto gd = new GridData(GridData.FILL_BOTH);
1195		gd.heightHint = 0;
1196		comp2.setLayoutData(gd);
1197		_comps[tab] = comp2;
1198	}
1199	void constructError(CTabFolder tabf) { mixin(S_TRACE);
1200		auto comp = new Composite(tabf, SWT.NONE);
1201		comp.setLayout(new GridLayout(1, true));
1202		auto comp2 = new Composite(comp, SWT.NONE);
1203		comp2.setLayout(zeroGridLayout(1, true));
1204		{ mixin(S_TRACE);
1205			auto l = new Label(comp2, SWT.WRAP);
1206			l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1207			l.setText(_prop.msgs.replError);
1208		}
1209
1210		auto tab = new CTabItem(tabf, SWT.NONE);
1211		tab.setText(_prop.msgs.replForError);
1212		tab.setControl(comp);
1213		_tabError = tab;
1214
1215		auto gd = new GridData(GridData.FILL_BOTH);
1216		gd.heightHint = 0;
1217		comp2.setLayoutData(gd);
1218		_comps[tab] = comp2;
1219	}
1220	void constructGrep(CTabFolder tabf) { mixin(S_TRACE);
1221		auto comp = new Composite(tabf, SWT.NONE);
1222		comp.setLayout(new GridLayout(1, true));
1223		auto comp2 = new Composite(comp, SWT.NONE);
1224		auto comp2gl = windowGridLayout(1, true);
1225		comp2gl.marginWidth = 0;
1226		comp2gl.marginHeight = 0;
1227		comp2.setLayout(comp2gl);
1228
1229		{ mixin(S_TRACE);
1230			auto grp = new Group(comp2, SWT.NONE);
1231			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1232			grp.setText(_prop.msgs.grepText);
1233			grp.setLayout(new GridLayout(2, false));
1234			auto fl = new Label(grp, SWT.NONE);
1235			fl.setText(_prop.msgs.grepFrom);
1236			_grepFromComp = new Composite(grp, SWT.NONE);
1237			_grepFromComp.setLayout(new FillLayout);
1238			auto gd = new GridData(GridData.FILL_HORIZONTAL);
1239			gd.widthHint = _prop.var.etc.nameWidth;
1240			_grepFromComp.setLayoutData(gd);
1241		}
1242		{ mixin(S_TRACE);
1243			auto grp = new Group(comp2, SWT.NONE);
1244			grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1245			grp.setText(_prop.msgs.grepTarget);
1246			grp.setLayout(new GridLayout(4, false));
1247
1248			_grepDir = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN);
1249			_grepDir.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
1250			createTextMenu!Combo(_comm, _prop, _grepDir, &catchMod);
1251			_grepDir.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1252			auto grepDirRef = new Button(grp, SWT.PUSH);
1253			grepDirRef.setText(_prop.msgs.reference);
1254			.listener(grepDirRef, SWT.Selection, { mixin(S_TRACE);
1255				selectDir(_prop, _grepDir, _prop.msgs.grepDir, _prop.msgs.grepDirDesc, _grepDir.getText());
1256			});
1257			createOpenButton(_comm, grp, {return _prop.toAppAbs(_grepDir.getText());}, true);
1258
1259			auto grepCurrent = new Button(grp, SWT.PUSH);
1260			grepCurrent.setText(_prop.msgs.grepCurrent);
1261			.listener(grepCurrent, SWT.Selection, &setGrepCurrentDir);
1262			_grepSubDir = new Button(grp, SWT.CHECK);
1263			auto gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
1264			gd.horizontalSpan = 4;
1265			_grepSubDir.setLayoutData(gd);
1266			_grepSubDir.setText(_prop.msgs.grepSubDir);
1267			.listener(_grepDir, SWT.Modify, { mixin(S_TRACE);
1268				if (ignoreMod) return;
1269				_prop.var.etc.grepDir = _grepDir.getText();
1270			});
1271			.listener(_grepSubDir, SWT.Selection, { mixin(S_TRACE);
1272				if (ignoreMod) return;
1273				_prop.var.etc.grepSubDir = _grepSubDir.getSelection();
1274			});
1275		}
1276
1277		auto tab = new CTabItem(tabf, SWT.NONE);
1278		tab.setText(_prop.msgs.replGrep);
1279		tab.setControl(comp);
1280		_tabGrep = tab;
1281
1282		auto gd = new GridData(GridData.FILL_BOTH);
1283		comp2.setLayoutData(gd);
1284		_comps[tab] = comp2;
1285	}
1286	void setGrepCurrentDir() { mixin(S_TRACE);
1287		if (_summ) { mixin(S_TRACE);
1288			auto sc = _summ.scenarioPath.dirName();
1289			if (_summ.useTemp) sc = _summ.zipName.dirName();
1290			_grepDir.setText(sc);
1291		}
1292	}
1293
1294	void refFunc(bool Del, A : CWXPath)(A a) { mixin(S_TRACE);
1295		bool recurse(TreeItem itm) { mixin(S_TRACE);
1296			if (a is itm.getData()) { mixin(S_TRACE);
1297				static if (Del) {
1298					itm.dispose();
1299				} else { mixin(S_TRACE);
1300					itm.setText(a.name);
1301				}
1302				return true;
1303			} else { mixin(S_TRACE);
1304				foreach (child; itm.getItems()) { mixin(S_TRACE);
1305					if (recurse(child)) { mixin(S_TRACE);
1306						return true;
1307					}
1308				}
1309				return false;
1310			}
1311		}
1312		foreach (child; _range.getItems()) { mixin(S_TRACE);
1313			if (recurse(child)) { mixin(S_TRACE);
1314				return;
1315			}
1316		}
1317		static if (!Del) {
1318			// ??
1319			refreshRangeTree();
1320		}
1321	}
1322	void delArea(Area a) { mixin(S_TRACE);
1323		refFunc!true(a);
1324	}
1325	void delBattle(Battle a) { mixin(S_TRACE);
1326		refFunc!true(a);
1327	}
1328	void delPackage(Package a) { mixin(S_TRACE);
1329		refFunc!true(a);
1330	}
1331	void delCast(CastCard a) { mixin(S_TRACE);
1332		refFunc!true(a);
1333	}
1334	void delSkill(SkillCard a) { mixin(S_TRACE);
1335		refFunc!true(a);
1336	}
1337	void delItem(ItemCard a) { mixin(S_TRACE);
1338		refFunc!true(a);
1339	}
1340	void delBeast(BeastCard a) { mixin(S_TRACE);
1341		refFunc!true(a);
1342	}
1343	void delInfo(InfoCard a) { mixin(S_TRACE);
1344		refFunc!true(a);
1345	}
1346	void refArea(Area a) { mixin(S_TRACE);
1347		if (_prop.var.etc.showAreaDirTree) {
1348			refreshRangeTree();
1349		} else {
1350			refFunc!false(a);
1351		}
1352	}
1353	void refBattle(Battle a) { mixin(S_TRACE);
1354		if (_prop.var.etc.showAreaDirTree) {
1355			refreshRangeTree();
1356		} else {
1357			refFunc!false(a);
1358		}
1359	}
1360	void refPackage(Package a) { mixin(S_TRACE);
1361		if (_prop.var.etc.showAreaDirTree) {
1362			refreshRangeTree();
1363		} else {
1364			refFunc!false(a);
1365		}
1366	}
1367	void refCast(CastCard a) { mixin(S_TRACE);
1368		refFunc!false(a);
1369	}
1370	void refSkill(SkillCard a) { mixin(S_TRACE);
1371		refFunc!false(a);
1372	}
1373	void refItem(ItemCard a) { mixin(S_TRACE);
1374		refFunc!false(a);
1375	}
1376	void refBeast(BeastCard a) { mixin(S_TRACE);
1377		refFunc!false(a);
1378	}
1379	void refInfo(InfoCard a) { mixin(S_TRACE);
1380		refFunc!false(a);
1381	}
1382	static CWXPath[] rangeTree(Summary summ) { mixin(S_TRACE);
1383		CWXPath[] r;
1384		r ~= summ;
1385		r ~= summ.flagDirRoot;
1386		foreach (a; summ.areas) r ~= a;
1387		foreach (a; summ.battles) r ~= a;
1388		foreach (a; summ.packages) r ~= a;
1389		foreach (a; summ.casts) { mixin(S_TRACE);
1390			r ~= a;
1391			foreach (c; a.skills) { mixin(S_TRACE);
1392				if (0 != c.linkId) continue;
1393				r ~= c;
1394			}
1395			foreach (c; a.items) { mixin(S_TRACE);
1396				if (0 != c.linkId) continue;
1397				r ~= c;
1398			}
1399			foreach (c; a.beasts) { mixin(S_TRACE);
1400				if (0 != c.linkId) continue;
1401				r ~= c;
1402			}
1403		}
1404		foreach (a; summ.skills) r ~= a;
1405		foreach (a; summ.items) r ~= a;
1406		foreach (a; summ.beasts) r ~= a;
1407		foreach (a; summ.infos) r ~= a;
1408		return r;
1409	}
1410	void refreshRangeTree() { mixin(S_TRACE);
1411		_range.setRedraw(false);
1412		scope (exit) _range.setRedraw(true);
1413		if (!_summ) { mixin(S_TRACE);
1414			_range.removeAll();
1415			return;
1416		}
1417		CWXPath sel = null;
1418		auto selItm = _range.getSelection();
1419		if (selItm.length) { mixin(S_TRACE);
1420			sel = cast(CWXPath)selItm[0].getData();
1421		}
1422		_range.removeAll();
1423		TreeItem add(TreeItem par, string name, CWXPath path) { mixin(S_TRACE);
1424			TreeItem itm;
1425			if (par) { mixin(S_TRACE);
1426				itm = new TreeItem(par, SWT.NONE);
1427			} else { mixin(S_TRACE);
1428				itm = new TreeItem(_range, SWT.NONE);
1429			}
1430			string text1, text2;
1431			Image img1, img2;
1432			getPathParams(path, text1, text2, img1, img2, false);
1433			itm.setText(name);
1434			itm.setImage(img1);
1435			itm.setData(cast(Object) path);
1436			itm.setChecked(true);
1437			if (sel is path) { mixin(S_TRACE);
1438				_range.setSelection([itm]);
1439			}
1440			return itm;
1441		}
1442		add(null, _prop.msgs.summary, _summ);
1443		add(null, _prop.msgs.flagsAndSteps, _summ.flagDirRoot);
1444		if (_prop.var.etc.showAreaDirTree) { mixin(S_TRACE);
1445			TreeItem[string] itmTable;
1446			auto dirSet = new HashSet!string;
1447			auto dirSet2 = new HashSet!string;
1448			void put1(string dirName) { mixin(S_TRACE);
1449				auto l = dirName.toLower();
1450				if (dirSet2.contains(l)) return;
1451				dirSet.add(dirName);
1452				dirSet2.add(l);
1453			}
1454			foreach (a; _summ.areas) put1(a.dirName);
1455			foreach (a; _summ.battles) put1(a.dirName);
1456			foreach (a; _summ.packages) put1(a.dirName);
1457			bool delegate(string, string) cmps;
1458			if (_prop.var.etc.logicalSort) {
1459				cmps = (a, b) => incmp(a, b) < 0;
1460			} else {
1461				cmps = (a, b) => icmp(a, b) < 0;
1462			}
1463			foreach (dirName; .sortDlg(dirSet.toArray(), cmps)) { mixin (S_TRACE);
1464				auto dirs = .split(dirName, "\\");
1465				TreeItem itm = null;
1466				foreach (i, dir; dirs) { mixin (S_TRACE);
1467					auto fPath = dirs[0 .. i + 1].join("\\");
1468					auto path = fPath.toLower();
1469					auto p = path in itmTable;
1470					if (p) { mixin (S_TRACE);
1471						itm = *p;
1472					} else { mixin (S_TRACE);
1473						TreeItem sub;
1474						if (itm) { mixin (S_TRACE);
1475							sub = new TreeItem(itm, SWT.NONE);
1476						} else { mixin (S_TRACE);
1477							sub = new TreeItem(_range, SWT.NONE);
1478						}
1479						sub.setText(dir);
1480						sub.setImage(_prop.images.areaDir);
1481						sub.setChecked(true);
1482						itm = sub;
1483						itmTable[path] = sub;
1484					}
1485				}
1486				itmTable[dirName.toLower()] = itm;
1487			}
1488			void put(A)(A[] arr) { mixin (S_TRACE);
1489				foreach (a; arr) { mixin (S_TRACE);
1490					add(itmTable[a.dirName.toLower()], .tryFormat("%s.%s", a.id, a.baseName), a);
1491				}
1492			}
1493			put(_summ.areas);
1494			put(_summ.battles);
1495			put(_summ.packages);
1496		} else { mixin(S_TRACE);
1497			foreach (a; _summ.areas) add(null, a.name, a);
1498			foreach (a; _summ.battles) add(null, a.name, a);
1499			foreach (a; _summ.packages) add(null, a.name, a);
1500		}
1501		foreach (a; _summ.casts) { mixin(S_TRACE);
1502			auto par = add(null, .tryFormat("%s.%s", a.id, a.name), a);
1503			foreach (c; a.skills) { mixin(S_TRACE);
1504				if (0 != c.linkId) continue;
1505				add(par, .tryFormat("%s.%s", c.id, c.name), c);
1506			}
1507			foreach (c; a.items) { mixin(S_TRACE);
1508				if (0 != c.linkId) continue;
1509				add(par, .tryFormat("%s.%s", c.id, c.name), c);
1510			}
1511			foreach (c; a.beasts) { mixin(S_TRACE);
1512				if (0 != c.linkId) continue;
1513				add(par, .tryFormat("%s.%s", c.id, c.name), c);
1514			}
1515		}
1516		foreach (a; _summ.skills) { mixin(S_TRACE);
1517			add(null, .tryFormat("%s.%s", a.id, a.name), a);
1518		}
1519		foreach (a; _summ.items) { mixin(S_TRACE);
1520			add(null, .tryFormat("%s.%s", a.id, a.name), a);
1521		}
1522		foreach (a; _summ.beasts) { mixin(S_TRACE);
1523			add(null, .tryFormat("%s.%s", a.id, a.name), a);
1524		}
1525		foreach (a; _summ.infos) { mixin(S_TRACE);
1526			add(null, .tryFormat("%s.%s", a.id, a.name), a);
1527		}
1528		_range.treeExpandedAll();
1529		_range.showSelection();
1530		_comm.refreshToolBar();
1531	}
1532	void refreshRangeAllCheck() { mixin(S_TRACE);
1533		bool recurse(TreeItem itm) { mixin(S_TRACE);
1534			if (!itm.getChecked()) { mixin(S_TRACE);
1535				return true;
1536			} else { mixin(S_TRACE);
1537				foreach (child; itm.getItems()) { mixin(S_TRACE);
1538					if (recurse(child)) { mixin(S_TRACE);
1539						return true;
1540					}
1541				}
1542				return false;
1543			}
1544		}
1545		foreach (child; _range.getItems()) { mixin(S_TRACE);
1546			if (recurse(child)) { mixin(S_TRACE);
1547				_rangeAllCheck.setSelection(false);
1548				return;
1549			}
1550		}
1551		_rangeAllCheck.setSelection(true);
1552	}
1553	class RefRangeAllCheck : SelectionAdapter {
1554		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
1555			if (SWT.CHECK != e.detail) return;
1556			auto par = (cast(TreeItem)e.item);
1557			// ????????????????
1558			// ??????????????????
1559			if (par && !par.getData()) { mixin(S_TRACE);
1560				void recurse(TreeItem itm) { mixin(S_TRACE);
1561					itm.setChecked(par.getChecked());
1562					foreach (child; itm.getItems()) recurse(child);
1563				}
1564				foreach (itm; par.getItems()) { mixin(S_TRACE);
1565					recurse(itm);
1566				}
1567			}
1568			// ??????????????????
1569			// ?????????????????????????
1570			while (par && par.getParentItem() && !par.getParentItem().getData()) { mixin(S_TRACE);
1571				bool same = true;
1572				void recurse2(TreeItem itm) { mixin(S_TRACE);
1573					if (itm.getChecked() != par.getChecked()) { mixin(S_TRACE);
1574						same = false;
1575						return;
1576					}
1577					foreach (child; itm.getItems()) recurse2(child);
1578				}
1579				foreach (itm; par.getParentItem().getItems()) { mixin(S_TRACE);
1580					recurse2(itm);
1581				}
1582				if (!same) break;
1583				par.getParentItem().setChecked(par.getChecked());
1584				par = par.getParentItem();
1585			}
1586			refreshRangeAllCheck();
1587		}
1588	}
1589	class RangeAllCheck : SelectionAdapter {
1590		override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
1591			void recurse(TreeItem itm) { mixin(S_TRACE);
1592				itm.setChecked(_rangeAllCheck.getSelection());
1593				foreach (child; itm.getItems()) { mixin(S_TRACE);
1594					recurse(child);
1595				}
1596			}
1597			foreach (child; _range.getItems()) { mixin(S_TRACE);
1598				recurse(child);
1599			}
1600		}
1601	}
1602	void refUndoMax() { mixin(S_TRACE);
1603		_undo.max = _prop.var.etc.undoMaxReplace;
1604	}
1605public:
1606	this (Commons comm, Props prop, Shell shell, Summary summ) { mixin(S_TRACE);
1607		_uiThread = core.thread.Thread.getThis();
1608		_comm = comm;
1609		_prop = prop;
1610		_summ = summ;
1611		_undo = new UndoManager(_prop.var.etc.undoMaxReplace);
1612		_win = new Shell(shell, SWT.SHELL_TRIM);
1613		_win.setText(_prop.msgs.dlgTitReplaceText);
1614		_win.setImage(prop.images.menu(MenuID.Find));
1615
1616		_display = shell.getDisplay();
1617
1618		setup();
1619		_win.open();
1620		_win.setActive();
1621	}
1622	@property
1623	Shell widget() { mixin(S_TRACE);
1624		return _win;
1625	}
1626	@property
1627	void summary(Summary summ) { mixin(S_TRACE);
1628		if (_win.isDisposed()) return;
1629		if (!summ) { mixin(S_TRACE);
1630			_win.close();
1631		} else { mixin(S_TRACE);
1632			_summ = summ;
1633			reset();
1634			refreshRangeTree();
1635			setupIDs(true, true, true);
1636		}
1637		_undo.reset();
1638		_comm.refreshToolBar();
1639	}
1640
1641	void open() { mixin(S_TRACE);
1642		reset();
1643		tabChanged();
1644		auto tab = _tabf.getSelection();
1645		if (tab is _tabText) { mixin(S_TRACE);
1646			_from.setFocus();
1647		} else if (tab is _tabID) { mixin(S_TRACE);
1648			_idKind.setFocus();
1649		} else if (tab is _tabPath) { mixin(S_TRACE);
1650			_fromPath.setFocus();
1651		} else if (tab is _tabContents) { mixin(S_TRACE);
1652			// Nothing
1653		} else if (tab is _tabCoupon) { mixin(S_TRACE);
1654			// Nothing
1655		} else if (tab is _tabUnuse) { mixin(S_TRACE);
1656			// Nothing
1657		} else if (tab is _tabError) { mixin(S_TRACE);
1658			// Nothing
1659		} else if (tab is _tabGrep) { mixin(S_TRACE);
1660			_from.setFocus();
1661		} else assert (0);
1662	}
1663	void replaceText(string from, bool start = false) { mixin(S_TRACE);
1664		reset();
1665		_from.setText(from);
1666		_to.setText("");
1667		_tabf.setSelection(_tabText);
1668		tabChanged();
1669		_from.setFocus();
1670		if (start) { mixin(S_TRACE);
1671			search();
1672		}
1673	}
1674	void replacePath(string from, bool start = false) { mixin(S_TRACE);
1675		reset();
1676		_fromPath.setText(from);
1677		_toPath.setText("");
1678		_tabf.setSelection(_tabPath);
1679		tabChanged();
1680		_fromPath.setFocus();
1681		if (start) { mixin(S_TRACE);
1682			search();
1683		}
1684	}
1685	void replaceID(ID)(ID from, bool start = false) { mixin(S_TRACE);
1686		reset();
1687		static if (is(ID:AreaId)) {
1688			_idKind.select(ID_AREA);
1689		} else static if (is(ID:BattleId)) {
1690			_idKind.select(ID_BATTLE);
1691		} else static if (is(ID:PackageId)) {
1692			_idKind.select(ID_PACKAGE);
1693		} else static if (is(ID:CastId)) {
1694			_idKind.select(ID_CAST);
1695		} else static if (is(ID:SkillId)) {
1696			_idKind.select(ID_SKILL);
1697		} else static if (is(ID:ItemId)) {
1698			_idKind.select(ID_ITEM);
1699		} else static if (is(ID:BeastId)) {
1700			_idKind.select(ID_BEAST);
1701		} else static if (is(ID:InfoId)) {
1702			_idKind.select(ID_INFO);
1703		} else static if (is(ID:FlagId)) {
1704			_idKind.select(ID_FLAG);
1705		} else static if (is(ID:StepId)) {
1706			_idKind.select(ID_STEP);
1707		} else static if (is(ID:CouponId)) {
1708			_idKind.select(ID_COUPON);
1709		} else static if (is(ID:GossipId)) {
1710			_idKind.select(ID_GOSSIP);
1711		} else static if (is(ID:CompleteStampId)) {
1712			_idKind.select(ID_COMPLETE_STAMP);
1713		} else static if (is(ID:KeyCodeId)) {
1714			_idKind.select(ID_KEY_CODE);
1715		} else static if (is(ID:CellNameId)) {
1716			// FIXME: CardWirth 1.60 ????
1717/+			_idKind.select(ID_CELL_NAME);
1718+/		} else static assert (0);
1719		selIDKind();
1720		static if (is(typeof(from.id):ulong)) {
1721			bool sel = false;
1722			foreach (index, id; _fromIDTbl) { mixin(S_TRACE);
1723				if (id == from.id) { mixin(S_TRACE);
1724					_fromID.select(index);
1725					sel = true;
1726					break;
1727				}
1728			}
1729			if (!sel) return;
1730		} else {
1731			_fromID.setText(cast(string)from);
1732		}
1733		_tabf.setSelection(_tabID);
1734		tabChanged();
1735		_fromID.setFocus();
1736		if (start) { mixin(S_TRACE);
1737			search();
1738		}
1739	}
1740
1741	private void openRangePath() { mixin(S_TRACE);
1742		auto sels = _range.getSelection();
1743		if (!sels.length) return;
1744		auto data = cast(CWXPath)sels[0].getData();
1745		if (!data) return;
1746		string path = data.cwxPath(true);
1747		path = cpaddattr(path, "shallow");
1748		auto r = _comm.openCWXPath(path, false);
1749		if (!r) { mixin(S_TRACE);
1750			MessageBox.showWarning(.tryFormat(_prop.msgs.cwxPathOpenError, path), _prop.msgs.dlgTitWarning, _win);
1751		}
1752	}
1753	private class OpenPath : MouseAdapter, KeyListener {
1754		override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
1755			if (1 == e.button) { mixin(S_TRACE);
1756				openRangePath();
1757			}
1758		}
1759		override void keyReleased(KeyEvent e) {}
1760		override void keyPressed(KeyEvent e) { mixin(S_TRACE);
1761			if (SWT.CR == e.character) openRangePath();
1762		}
1763	}
1764	private void setup() { mixin(S_TRACE);
1765		_win.addShellListener(new SListener);
1766		_win.setLayout(zeroGridLayout(1, true));
1767		auto area = new Composite(_win, SWT.NONE);
1768		area.setLayoutData(new GridData(GridData.FILL_BOTH));
1769		area.setLayout(windowGridLayout(2, false));
1770
1771		auto sash = new SplitPane(area, SWT.HORIZONTAL);
1772		sash.setLayoutData(new GridData(GridData.FILL_BOTH));
1773
1774		auto left = new Composite(sash, SWT.NONE);
1775		left.setLayout(windowGridLayout(1, true));
1776		_parent = left;
1777		auto right = new Composite(sash, SWT.NONE);
1778		right.setLayout(windowGridLayout(1, true));
1779
1780		_tabf = new CTabFolder(left, SWT.BORDER);
1781		{ mixin(S_TRACE);
1782			_tabf.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1783			constructText(_tabf);
1784			constructID(_tabf);
1785			constructPath(_tabf);
1786			constructContents(_tabf);
1787			constructCoupon(_tabf);
1788			constructUnuse(_tabf);
1789			constructError(_tabf);
1790			constructGrep(_tabf);
1791			_tabf.addSelectionListener(new TSListener);
1792		}
1793		{ mixin(S_TRACE);
1794			_result = new Table(left, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.VIRTUAL);
1795			auto gd = new GridData(GridData.FILL_BOTH);
1796			gd.widthHint = _prop.var.etc.searchResultTableWidth;
1797			gd.heightHint = _prop.var.etc.searchResultTableHeight;
1798			_result.setLayoutData(gd);
1799			_result.addMouseListener(new ML);
1800			_result.addKeyListener(new KL);
1801			auto menu = new Menu(_win, SWT.POP_UP);
1802			createMenuItem(_comm, menu, MenuID.Undo, &undo, &_undo.canUndo);
1803			createMenuItem(_comm, menu, MenuID.Redo, &redo, &_undo.canRedo);
1804			new MenuItem(menu, SWT.SEPARATOR);
1805			createMenuItem(_comm, menu, MenuID.CopyAsText, &copyResult, () => _result.getSelectionIndex() != -1);
1806			new MenuItem(menu, SWT.SEPARATOR);
1807			createMenuItem(_comm, menu, MenuID.SelectAll, &_result.selectAll, () => _result.getItemCount() > 0);
1808			new MenuItem(menu, SWT.SEPARATOR);
1809			createMenuItem(_comm, menu, MenuID.OpenAtView, &openPath, &canOpenPath);
1810			_result.setMenu(menu);
1811			_edit = new TableTextEdit(_comm, _prop, _result, 0, &couponEditEnd, &canCouponEdit);
1812		}
1813		{ mixin(S_TRACE);
1814			auto comp = new Composite(left, SWT.NONE);
1815			comp.setLayout(zeroMarginGridLayout(2, false));
1816			comp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
1817			auto realtime = new Button(comp, SWT.CHECK);
1818			realtime.setText(_prop.msgs.searchResultRealtime);
1819			realtime.setSelection(_prop.var.etc.searchResultRealtime);
1820			.listener(realtime, SWT.Selection, { mixin(S_TRACE);
1821				_prop.var.etc.searchResultRealtime = realtime.getSelection();
1822				if (_prop.var.etc.searchResultRealtime) { mixin(S_TRACE);
1823					resultRedraw(true);
1824				} else if (_inProc) { mixin(S_TRACE);
1825					resultRedraw(false);
1826				}
1827			});
1828			auto openDlg = new Button(comp, SWT.CHECK);
1829			openDlg.setText(_prop.msgs.searchOpenDialog);
1830			openDlg.setSelection(_prop.var.etc.searchOpenDialog);
1831			openDlg.addSelectionListener(new class SelectionAdapter {
1832				override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
1833					_prop.var.etc.searchOpenDialog = openDlg.getSelection();
1834				}
1835			});
1836		}
1837		{ mixin(S_TRACE);
1838			auto grp = new Group(right, SWT.NONE);
1839			grp.setText(_prop.msgs.searchRange);
1840			grp.setLayoutData(new GridData(GridData.FILL_BOTH));
1841			grp.setLayout(new GridLayout(1, true));
1842			_range = new Tree(grp, SWT.SINGLE | SWT.BORDER | SWT.VIRTUAL | SWT.CHECK);
1843			initTree(_comm, _range, false);
1844			_range.addSelectionListener(new RefRangeAllCheck);
1845			_range.setLayoutData(new GridData(GridData.FILL_BOTH));
1846			refreshRangeTree();
1847			_rangeAllCheck = new Button(grp, SWT.CHECK);
1848			_rangeAllCheck.setText(_prop.msgs.allCheckRange);
1849			refreshRangeAllCheck();
1850			_rangeAllCheck.addSelectionListener(new RangeAllCheck);
1851			auto openPath = new OpenPath;
1852			_range.addKeyListener(openPath);
1853			_range.addMouseListener(openPath);
1854			auto menu = new Menu(_win, SWT.POP_UP);
1855			createMenuItem(_comm, menu, MenuID.OpenAtView, &openRangePath, () => _range.getSelection().length > 0 && cast(CWXPath)_range.getSelection()[0].getData());
1856			_range.setMenu(menu);
1857		}
1858		{ mixin(S_TRACE);
1859			auto sep = new Label(_win, SWT.SEPARATOR | SWT.HORIZONTAL);
1860			sep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1861		}
1862		{ mixin(S_TRACE);
1863			auto bArea = new Composite(_win, SWT.NONE);
1864			bArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1865			bArea.setLayout(new GridLayout(2, false));
1866			_status = new Label(bArea, SWT.NONE);
1867			_status.setText(_prop.msgs.searchResultEmpty);
1868			_status.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1869			auto comp = new Composite(bArea, SWT.NONE);
1870			comp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
1871			auto gl = new GridLayout(4, true);
1872			gl.marginWidth = 0;
1873			gl.marginHeight = 0;
1874			comp.setLayout(gl);
1875			Button createButton(string text, void delegate() push) { mixin(S_TRACE);
1876				auto b = new Button(comp, SWT.PUSH);
1877				b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1878				b.setText(text);
1879				auto sa = new class SelectionAdapter {
1880					private void delegate() push;
1881					override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
1882						push();
1883					}
1884				};
1885				sa.push = push;
1886				b.addSelectionListener(sa);
1887				return b;
1888			}
1889			_find = createButton(_prop.msgs.search, &search);
1890			_comm.put(_find, &canFind);
1891			_replace = createButton(_prop.msgs.replace, &replace);
1892			_comm.put(_replace, &canReplace);
1893			_close = createButton(_prop.msgs.dlgTextClose, &exit);
1894			auto cancel = createButton(_prop.msgs.searchCancel, { mixin(S_TRACE);
1895				_cancel = true;
1896				resultRedraw(true);
1897			});
1898			_comm.put(cancel, &canCancel);
1899		}
1900		auto d = _tabf.getDisplay();
1901		auto keyFilter = new class Listener {
1902			override void handleEvent(Event e) { mixin(S_TRACE);
1903				auto fc = d.getFocusControl();
1904				if (!fc || !_tabf.isDescendant(fc)) return;
1905				if (e.character == SWT.CR) { mixin(S_TRACE);
1906					search();
1907				}
1908			}
1909		};
1910		d.addFilter(SWT.KeyDown, keyFilter);
1911		.listener(_tabf, SWT.Dispose, { mixin(S_TRACE);
1912			d.removeFilter(SWT.KeyDown, keyFilter);
1913		});
1914
1915		ignoreMod = true;
1916		scope (exit) ignoreMod = false;
1917		setComboItems(_from, _prop.var.etc.searchHistories.dup);
1918		setComboItems(_to, _prop.var.etc.replaceHistories.dup);
1919		setComboItems(_grepDir, _prop.var.etc.grepDirHistories.dup);
1920		_notIgnoreCase.setSelection(_prop.var.etc.replaceTextNotIgnoreCase);
1921		_exact.setSelection(_prop.var.etc.replaceTextExactMatch);
1922		_ignoreReturnCode.setSelection(_prop.var.etc.replaceTextIgnoreReturnCode);
1923		_useRegex.setSelection(_prop.var.etc.replaceTextRegExp);
1924		_useWildcard.setSelection(_prop.var.etc.replaceTextWildcard);
1925		_summary.setSelection(_prop.var.etc.replaceTextSummary);
1926		_msg.setSelection(_prop.var.etc.replaceTextMessage);
1927		_cardName.setSelection(_prop.var.etc.replaceTextCardName);
1928		_cardDesc.setSelection(_prop.var.etc.replaceTextCardDescription);
1929		_event.setSelection(_prop.var.etc.replaceTextEventText);
1930		_flag.setSelection(_prop.var.etc.replaceTextFlagAndStep);
1931		_start.setSelection(_prop.var.etc.replaceTextStart);
1932		_coupon.setSelection(_prop.var.etc.replaceTextCoupon);
1933		_gossip.setSelection(_prop.var.etc.replaceTextGossip);
1934		_end.setSelection(_prop.var.etc.replaceTextEndScenario);
1935		_area.setSelection(_prop.var.etc.replaceTextAreaName);
1936		_keyCode.setSelection(_prop.var.etc.replaceTextKeyCode);
1937		_file.setSelection(_prop.var.etc.replaceTextFile);
1938		_comment.setSelection(_prop.var.etc.replaceTextComment);
1939		_jptx.setSelection(_prop.var.etc.replaceTextJptx);
1940		if (_prop.var.etc.grepDir.length) { mixin(S_TRACE);
1941			_grepDir.setText(_prop.var.etc.grepDir);
1942		} else { mixin(S_TRACE);
1943			setGrepCurrentDir();
1944		}
1945		_grepSubDir.setSelection(_prop.var.etc.grepSubDir);
1946
1947		_contents[CType.START].setSelection(_prop.var.etc.searchContentsStart);
1948		_contents[CType.START_BATTLE].setSelection(_prop.var.etc.searchContentsStartBattle);
1949		_contents[CType.END].setSelection(_prop.var.etc.searchContentsEnd);
1950		_contents[CType.END_BAD_END].setSelection(_prop.var.etc.searchContentsEndBadEnd);
1951		_contents[CType.CHANGE_AREA].setSelection(_prop.var.etc.searchContentsChangeArea);
1952		_contents[CType.CHANGE_BG_IMAGE].setSelection(_prop.var.etc.searchContentsChangeBgImage);
1953		_contents[CType.EFFECT].setSelection(_prop.var.etc.searchContentsEffect);
1954		_contents[CType.EFFECT_BREAK].setSelection(_prop.var.etc.searchContentsEffectBreak);
1955		_contents[CType.LINK_START].setSelection(_prop.var.etc.searchContentsLinkStart);
1956		_contents[CType.LINK_PACKAGE].setSelection(_prop.var.etc.searchContentsLinkPackage);
1957		_contents[CType.TALK_MESSAGE].setSelection(_prop.var.etc.searchContentsTalkMessage);
1958		_contents[CType.TALK_DIALOG].setSelection(_prop.var.etc.searchContentsTalkDialog);
1959		_contents[CType.PLAY_BGM].setSelection(_prop.var.etc.searchContentsPlayBgm);
1960		_contents[CType.PLAY_SOUND].setSelection(_prop.var.etc.searchContentsPlaySound);
1961		_contents[CType.WAIT].setSelection(_prop.var.etc.searchContentsWait);
1962		_contents[CType.ELAPSE_TIME].setSelection(_prop.var.etc.searchContentsElapseTime);
1963		_contents[CType.CALL_START].setSelection(_prop.var.etc.searchContentsCallStart);
1964		_contents[CType.CALL_PACKAGE].setSelection(_prop.var.etc.searchContentsCallPackage);
1965		_contents[CType.BRANCH_FLAG].setSelection(_prop.var.etc.searchContentsBranchFlag);
1966		_contents[CType.BRANCH_MULTI_STEP].setSelection(_prop.var.etc.searchContentsBranchMultiStep);
1967		_contents[CType.BRANCH_STEP].setSelection(_prop.var.etc.searchContentsBranchStep);
1968		_contents[CType.BRANCH_SELECT].setSelection(_prop.var.etc.searchContentsBranchSelect);
1969		_contents[CType.BRANCH_ABILITY].setSelection(_prop.var.etc.searchContentsBranchAbility);
1970		_contents[CType.BRANCH_RANDOM].setSelection(_prop.var.etc.searchContentsBranchRandom);
1971		_contents[CType.BRANCH_LEVEL].setSelection(_prop.var.etc.searchContentsBranchLevel);
1972		_contents[CType.BRANCH_STATUS].setSelection(_prop.var.etc.searchContentsBranchStatus);
1973		_contents[CType.BRANCH_PARTY_NUMBER].setSelection(_prop.var.etc.searchContentsBranchPartyNumber);
1974		_contents[CType.BRANCH_AREA].setSelection(_prop.var.etc.searchContentsBranchArea);
1975		_contents[CType.BRANCH_BATTLE].setSelection(_prop.var.etc.searchContentsBranchBattle);
1976		_contents[CType.BRANCH_IS_BATTLE].setSelection(_prop.var.etc.searchContentsBranchIsBattle);
1977		_contents[CType.BRANCH_CAST].setSelection(_prop.var.etc.searchContentsBranchCast);
1978		_contents[CType.BRANCH_ITEM].setSelection(_prop.var.etc.searchContentsBranchItem);
1979		_contents[CType.BRANCH_SKILL].setSelection(_prop.var.etc.searchContentsBranchSkill);
1980		_contents[CType.BRANCH_INFO].setSelection(_prop.var.etc.searchContentsBranchInfo);
1981		_contents[CType.BRANCH_BEAST].setSelection(_prop.var.etc.searchContentsBranchBeast);
1982		_contents[CType.BRANCH_MONEY].setSelection(_prop.var.etc.searchContentsBranchMoney);
1983		_contents[CType.BRANCH_COUPON].setSelection(_prop.var.etc.searchContentsBranchCoupon);
1984		_contents[CType.BRANCH_COMPLETE_STAMP].setSelection(_prop.var.etc.searchContentsBranchCompleteStamp);
1985		_contents[CType.BRANCH_GOSSIP].setSelection(_prop.var.etc.searchContentsBranchGossip);
1986		_contents[CType.SET_FLAG].setSelection(_prop.var.etc.searchContentsSetFlag);
1987		_contents[CType.SET_STEP].setSelection(_prop.var.etc.searchContentsSetStep);
1988		_contents[CType.SET_STEP_UP].setSelection(_prop.var.etc.searchContentsSetStepUp);
1989		_contents[CType.SET_STEP_DOWN].setSelection(_prop.var.etc.searchContentsSetStepDown);
1990		_contents[CType.REVERSE_FLAG].setSelection(_prop.var.etc.searchContentsReverseFlag);
1991		_contents[CType.CHECK_FLAG].setSelection(_prop.var.etc.searchContentsCheckFlag);
1992		_contents[CType.GET_CAST].setSelection(_prop.var.etc.searchContentsGetCast);
1993		_contents[CType.GET_ITEM].setSelection(_prop.var.etc.searchContentsGetItem);
1994		_contents[CType.GET_SKILL].setSelection(_prop.var.etc.searchContentsGetSkill);
1995		_contents[CType.GET_INFO].setSelection(_prop.var.etc.searchContentsGetInfo);
1996		_contents[CType.GET_BEAST].setSelection(_prop.var.etc.searchContentsGetBeast);
1997		_contents[CType.GET_MONEY].setSelection(_prop.var.etc.searchContentsGetMoney);
1998		_contents[CType.GET_COUPON].setSelection(_prop.var.etc.searchContentsGetCoupon);
1999		_contents[CType.GET_COMPLETE_STAMP].setSelection(_prop.var.etc.searchContentsGetCompleteStamp);
2000		_contents[CType.GET_GOSSIP].setSelection(_prop.var.etc.searchContentsGetGossip);
2001		_contents[CType.LOSE_CAST].setSelection(_prop.var.etc.searchContentsLoseCast);
2002		_contents[CType.LOSE_ITEM].setSelection(_prop.var.etc.searchContentsLoseItem);
2003		_contents[CType.LOSE_SKILL].setSelection(_prop.var.etc.searchContentsLoseSkill);
2004		_contents[CType.LOSE_INFO].setSelection(_prop.var.etc.searchContentsLoseInfo);
2005		_contents[CType.LOSE_BEAST].setSelection(_prop.var.etc.searchContentsLoseBeast);
2006		_contents[CType.LOSE_MONEY].setSelection(_prop.var.etc.searchContentsLoseMoney);
2007		_contents[CType.LOSE_COUPON].setSelection(_prop.var.etc.searchContentsLoseCoupon);
2008		_contents[CType.LOSE_COMPLETE_STAMP].setSelection(_prop.var.etc.searchContentsLoseCompleteStamp);
2009		_contents[CType.LOSE_GOSSIP].setSelection(_prop.var.etc.searchContentsLoseGossip);
2010		_contents[CType.SHOW_PARTY].setSelection(_prop.var.etc.searchContentsShowParty);
2011		_contents[CType.HIDE_PARTY].setSelection(_prop.var.etc.searchContentsHideParty);
2012		_contents[CType.REDISPLAY].setSelection(_prop.var.etc.searchContentsRedisplay);
2013		_contents[CType.SUBSTITUTE_STEP].setSelection(_prop.var.etc.searchContentsSubstituteStep);
2014		_contents[CType.SUBSTITUTE_FLAG].setSelection(_prop.var.etc.searchContentsSubstituteFlag);
2015		_contents[CType.BRANCH_STEP_CMP].setSelection(_prop.var.etc.searchContentsBranchStepCmp);
2016		_contents[CType.BRANCH_FLAG_CMP].setSelection(_prop.var.etc.searchContentsBranchFlagCmp);
2017		_contents[CType.BRANCH_RANDOM_SELECT].setSelection(_prop.var.etc.searchContentsBranchRandomSelect);
2018		_contents[CType.BRANCH_KEY_CODE].setSelection(_prop.var.etc.searchContentsBranchKeyCode);
2019		_contents[CType.CHECK_STEP].setSelection(_prop.var.etc.searchContentsCheckStep);
2020		_contents[CType.BRANCH_ROUND].setSelection(_prop.var.etc.searchContentsBranchRound);
2021
2022		_cCoupon.setSelection(_prop.var.etc.replaceNameCoupon);
2023		_cGossip.setSelection(_prop.var.etc.replaceNameGossip);
2024		_cEnd.setSelection(_prop.var.etc.replaceNameEndScenario);
2025		_cKeyCode.setSelection(_prop.var.etc.replaceNameKeyCode);
2026		// FIXME: CardWirth 1.60 ????
2027/+		_cCellName.setSelection(_prop.var.etc.replaceNameCellName);
2028+/
2029		_unuseFlag.setSelection(_prop.var.etc.searchUnusedFlag);
2030		_unuseStep.setSelection(_prop.var.etc.searchUnusedStep);
2031		_unuseArea.setSelection(_prop.var.etc.searchUnusedArea);
2032		_unuseBattle.setSelection(_prop.var.etc.searchUnusedBattle);
2033		_unusePackage.setSelection(_prop.var.etc.searchUnusedPackage);
2034		_unuseCast.setSelection(_prop.var.etc.searchUnusedCast);
2035		_unuseSkill.setSelection(_prop.var.etc.searchUnusedSkill);
2036		_unuseItem.setSelection(_prop.var.etc.searchUnusedItem);
2037		_unuseBeast.setSelection(_prop.var.etc.searchUnusedBeast);
2038		_unuseInfo.setSelection(_prop.var.etc.searchUnusedInfo);
2039		_unuseStart.setSelection(_prop.var.etc.searchUnusedStart);
2040		_unusePath.setSelection(_prop.var.etc.searchUnusedPath);
2041		foreach (l; _checked) { mixin(S_TRACE);
2042			l.check();
2043		}
2044		_tabf.setSelection(0);
2045		if (0 <= _prop.var.etc.searchPlan && _prop.var.etc.searchPlan < _tabf.getItemCount()) { mixin(S_TRACE);
2046			_tabf.setSelection(_prop.var.etc.searchPlan);
2047		}
2048
2049		sash.addDisposeListener(new SashDispose);
2050		sash.setWeights([_prop.var.etc.replaceRangeSashL, _prop.var.etc.replaceRangeSashR]);
2051
2052		_comm.refTableViewStyle.add(&refreshRangeTree);
2053		_comm.refArea.add(&refArea);
2054		_comm.refBattle.add(&refBattle);
2055		_comm.refPackage.add(&refPackage);
2056		_comm.refCast.add(&refCast);
2057		_comm.refSkill.add(&refSkill);
2058		_comm.refItem.add(&refItem);
2059		_comm.refBeast.add(&refBeast);
2060		_comm.refInfo.add(&refInfo);
2061		_comm.delArea.add(&delArea);
2062		_comm.delBattle.add(&delBattle);
2063		_comm.delPackage.add(&delPackage);
2064		_comm.delCast.add(&delCast);
2065		_comm.delSkill.add(&delSkill);
2066		_comm.delItem.add(&delItem);
2067		_comm.delBeast.add(&delBeast);
2068		_comm.delInfo.add(&delInfo);
2069		_comm.refSearchHistories.add(&refSearchHistories);
2070		_comm.refContentText.add(&refContentText);
2071		_comm.refUndoMax.add(&refUndoMax);
2072
2073		_comm.changed.add(&changed);
2074		_comm.refScenario.add(&summary);
2075		_win.addDisposeListener(new DL);
2076		auto cs = _win.computeSize(SWT.DEFAULT, SWT.DEFAULT);
2077		auto size = _prop.var.replaceDlg;
2078		if (size.width != SWT.DEFAULT) cs.x = size.width;
2079		if (size.height != SWT.DEFAULT) cs.y = size.height;
2080		_win.setSize(cs);
2081
2082		auto winProps = _prop.var.replaceDlg;
2083		_win.setMaximized(winProps.maximized);
2084		scope wp = _win.computeSize(SWT.DEFAULT, SWT.DEFAULT);
2085		int width = winProps.width == SWT.DEFAULT ? wp.x : winProps.width;
2086		int height = winProps.height == SWT.DEFAULT ? wp.y : winProps.height;
2087		int x = winProps.x == SWT.DEFAULT ? _win.getBounds().x : winProps.x + _win.getParent().getBounds().x;
2088		int y = winProps.y == SWT.DEFAULT ? _win.getBounds().y : winProps.y + _win.getParent().getBounds().y;
2089		intoDisplay(x, y, width, height);
2090		_win.setBounds(x, y, width, height);
2091	}
2092	private void saveWin() { mixin(S_TRACE);
2093		auto winProps = _prop.var.replaceDlg;
2094		if (!_win.getMaximized()) { mixin(S_TRACE);
2095			winProps.width = _win.getSize().x;
2096			winProps.height = _win.getSize().y;
2097			winProps.x = _win.getBounds().x - _win.getParent().getBounds().x;
2098			winProps.y = _win.getBounds().y - _win.getParent().getBounds().y;
2099		}
2100		winProps.maximized = _win.getMaximized();
2101	}
2102	private class SashDispose : DisposeListener {
2103		override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
2104			auto sash = cast(SplitPane) e.widget;
2105			auto ws = sash.getWeights();
2106			_prop.var.etc.replaceRangeSashL = ws[0];
2107			_prop.var.etc.replaceRangeSashR = ws[1];
2108		}
2109	}
2110	private class DL : DisposeListener {
2111		override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
2112			_cancel = true;
2113			_comm.changed.remove(&changed);
2114			_comm.refScenario.remove(&summary);
2115			saveWin();
2116			_prop.var.etc.replaceTextNotIgnoreCase = _notIgnoreCase.getSelection();
2117			_prop.var.etc.replaceTextExactMatch = _exact.getSelection();
2118			_prop.var.etc.replaceTextIgnoreReturnCode = _ignoreReturnCode.getSelection();
2119			_prop.var.etc.replaceTextRegExp = _useRegex.getSelection();
2120			_prop.var.etc.replaceTextWildcard = _useWildcard.getSelection();
2121			_prop.var.etc.replaceTextSummary = _summary.getSelection();
2122			_prop.var.etc.replaceTextMessage = _msg.getSelection();
2123			_prop.var.etc.replaceTextCardName = _cardName.getSelection();
2124			_prop.var.etc.replaceTextCardDescription = _cardDesc.getSelection();
2125			_prop.var.etc.replaceTextEventText = _event.getSelection();
2126			_prop.var.etc.replaceTextStart = _start.getSelection();
2127			_prop.var.etc.replaceTextFlagAndStep = _flag.getSelection();
2128			_prop.var.etc.replaceTextCoupon = _coupon.getSelection();
2129			_prop.var.etc.replaceTextGossip = _gossip.getSelection();
2130			_prop.var.etc.replaceTextEndScenario = _end.getSelection();
2131			_prop.var.etc.replaceTextAreaName = _area.getSelection();
2132			_prop.var.etc.replaceTextKeyCode = _keyCode.getSelection();
2133			_prop.var.etc.replaceTextFile = _file.getSelection();
2134			_prop.var.etc.replaceTextComment = _comment.getSelection();
2135			_prop.var.etc.replaceTextJptx = _jptx.getSelection();
2136
2137			_prop.var.etc.searchContentsStart = _contents[CType.START].getSelection();
2138			_prop.var.etc.searchContentsStartBattle = _contents[CType.START_BATTLE].getSelection();
2139			_prop.var.etc.searchContentsEnd = _contents[CType.END].getSelection();
2140			_prop.var.etc.searchContentsEndBadEnd = _contents[CType.END_BAD_END].getSelection();
2141			_prop.var.etc.searchContentsChangeArea = _contents[CType.CHANGE_AREA].getSelection();
2142			_prop.var.etc.searchContentsChangeBgImage = _contents[CType.CHANGE_BG_IMAGE].getSelection();
2143			_prop.var.etc.searchContentsEffect = _contents[CType.EFFECT].getSelection();
2144			_prop.var.etc.searchContentsEffectBreak = _contents[CType.EFFECT_BREAK].getSelection();
2145			_prop.var.etc.searchContentsLinkStart = _contents[CType.LINK_START].getSelection();
2146			_prop.var.etc.searchContentsLinkPackage = _contents[CType.LINK_PACKAGE].getSelection();
2147			_prop.var.etc.searchContentsTalkMessage = _contents[CType.TALK_MESSAGE].getSelection();
2148			_prop.var.etc.searchContentsTalkDialog = _contents[CType.TALK_DIALOG].getSelection();
2149			_prop.var.etc.searchContentsPlayBgm = _contents[CType.PLAY_BGM].getSelection();
2150			_prop.var.etc.searchContentsPlaySound = _contents[CType.PLAY_SOUND].getSelection();
2151			_prop.var.etc.searchContentsWait = _contents[CType.WAIT].getSelection();
2152			_prop.var.etc.searchContentsElapseTime = _contents[CType.ELAPSE_TIME].getSelection();
2153			_prop.var.etc.searchContentsCallStart = _contents[CType.CALL_START].getSelection();
2154			_prop.var.etc.searchContentsCallPackage = _contents[CType.CALL_PACKAGE].getSelection();
2155			_prop.var.etc.searchContentsBranchFlag = _contents[CType.BRANCH_FLAG].getSelection();
2156			_prop.var.etc.searchContentsBranchMultiStep = _contents[CType.BRANCH_MULTI_STEP].getSelection();
2157			_prop.var.etc.searchContentsBranchStep = _contents[CType.BRANCH_STEP].getSelection();
2158			_prop.var.etc.searchContentsBranchSelect = _contents[CType.BRANCH_SELECT].getSelection();
2159			_prop.var.etc.searchContentsBranchAbility = _contents[CType.BRANCH_ABILITY].getSelection();
2160			_prop.var.etc.searchContentsBranchRandom = _contents[CType.BRANCH_RANDOM].getSelection();
2161			_prop.var.etc.searchContentsBranchLevel = _contents[CType.BRANCH_LEVEL].getSelection();
2162			_prop.var.etc.searchContentsBranchStatus = _contents[CType.BRANCH_STATUS].getSelection();
2163			_prop.var.etc.searchContentsBranchPartyNumber = _contents[CType.BRANCH_PARTY_NUMBER].getSelection();
2164			_prop.var.etc.searchContentsBranchArea = _contents[CType.BRANCH_AREA].getSelection();
2165			_prop.var.etc.searchContentsBranchBattle = _contents[CType.BRANCH_BATTLE].getSelection();
2166			_prop.var.etc.searchContentsBranchIsBattle = _contents[CType.BRANCH_IS_BATTLE].getSelection();
2167			_prop.var.etc.searchContentsBranchCast = _contents[CType.BRANCH_CAST].getSelection();
2168			_prop.var.etc.searchContentsBranchItem = _contents[CType.BRANCH_ITEM].getSelection();
2169			_prop.var.etc.searchContentsBranchSkill = _contents[CType.BRANCH_SKILL].getSelection();
2170			_prop.var.etc.searchContentsBranchInfo = _contents[CType.BRANCH_INFO].getSelection();
2171			_prop.var.etc.searchContentsBranchBeast = _contents[CType.BRANCH_BEAST].getSelection();
2172			_prop.var.etc.searchContentsBranchMoney = _contents[CType.BRANCH_MONEY].getSelection();
2173			_prop.var.etc.searchContentsBranchCoupon = _contents[CType.BRANCH_COUPON].getSelection();
2174			_prop.var.etc.searchContentsBranchCompleteStamp = _contents[CType.BRANCH_COMPLETE_STAMP].getSelection();
2175			_prop.var.etc.searchContentsBranchGossip = _contents[CType.BRANCH_GOSSIP].getSelection();
2176			_prop.var.etc.searchContentsSetFlag = _contents[CType.SET_FLAG].getSelection();
2177			_prop.var.etc.searchContentsSetStep = _contents[CType.SET_STEP].getSelection();
2178			_prop.var.etc.searchContentsSetStepUp = _contents[CType.SET_STEP_UP].getSelection();
2179			_prop.var.etc.searchContentsSetStepDown = _contents[CType.SET_STEP_DOWN].getSelection();
2180			_prop.var.etc.searchContentsReverseFlag = _contents[CType.REVERSE_FLAG].getSelection();
2181			_prop.var.etc.searchContentsCheckFlag = _contents[CType.CHECK_FLAG].getSelection();
2182			_prop.var.etc.searchContentsGetCast = _contents[CType.GET_CAST].getSelection();
2183			_prop.var.etc.searchContentsGetItem = _contents[CType.GET_ITEM].getSelection();
2184			_prop.var.etc.searchContentsGetSkill = _contents[CType.GET_SKILL].getSelection();
2185			_prop.var.etc.searchContentsGetInfo = _contents[CType.GET_INFO].getSelection();
2186			_prop.var.etc.searchContentsGetBeast = _contents[CType.GET_BEAST].getSelection();
2187			_prop.var.etc.searchContentsGetMoney = _contents[CType.GET_MONEY].getSelection();
2188			_prop.var.etc.searchContentsGetCoupon = _contents[CType.GET_COUPON].getSelection();
2189			_prop.var.etc.searchContentsGetCompleteStamp = _contents[CType.GET_COMPLETE_STAMP].getSelection();
2190			_prop.var.etc.searchContentsGetGossip = _contents[CType.GET_GOSSIP].getSelection();
2191			_prop.var.etc.searchContentsLoseCast = _contents[CType.LOSE_CAST].getSelection();
2192			_prop.var.etc.searchContentsLoseItem = _contents[CType.LOSE_ITEM].getSelection();
2193			_prop.var.etc.searchContentsLoseSkill = _contents[CType.LOSE_SKILL].getSelection();
2194			_prop.var.etc.searchContentsLoseInfo = _contents[CType.LOSE_INFO].getSelection();
2195			_prop.var.etc.searchContentsLoseBeast = _contents[CType.LOSE_BEAST].getSelection();
2196			_prop.var.etc.searchContentsLoseMoney = _contents[CType.LOSE_MONEY].getSelection();
2197			_prop.var.etc.searchContentsLoseCoupon = _contents[CType.LOSE_COUPON].getSelection();
2198			_prop.var.etc.searchContentsLoseCompleteStamp = _contents[CType.LOSE_COMPLETE_STAMP].getSelection();
2199			_prop.var.etc.searchContentsLoseGossip = _contents[CType.LOSE_GOSSIP].getSelection();
2200			_prop.var.etc.searchContentsShowParty = _contents[CType.SHOW_PARTY].getSelection();
2201			_prop.var.etc.searchContentsHideParty = _contents[CType.HIDE_PARTY].getSelection();
2202			_prop.var.etc.searchContentsRedisplay = _contents[CType.REDISPLAY].getSelection();
2203			_prop.var.etc.searchContentsSubstituteStep = _contents[CType.SUBSTITUTE_STEP].getSelection();
2204			_prop.var.etc.searchContentsSubstituteFlag = _contents[CType.SUBSTITUTE_FLAG].getSelection();
2205			_prop.var.etc.searchContentsBranchStepCmp = _contents[CType.BRANCH_STEP_CMP].getSelection();
2206			_prop.var.etc.searchContentsBranchFlagCmp = _contents[CType.BRANCH_FLAG_CMP].getSelection();
2207			_prop.var.etc.searchContentsBranchRandomSelect = _contents[CType.BRANCH_RANDOM_SELECT].getSelection();
2208			_prop.var.etc.searchContentsBranchKeyCode = _contents[CType.BRANCH_KEY_CODE].getSelection();
2209			_prop.var.etc.searchContentsCheckStep = _contents[CType.CHECK_STEP].getSelection();
2210			_prop.var.etc.searchContentsBranchRound = _contents[CType.BRANCH_ROUND].getSelection();
2211
2212			_prop.var.etc.replaceNameCoupon = _cCoupon.getSelection();
2213			_prop.var.etc.replaceNameGossip = _cGossip.getSelection();
2214			_prop.var.etc.replaceNameEndScenario = _cEnd.getSelection();
2215			_prop.var.etc.replaceNameKeyCode = _cKeyCode.getSelection();
2216			// FIXME: CardWirth 1.60 ????
2217/+			_prop.var.etc.replaceNameCellName = _cCellName.getSelection();
2218+/
2219			_prop.var.etc.searchUnusedFlag = _unuseFlag.getSelection();
2220			_prop.var.etc.searchUnusedStep = _unuseStep.getSelection();
2221			_prop.var.etc.searchUnusedArea = _unuseArea.getSelection();
2222			_prop.var.etc.searchUnusedBattle = _unuseBattle.getSelection();
2223			_prop.var.etc.searchUnusedPackage = _unusePackage.getSelection();
2224			_prop.var.etc.searchUnusedCast = _unuseCast.getSelection();
2225			_prop.var.etc.searchUnusedSkill = _unuseSkill.getSelection();
2226			_prop.var.etc.searchUnusedItem = _unuseItem.getSelection();
2227			_prop.var.etc.searchUnusedBeast = _unuseBeast.getSelection();
2228			_prop.var.etc.searchUnusedInfo = _unuseInfo.getSelection();
2229			_prop.var.etc.searchUnusedStart = _unuseStart.getSelection();
2230			_prop.var.etc.searchUnusedPath = _unusePath.getSelection();
2231
2232			_comm.refTableViewStyle.remove(&refreshRangeTree);
2233			_comm.refArea.remove(&refArea);
2234			_comm.refBattle.remove(&refBattle);
2235			_comm.refPackage.remove(&refPackage);
2236			_comm.refCast.remove(&refCast);
2237			_comm.refSkill.remove(&refSkill);
2238			_comm.refItem.remove(&refItem);
2239			_comm.refBeast.remove(&refBeast);
2240			_comm.refInfo.remove(&refInfo);
2241			_comm.delArea.remove(&delArea);
2242			_comm.delBattle.remove(&delBattle);
2243			_comm.delPackage.remove(&delPackage);
2244			_comm.delCast.remove(&delCast);
2245			_comm.delSkill.remove(&delSkill);
2246			_comm.delItem.remove(&delItem);
2247			_comm.delBeast.remove(&delBeast);
2248			_comm.delInfo.remove(&delInfo);
2249			_comm.refSearchHistories.remove(&refSearchHistories);
2250			_comm.refContentText.remove(&refContentText);
2251			_comm.refUndoMax.remove(&refUndoMax);
2252		}
2253	}
2254	private void changed() { mixin(S_TRACE);
2255		if (!_inUndo && !_inProc) { mixin(S_TRACE);
2256			_undo.reset();
2257		}
2258		auto thr = core.thread.Thread.getThis();
2259		if (&_uiThread !is &thr) return;
2260		if (_inGrep) return;
2261		if (_inUndo) return;
2262		if (_inProc) { mixin(S_TRACE);
2263			_cancel = true;
2264		} else { mixin(S_TRACE);
2265			_comm.refreshToolBar();
2266		}
2267	}
2268	private void undo() { mixin(S_TRACE);
2269		if (!_undo.canUndo) return;
2270		scope (exit) {
2271			_comm.refreshToolBar();
2272		}
2273		_inProc = true;
2274		scope (exit) _inProc = false;
2275		_inUndo = true;
2276		scope (exit) _inUndo = false;
2277		resultRedraw(false);
2278		scope (exit) resultRedraw(true);
2279		_undo.undo();
2280		_comm.updateJpy1Files();
2281	}
2282	private void redo() { mixin(S_TRACE);
2283		if (!_undo.canRedo) return;
2284		scope (exit) {
2285			_comm.refreshToolBar();
2286		}
2287		_inProc = true;
2288		scope (exit) _inProc = false;
2289		_inUndo = true;
2290		scope (exit) _inUndo = false;
2291		resultRedraw(false);
2292		scope (exit) resultRedraw(true);
2293		_undo.redo();
2294		_comm.updateJpy1Files();
2295	}
2296	private void search() { mixin(S_TRACE);
2297		auto c = _win.getDisplay().getFocusControl();
2298		_replMode = false;
2299		replaceImpl();
2300		if (c) .forceFocus(c, false);
2301	}
2302	private void replace() { mixin(S_TRACE);
2303		auto c = _win.getDisplay().getFocusControl();
2304		_replMode = true;
2305		replaceImpl();
2306		if (c) .forceFocus(_replace, false);
2307	}
2308	private void reset(bool removeColumns = true) { mixin(S_TRACE);
2309		if (!_inUndo && !_inProc) { mixin(S_TRACE);
2310			_undo.reset();
2311		}
2312		_result.removeAll();
2313		_grepCount = -1;
2314		if (removeColumns && _result.getColumnCount()) { mixin(S_TRACE);
2315			foreach (column; _result.getColumns()) { mixin(S_TRACE);
2316				column.dispose();
2317			}
2318			_result.setHeaderVisible(false);
2319		}
2320		if (_replMode) { mixin(S_TRACE);
2321			_status.setText(_prop.msgs.replResultEmpty);
2322		} else { mixin(S_TRACE);
2323			_status.setText(_prop.msgs.searchResultEmpty);
2324		}
2325		_lastFind = null;
2326		_comm.refreshToolBar();
2327	}
2328	@property
2329	private bool canFind() { mixin(S_TRACE);
2330		if (_inProc) return false;
2331		if (!_tabf || _tabf.isDisposed()) return false;
2332		auto sel = _tabf.getSelection();
2333		if (!sel) return false;
2334		if (sel is _tabText) { mixin(S_TRACE);
2335			return _summ && _from.getText().length > 0;
2336		} else if (sel is _tabID) { mixin(S_TRACE);
2337			return _summ && canReplID();
2338		} else if (sel is _tabPath) { mixin(S_TRACE);
2339			return _summ && _fromPath.getText().length > 0;
2340		} else if (sel is _tabContents) { mixin(S_TRACE);
2341			return _summ !is null;
2342		} else if (sel is _tabCoupon) { mixin(S_TRACE);
2343			return _summ !is null;
2344		} else if (sel is _tabUnuse) { mixin(S_TRACE);
2345			return _summ !is null;
2346		} else if (sel is _tabError) { mixin(S_TRACE);
2347			return _summ !is null;
2348		} else if (sel is _tabGrep) { mixin(S_TRACE);
2349			return true;
2350		} else assert (0);
2351	}
2352	@property
2353	private bool canReplace() { mixin(S_TRACE);
2354		if (_inProc) return false;
2355		if (!_tabf || _tabf.isDisposed()) return false;
2356		auto sel = _tabf.getSelection();
2357		if (!sel) return false;
2358		if (!_summ) return false;
2359		return canFind && ((sel is _tabText && !_ignoreReturnCode.getSelection()) || sel is _tabID || sel is _tabPath);
2360	}
2361	private bool canCancel() { mixin(S_TRACE);
2362		return _inProc;
2363	}
2364	private void replaceImpl() { mixin(S_TRACE);
2365		if (_inProc) return;
2366		_rUndo.length = 0;
2367		_after.length = 0;
2368
2369		_notIgnoreCaseSel = _notIgnoreCase.getSelection();
2370		_exactSel = _exact.getSelection();
2371		_ignoreReturnCodeSel = _ignoreReturnCode.getSelection();
2372		_summarySel = _summary.getSelection();
2373		_msgSel = _msg.getSelection();
2374		_cardNameSel = _cardName.getSelection();
2375		_cardDescSel = _cardDesc.getSelection();
2376		_eventSel = _event.getSelection();
2377		_startSel = _start.getSelection();
2378		_flagSel = _flag.getSelection();
2379		_couponSel = _coupon.getSelection();
2380		_gossipSel = _gossip.getSelection();
2381		_endSel = _end.getSelection();
2382		_areaSel = _area.getSelection();
2383		_keyCodeSel = _keyCode.getSelection();
2384		_fileSel = _file.getSelection();
2385		_commentSel = _comment.getSelection();
2386		_jptxSel = _jptx.getSelection();
2387		_fromText = _from.getText();
2388		_toText = _to.getText();
2389
2390		_flagDirOnRange = false;
2391		foreach (itm; _range.getItems()) { mixin(S_TRACE);
2392			if (itm.getChecked()) { mixin(S_TRACE);
2393				auto root = cast(FlagDir) itm.getData();
2394				if (root) { mixin(S_TRACE);
2395					_flagDirOnRange = true;
2396					break;
2397				}
2398			}
2399		}
2400
2401		_cancel = false;
2402		if (_tabf.getSelection() is _tabText) { mixin(S_TRACE);
2403			replaceTextImpl();
2404		} else if (_tabf.getSelection() is _tabID) { mixin(S_TRACE);
2405			replaceIDImpl();
2406		} else if (_tabf.getSelection() is _tabPath) { mixin(S_TRACE);
2407			replacePathImpl();
2408		} else if (_tabf.getSelection() is _tabContents) { mixin(S_TRACE);
2409			searchContents();
2410		} else if (_tabf.getSelection() is _tabCoupon) { mixin(S_TRACE);
2411			searchCoupon();
2412		} else if (_tabf.getSelection() is _tabUnuse) { mixin(S_TRACE);
2413			searchUnuseImpl();
2414		} else if (_tabf.getSelection() is _tabError) { mixin(S_TRACE);
2415			searchErrorImpl();
2416		} else if (_tabf.getSelection() is _tabGrep) { mixin(S_TRACE);
2417			grepImpl();
2418		} else assert (0);
2419	}
2420	private bool cautionReplace(string name1, string name2) { mixin(S_TRACE);
2421		if (_replMode && _prop.var.etc.cautionBeforeReplace) { mixin(S_TRACE);
2422			auto dlg = new MessageBox(_win, SWT.ICON_QUESTION | SWT.YES | SWT.NO);
2423			dlg.setMessage(.tryFormat(_prop.msgs.cautionOfReplace, name1, name2));
2424			dlg.setText(_prop.msgs.dlgTitQuestion);
2425			return SWT.YES == dlg.open();
2426		}
2427		return true;
2428	}
2429	private void after() { mixin(S_TRACE);
2430		foreach (a; _after) a();
2431		if (_after.length) { mixin(S_TRACE);
2432			refContentText();
2433			if (_replMode) _comm.replText.call();
2434		}
2435		if (_replMode && _rUndo.length) { mixin(S_TRACE);
2436			_undo ~= new UndoRepl(_rUndo, false);
2437		}
2438		_rUndo = [];
2439		_after = [];
2440		_comm.refreshToolBar();
2441	}
2442	@property
2443	private CWXPath[] searchRange() { mixin(S_TRACE);
2444		CWXPath[] r;
2445		void recurse(TreeItem itm) { mixin(S_TRACE);
2446			auto data = cast(CWXPath)itm.getData();
2447			if (data) r ~= data;
2448			foreach (child; itm.getItems()) { mixin(S_TRACE);
2449				if (child.getChecked()) { mixin(S_TRACE);
2450					recurse(child);
2451				}
2452			}
2453		}
2454		foreach (itm; _range.getItems()) { mixin(S_TRACE);
2455			if (itm.getChecked()) { mixin(S_TRACE);
2456				recurse(itm);
2457			}
2458		}
2459		return r;
2460	}
2461	private void searchAll(CWXPath path, ref uint count,
2462			void delegate(CWXPath path, ref uint count) dlg) { mixin(S_TRACE);
2463		if (cancel) return;
2464		dlg(path, count);
2465		// _range???????????????????
2466		auto fdir = cast(FlagDir) path;
2467		if (fdir) { mixin(S_TRACE);
2468			foreach (o; fdir.flags) searchAll(o, count, dlg);
2469			foreach (o; fdir.steps) searchAll(o, count, dlg);
2470			foreach (o; fdir.subDirs) searchAll(o, count, dlg);
2471		}
2472		auto eto = cast(EventTreeOwner) path;
2473		if (eto) { mixin(S_TRACE);
2474			foreach (o; eto.trees) searchAll(o, count, dlg);
2475		}
2476		auto et = cast(EventTree) path;
2477		if (et) { mixin(S_TRACE);
2478			foreach (o; et.starts) searchAll(o, count, dlg);
2479		}
2480		auto c = cast(Content) path;
2481		if (c) { mixin(S_TRACE);
2482			foreach (o; c.backs) searchAll(o, count, dlg);
2483			foreach (o; c.next) searchAll(o, count, dlg);
2484		}
2485		auto area = cast(Area) path;
2486		if (area) { mixin(S_TRACE);
2487			foreach (o; area.cards) searchAll(o, count, dlg);
2488			foreach (o; area.backs) searchAll(o, count, dlg);
2489		}
2490		auto battle = cast(Battle) path;
2491		if (battle) { mixin(S_TRACE);
2492			foreach (o; battle.cards) searchAll(o, count, dlg);
2493		}
2494		auto mo = cast(MotionOwner) path;
2495		if (mo) { mixin(S_TRACE);
2496			foreach (m; mo.motions) { mixin(S_TRACE);
2497				if (m.beast && 0 == m.beast.linkId) { mixin(S_TRACE);
2498					searchAll(m.beast, count, dlg);
2499				}
2500			}
2501		}
2502	}
2503
2504	@property
2505	private bool cancel() { mixin(S_TRACE);
2506		return _cancel;
2507	}
2508
2509	private void setResultStatus(uint count) { mixin(S_TRACE);
2510		if (count > 0) { mixin(S_TRACE);
2511			if (_replMode && _summ) { mixin(S_TRACE);
2512				_summ.changed();
2513				_comm.refUseCount.call();
2514			}
2515		}
2516		_inProc = false;
2517		resultRedraw(true);
2518		refResultStatus(count, true);
2519	}
2520	private void refResultStatus(uint count, bool force) { mixin(S_TRACE);
2521		if (!_prop.var.etc.searchResultRealtime) { mixin(S_TRACE);
2522			if (!force && 0 != (count % _prop.var.etc.searchResultRefreshCount)) return;
2523		}
2524		_display.syncExec(new class Runnable {
2525			void run() { mixin(S_TRACE);
2526				if (!_win || _win.isDisposed()) return;
2527				if (!_tabf.getSelection()) return;
2528				string text;
2529				string num = .formatNum(count);
2530				if (_replMode) { mixin(S_TRACE);
2531					string kind = _tabf.getSelection().getText();
2532					text = .tryFormat(_prop.msgs.replResult, num, kind);
2533				} else { mixin(S_TRACE);
2534					if (_grepSumm) { mixin(S_TRACE);
2535						text = .tryFormat(_prop.msgs.searchResultGrep2, _grepCount, num, _grepFile);
2536					} else if (_grepFile.length) { mixin(S_TRACE);
2537						text = .tryFormat(_prop.msgs.searchResultGrep1, _grepCount, num, _grepFile);
2538					} else if (0 <= _grepCount) { mixin(S_TRACE);
2539						string kind = _tabf.getSelection().getText();
2540						text = .tryFormat(_prop.msgs.searchResultGrep3, _grepCount, num, kind);
2541					} else { mixin(S_TRACE);
2542						string kind = _tabf.getSelection().getText();
2543						text = .tryFormat(_prop.msgs.searchResult, num, kind);
2544					}
2545				}
2546				_status.setText(text);
2547			}
2548		});
2549	}
2550	@property
2551	private bool[CWXPath] rangeTable() { mixin(S_TRACE);
2552		bool[CWXPath] range;
2553		void recurse(TreeItem itm) { mixin(S_TRACE);
2554			auto data = cast(CWXPath)itm.getData();
2555			if (data) range[data] = itm.getChecked();
2556			foreach (cItm; itm.getItems()) { mixin(S_TRACE);
2557				recurse(cItm);
2558			}
2559		}
2560		foreach (itm; _range.getItems()) { mixin(S_TRACE);
2561			recurse(itm);
2562		}
2563		return range;
2564	}
2565	private bool dec(CWXPath path, in bool[CWXPath] range) { mixin(S_TRACE);
2566		assert (path);
2567		auto p = path in range;
2568		if (p) { mixin(S_TRACE);
2569			return *p;
2570		}
2571		return dec(path.cwxParent, range);
2572	}
2573	private void replaceIDImpl2(ID)(ID from, ID to) { mixin(S_TRACE);
2574		if (!_summ) return;
2575		reset();
2576		_lastFind = _tabf.getSelection();
2577
2578		_result.setHeaderVisible(true);
2579		auto mainColumn = new TableColumn(_result, SWT.NONE);
2580		mainColumn.setText(_prop.msgs.searchResultColumnMain);
2581		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
2582		auto subColumn = new TableColumn(_result, SWT.NONE);
2583		subColumn.setText(_prop.msgs.searchResultColumnParent);
2584		saveColumnWidth!("prop.var.etc.searchResultColumnParent")(_prop, subColumn);
2585
2586		auto range = rangeTable;
2587
2588		auto uc = _summ.useCounter;
2589		auto users = uc.values(from);
2590		_inProc = true;
2591		scope (exit) _inProc = false;
2592		size_t count = 0;
2593
2594		auto cursors = setWaitCursors(_win);
2595		auto thr = new core.thread.Thread({ mixin(S_TRACE);
2596			auto exit = new class Runnable {
2597				override void run() { mixin(S_TRACE);
2598					_inProc = false;
2599					setResultStatus(count);
2600					if (count) { mixin(S_TRACE);
2601						_comm.replID.call();
2602					}
2603					resetCursors(cursors);
2604					after();
2605				}
2606			};
2607			scope (exit) _display.syncExec(exit);
2608
2609			try { mixin(S_TRACE);
2610				foreach (u; users) { mixin(S_TRACE);
2611					if (!dec(u.owner, range)) continue;
2612					if (_replMode) { mixin(S_TRACE);
2613						static if (is(ID:FlagId)) {
2614							u.flag = cast(string)to;
2615							storeID(u.owner, u, cast(string)from, cast(string)to, &u.flag);
2616						} else static if (is(ID:StepId)) {
2617							u.step = cast(string)to;
2618							storeID(u.owner, u, cast(string)from, cast(string)to, &u.step);
2619						} else static if (is(ID:CouponId)) {
2620							u.coupon = cast(string)to;
2621							storeID(u.owner, u, cast(string)from, cast(string)to, &u.coupon);
2622						} else static if (is(ID:GossipId)) {
2623							u.gossip = cast(string)to;
2624							storeID(u.owner, u, cast(string)from, cast(string)to, &u.gossip);
2625						} else static if (is(ID:CompleteStampId)) {
2626							u.completeStamp = cast(string)to;
2627							storeID(u.owner, u, cast(string)from, cast(string)to, &u.completeStamp);
2628						} else static if (is(ID:KeyCodeId)) {
2629							u.keyCode = cast(string)to;
2630							storeID(u.owner, u, cast(string)from, cast(string)to, &u.keyCode);
2631						// FIXME: CardWirth 1.60 ????
2632/+						} else static if (is(ID:CellNameId)) {
2633							u.cellName = cast(string)to;
2634							storeID(u.owner, u, cast(string)from, cast(string)to, &u.cellName);
2635+/						} else {
2636							u.id = to;
2637							storeID(u.owner, u, from, to, &u.id);
2638						}
2639					}
2640					addResult(u.owner, count);
2641				}
2642			} catch (Throwable e) {
2643				debugln(e);
2644			}
2645		});
2646		thr.start();
2647	}
2648	private bool canReplID() {
2649		if (idKindIsString) {
2650			return _fromID.getText() != "";
2651		} else {
2652			return getID(_fromID, _fromIDVal, _fromIDTbl) !is 0;
2653		}
2654	}
2655	private ulong getID(Combo combo, Spinner spn, ulong[int] tbl) { mixin(S_TRACE);
2656		if (!_summ) return 0;
2657		if (combo.getSelectionIndex() == 0) { mixin(S_TRACE);
2658			return spn.getSelection();
2659		} else { mixin(S_TRACE);
2660			auto p = combo.getSelectionIndex() in tbl;
2661			if (!p) return 0;
2662			return *p;
2663		}
2664	}
2665	private string getIDName(Combo combo, Spinner spn) { mixin(S_TRACE);
2666		if (combo.getSelectionIndex() == 0) { mixin(S_TRACE);
2667			auto id = spn.getSelection();
2668			string objName = _idKind.getText();
2669			return .tryFormat(_prop.msgs.idValue, id, objName);
2670		} else { mixin(S_TRACE);
2671			return .tryFormat(_prop.msgs.replaceValue, combo.getText());
2672		}
2673	}
2674	private void replaceIDImpl() { mixin(S_TRACE);
2675		if (!_summ) return;
2676		int index = _idKind.getSelectionIndex();
2677		if (idKindIsString) {
2678			string from = _fromID.getText();
2679			string to = _toID.getText();
2680			if (from == "") return;
2681			if (from == to) _replMode = false;
2682			if (!cautionReplace(from, to)) return;
2683			switch (_idKind.getSelectionIndex()) {
2684			case ID_FLAG: replaceIDImpl2(toFlagId(from), toFlagId(to)); break;
2685			case ID_STEP: replaceIDImpl2(toStepId(from), toStepId(to)); break;
2686			case ID_COUPON: replaceIDImpl2(toCouponId(from), toCouponId(to)); break;
2687			case ID_GOSSIP: replaceIDImpl2(toGossipId(from), toGossipId(to)); break;
2688			case ID_COMPLETE_STAMP: replaceIDImpl2(toCompleteStampId(from), toCompleteStampId(to)); break;
2689			case ID_KEY_CODE: replaceIDImpl2(toKeyCodeId(from), toKeyCodeId(to)); break;
2690			// FIXME: CardWirth 1.60 ????
2691/+			case ID_CELL_NAME: replaceIDImpl2(toCellNameId(from), toCellNameId(to)); break;
2692+/			default: assert (0);
2693			}
2694		} else {
2695			ulong from = getID(_fromID, _fromIDVal, _fromIDTbl);
2696			ulong to = getID(_toID, _toIDVal, _toIDTbl);
2697			if (0 == from) return;
2698			if (from == to) _replMode = false;
2699			if (!cautionReplace(getIDName(_fromID, _fromIDVal), getIDName(_toID, _toIDVal))) return;
2700			switch (_idKind.getSelectionIndex()) {
2701			case ID_AREA: replaceIDImpl2(toAreaId(from), toAreaId(to)); break;
2702			case ID_BATTLE: replaceIDImpl2(toBattleId(from), toBattleId(to)); break;
2703			case ID_PACKAGE: replaceIDImpl2(toPackageId(from), toPackageId(to)); break;
2704			case ID_CAST: replaceIDImpl2(toCastId(from), toCastId(to)); break;
2705			case ID_SKILL: replaceIDImpl2(toSkillId(from), toSkillId(to)); break;
2706			case ID_ITEM: replaceIDImpl2(toItemId(from), toItemId(to)); break;
2707			case ID_BEAST: replaceIDImpl2(toBeastId(from), toBeastId(to)); break;
2708			case ID_INFO: replaceIDImpl2(toInfoId(from), toInfoId(to)); break;
2709			default: assert (0);
2710			}
2711		}
2712	}
2713	private void replacePathImpl() { mixin(S_TRACE);
2714		if (!_summ) return;
2715		if (!_fromPath.getText().length) return;
2716		string toText = _toPath.getText();
2717		string fromName = .tryFormat(_prop.msgs.replaceValue, _fromPath.getText());
2718		string toName = toText.length ? .tryFormat(_prop.msgs.replaceValue, toText) : _prop.msgs.emptyPath;
2719		if (!cautionReplace(fromName, toName)) return;
2720		auto from = toPathId(_fromPath.getText());
2721		auto to = toPathId(_toPath.getText());
2722		if (from == to) _replMode = false;
2723		reset();
2724		_lastFind = _tabf.getSelection();
2725
2726		new FullTableColumn(_result, SWT.NONE);
2727
2728		auto range = rangeTable;
2729
2730		auto uc = _summ.useCounter;
2731		_inProc = true;
2732		scope (exit) _inProc = false;
2733		size_t count = 0;
2734
2735		auto cursors = setWaitCursors(_win);
2736		auto thr = new core.thread.Thread({ mixin(S_TRACE);
2737			string[2][] fromTos;
2738			auto exit = new class Runnable {
2739				override void run() { mixin(S_TRACE);
2740					_inProc = false;
2741					setResultStatus(count);
2742					if (count) { mixin(S_TRACE);
2743						foreach (fromTo; std.algorithm.uniq(fromTos)) { mixin(S_TRACE);
2744							_comm.replPath.call(fromTo[0], fromTo[1]);
2745						}
2746					}
2747					_comm.updateJpy1Files();
2748					resetCursors(cursors);
2749					after();
2750				}
2751			};
2752			scope (exit) _display.syncExec(exit);
2753
2754			try { mixin(S_TRACE);
2755				auto wildcard = Wildcard((cast(string)from).encodePath(), 0 == filenameCharCmp('A', 'a'));
2756				foreach (key; uc.path.keys) { mixin(S_TRACE);
2757					if (wildcard.match((cast(string)key).encodePath())) { mixin(S_TRACE);
2758						foreach (u; uc.path.values(key)) { mixin(S_TRACE);
2759							if (!cast(Jpy1Sec)u && !dec(u.owner, range)) continue;
2760							if (_replMode) { mixin(S_TRACE);
2761								auto id = u.path;
2762								u.path = cast(string)to;
2763								storeID(u.owner, u, cast(string)id, cast(string)to, (string id) { mixin(S_TRACE);
2764									u.path = id;
2765								});
2766								fromTos ~= [cast(string)id, cast(string)to];
2767							}
2768							addResult(u.owner, count);
2769						}
2770					}
2771				}
2772			} catch (Throwable e) {
2773				debugln(e);
2774			}
2775		});
2776		thr.start();
2777	}
2778
2779	private void couponEditEnd(TableItem itm, int column, string text) { mixin(S_TRACE);
2780		auto uc = _summ.useCounter;
2781		if (itm.getImage() is _prop.images.couponNormal) { mixin(S_TRACE);
2782			renameCoupon(itm, toCouponId(itm.getText()), toCouponId(text), uc.coupon);
2783			_comm.refCoupons.call();
2784		} else if (itm.getImage() is _prop.images.gossip) { mixin(S_TRACE);
2785			renameCoupon(itm, toGossipId(itm.getText()), toGossipId(text), uc.gossip);
2786			_comm.refGossips.call();
2787		} else if (itm.getImage() is _prop.images.endScenario) { mixin(S_TRACE);
2788			renameCoupon(itm, toCompleteStampId(itm.getText()), toCompleteStampId(text), uc.completeStamp);
2789			_comm.refCompleteStamps.call();
2790		} else if (itm.getImage() is _prop.images.keyCode) { mixin(S_TRACE);
2791			renameCoupon(itm, toKeyCodeId(itm.getText()), toKeyCodeId(text), uc.keyCode);
2792			_comm.refKeyCodes.call();
2793		} else { mixin(S_TRACE);
2794			// FIXME: CardWirth 1.60 ????
2795/+			renameCoupon(itm, toCellNameId(itm.getText()), toCellNameId(text), uc.cellName);
2796			_comm.refCellNames.call();
2797+/		}
2798		_comm.replText.call();
2799	}
2800	private bool canCouponEdit(TableItem itm, int column) { mixin(S_TRACE);
2801		return _lastFind is _tabCoupon;
2802	}
2803	struct CouponParams {
2804		Image image;
2805		string name;
2806		uint count;
2807	}
2808	class CouponUndo(User, KeyType) : Undo {
2809		private CouponParams[] _results;
2810		private KeyType _oldVal, _newVal;
2811		private UCCont!(KeyType, User) _uc;
2812		User[] users;
2813		this (KeyType oldVal, KeyType newVal, UCCont!(KeyType, User) uc) { mixin(S_TRACE);
2814			_oldVal = oldVal;
2815			_newVal = newVal;
2816			_uc = uc;
2817			save();
2818		}
2819		private void save() { mixin(S_TRACE);
2820			_results = [];
2821			foreach (itm; _result.getItems()) { mixin(S_TRACE);
2822				_results ~= CouponParams(itm.getImage(), itm.getText(), itm.getText(1).to!uint());
2823			}
2824		}
2825		private void impl() { mixin(S_TRACE);
2826			resultRedraw(false);
2827			scope(exit) resultRedraw(true);
2828			auto results = _results;
2829			save();
2830
2831			foreach (u; users) { mixin(S_TRACE);
2832				_uc.remove(_newVal, u);
2833				u.change(_oldVal);
2834				_uc.add(_oldVal, u);
2835			}
2836
2837			foreach (i, r; results) { mixin(S_TRACE);
2838				auto itm = i < _result.getItemCount() ? _result.getItem(i) : new TableItem(_result, SWT.NONE);
2839				itm.setImage(r.image);
2840				itm.setText(r.name);
2841				itm.setText(1, r.count.text());
2842			}
2843			while (results.length < _result.getItemCount()) { mixin(S_TRACE);
2844				_result.getItem(results.length).dispose();
2845			}
2846
2847			.swap(_oldVal, _newVal);
2848			refResultStatus(_result.getItemCount(), false);
2849			_comm.replText.call();
2850			_summ.changed();
2851		}
2852		void undo() { mixin(S_TRACE);
2853			impl();
2854		}
2855		void redo() { mixin(S_TRACE);
2856			impl();
2857		}
2858		void dispose() { }
2859	}
2860	private void renameCoupon(KeyType, UC)(TableItem itm, KeyType oldVal, KeyType newVal, UC uc) { mixin(S_TRACE);
2861		if (cast(string)oldVal == cast(string)newVal) return;
2862		if (cast(string)newVal == "") return;
2863		_inProc = true;
2864		scope (exit) _inProc = false;
2865		auto rangeT = rangeTable;
2866		auto undo = new CouponUndo!(ForeachType!(typeof(uc.values(oldVal))), KeyType)(oldVal, newVal, uc);
2867		foreach (u; uc.values(oldVal)) { mixin(S_TRACE);
2868			if (dec(u.owner, rangeT)) { mixin(S_TRACE);
2869				uc.remove(oldVal, u);
2870				u.change(newVal);
2871				uc.add(newVal, u);
2872				undo.users ~= u;
2873				itm.setText(0, cast(string)newVal);
2874			}
2875		}
2876		_undo ~= undo;
2877		// ?????????????????????????
2878		foreach (i, itm2; _result.getItems()) { mixin(S_TRACE);
2879			if (itm is itm2) continue;
2880			if (itm.getImage() !is itm2.getImage()) continue;
2881			if (itm.getText() == itm2.getText()) { mixin(S_TRACE);
2882				_result.select(i);
2883				_result.showSelection();
2884				itm2.setText(1, uc.get(newVal).text());
2885				itm.dispose();
2886				break;
2887			}
2888		}
2889		_summ.changed();
2890	}
2891	private void searchCouponImpl(KeyType)(in KeyType[] keys, UseCounter uc, in bool[CWXPath] rangeT, Image delegate() image, ref uint count) { mixin(S_TRACE);
2892		foreach (key; keys.dup.sort) { mixin(S_TRACE);
2893			if (cancel) break;
2894			uint use = 0;
2895			foreach (u; uc.values(key)) { mixin(S_TRACE);
2896				if (dec(u.owner, rangeT)) { mixin(S_TRACE);
2897					use++;
2898				}
2899			}
2900			if (use) { mixin(S_TRACE);
2901				addResult(key, use, image, count);
2902			}
2903		}
2904	}
2905	private void searchCoupon() { mixin(S_TRACE);
2906		if (!_summ) return;
2907		uint count = 0;
2908		reset();
2909		_lastFind = _tabf.getSelection();
2910
2911		_result.setHeaderVisible(true);
2912		auto mainColumn = new TableColumn(_result, SWT.NONE);
2913		mainColumn.setText(_prop.msgs.searchResultColumnCoupon);
2914		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
2915		auto subColumn = new TableColumn(_result, SWT.NONE);
2916		subColumn.setText(_prop.msgs.searchResultColumnCouponCount);
2917		saveColumnWidth!("prop.var.etc.searchResultColumnCouponCount")(_prop, subColumn);
2918
2919		bool cCouponSel = _cCoupon.getSelection();
2920		bool cKeyCodeSel = _cKeyCode.getSelection();
2921		bool cGossipSel = _cGossip.getSelection();
2922		bool cEndSel = _cEnd.getSelection();
2923		// FIXME: CardWirth 1.60 ????
2924/+		bool cCellName = _cCellName.getSelection();
2925+/
2926		auto rangeT = rangeTable;
2927		auto uc = _summ.useCounter;
2928		void search() { mixin(S_TRACE);
2929			if (cCouponSel) { mixin(S_TRACE);
2930				searchCouponImpl(uc.coupon.keys, uc, rangeT, &_prop.images.couponNormal, count);
2931			}
2932			if (cGossipSel) { mixin(S_TRACE);
2933				searchCouponImpl(uc.gossip.keys, uc, rangeT, &_prop.images.gossip, count);
2934			}
2935			if (cEndSel) { mixin(S_TRACE);
2936				searchCouponImpl(uc.completeStamp.keys, uc, rangeT, &_prop.images.endScenario, count);
2937			}
2938			if (cKeyCodeSel) { mixin(S_TRACE);
2939				searchCouponImpl(uc.keyCode.keys, uc, rangeT, &_prop.images.keyCode, count);
2940			}
2941			// FIXME: CardWirth 1.60 ????
2942/+			if (cCellName) { mixin(S_TRACE);
2943				searchCouponImpl(uc.cellName.keys, uc, rangeT, &_prop.images.backs, count);
2944			}
2945+/		}
2946
2947		_inProc = true;
2948		_comm.refreshToolBar();
2949		auto cursors = setWaitCursors(_win);
2950		auto thr = new core.thread.Thread({ mixin(S_TRACE);
2951			auto exit = new class Runnable {
2952				override void run() { mixin(S_TRACE);
2953					_inProc = false;
2954					setResultStatus(count);
2955					resetCursors(cursors);
2956					after();
2957				}
2958			};
2959			scope (exit) _display.syncExec(exit);
2960			try { mixin(S_TRACE);
2961				search();
2962			} catch (Throwable e) {
2963				debugln(e);
2964			}
2965		});
2966		thr.start();
2967	}
2968
2969	private void searchContents() { mixin(S_TRACE);
2970		if (!_summ) return;
2971		uint count = 0;
2972		reset();
2973		_lastFind = _tabf.getSelection();
2974
2975		_result.setHeaderVisible(true);
2976		auto mainColumn = new TableColumn(_result, SWT.NONE);
2977		mainColumn.setText(_prop.msgs.searchResultColumnMain);
2978		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
2979		auto subColumn = new TableColumn(_result, SWT.NONE);
2980		subColumn.setText(_prop.msgs.searchResultColumnParent);
2981		saveColumnWidth!("prop.var.etc.searchResultColumnParent")(_prop, subColumn);
2982
2983		auto range = searchRange;
2984
2985		_inProc = true;
2986		_comm.refreshToolBar();
2987		auto cursors = setWaitCursors(_win);
2988		bool[CType] contents;
2989		foreach (type; EnumMembers!CType) { mixin(S_TRACE);
2990			// FIXME: CardWirth 1.60 ????
2991			switch (type) {
2992			case CType.MOVE_BG_IMAGE: /// ?????(CardWirth 1.60)?
2993			case CType.REPLACE_BG_IMAGE: /// ????(CardWirth 1.60)?
2994			case CType.LOSE_BG_IMAGE: /// ????(CardWirth 1.60)?
2995				continue;
2996			default:
2997				break;
2998			}
2999			// FIXME: CardWirth 1.60 ????
3000			contents[type] = _contents[type].getSelection();
3001		}
3002		auto thr = new core.thread.Thread({ mixin(S_TRACE);
3003			auto exit = new class Runnable {
3004				override void run() { mixin(S_TRACE);
3005					_inProc = false;
3006					setResultStatus(count);
3007					resetCursors(cursors);
3008					after();
3009				}
3010			};
3011			scope (exit) _display.syncExec(exit);
3012			try { mixin(S_TRACE);
3013				foreach (path; range) { mixin(S_TRACE);
3014					searchAll(path, count, (CWXPath path, ref uint count) { mixin(S_TRACE);
3015						if (cancel) return;
3016						auto c = cast(Content) path;
3017						if (!c) return;
3018						assert (c.type in _contents);
3019						if (!contents[c.type]) return;
3020						addResult(path, count);
3021					});
3022				}
3023			} catch (Throwable e) {
3024				debugln(e);
3025			}
3026		});
3027		thr.start();
3028	}
3029
3030	private void searchUnuseImpl2(string ToId, T)(T[] all, ref uint count) { mixin(S_TRACE);
3031		if (!_summ) return;
3032		foreach (o; all) { mixin(S_TRACE);
3033			if (cancel) break;
3034			if (_summ.useCounter.get(mixin (ToId)) == 0) { mixin(S_TRACE);
3035				addResult(o, count);
3036			}
3037		}
3038	}
3039	private void searchUnuseImpl() { mixin(S_TRACE);
3040		if (!_summ) return;
3041		_replMode = false;
3042		uint count = 0;
3043		reset();
3044		_lastFind = _tabf.getSelection();
3045
3046		new FullTableColumn(_result, SWT.NONE);
3047
3048		auto range = searchRange();
3049
3050		bool unuseFlagSel = _unuseFlag.getSelection();
3051		bool unuseStepSel = _unuseStep.getSelection();
3052		bool unuseAreaSel = _unuseArea.getSelection();
3053		bool unuseBattleSel = _unuseBattle.getSelection();
3054		bool unusePackageSel = _unusePackage.getSelection();
3055		bool unuseCastSel = _unuseCast.getSelection();
3056		bool unuseSkillSel = _unuseSkill.getSelection();
3057		bool unuseItemSel = _unuseItem.getSelection();
3058		bool unuseBeastSel = _unuseBeast.getSelection();
3059		bool unuseInfoSel = _unuseInfo.getSelection();
3060		bool unuseStartSel = _unuseStart.getSelection();
3061		bool unusePathSel = _unusePath.getSelection();
3062
3063		void search() { mixin(S_TRACE);
3064			if (unuseFlagSel) { mixin(S_TRACE);
3065				searchUnuseImpl2!("toFlagId(o.path)")(_summ.flagDirRoot.allFlags, count);
3066			}
3067			if (unuseStepSel) { mixin(S_TRACE);
3068				searchUnuseImpl2!("toStepId(o.path)")(_summ.flagDirRoot.allSteps, count);
3069			}
3070			if (unuseAreaSel) { mixin(S_TRACE);
3071				searchUnuseImpl2!("toAreaId(o.id)")(_summ.areas, count);
3072			}
3073			if (unuseBattleSel) { mixin(S_TRACE);
3074				searchUnuseImpl2!("toBattleId(o.id)")(_summ.battles, count);
3075			}
3076			if (unusePackageSel) { mixin(S_TRACE);
3077				searchUnuseImpl2!("toPackageId(o.id)")(_summ.packages, count);
3078			}
3079			if (unuseCastSel) { mixin(S_TRACE);
3080				searchUnuseImpl2!("toCastId(o.id)")(_summ.casts, count);
3081			}
3082			if (unuseSkillSel) { mixin(S_TRACE);
3083				searchUnuseImpl2!("toSkillId(o.id)")(_summ.skills, count);
3084			}
3085			if (unuseItemSel) { mixin(S_TRACE);
3086				searchUnuseImpl2!("toItemId(o.id)")(_summ.items, count);
3087			}
3088			if (unuseBeastSel) { mixin(S_TRACE);
3089				searchUnuseImpl2!("toBeastId(o.id)")(_summ.beasts, count);
3090			}
3091			if (unuseInfoSel) { mixin(S_TRACE);
3092				searchUnuseImpl2!("toInfoId(o.id)")(_summ.infos, count);
3093			}
3094			if (unuseStartSel) { mixin(S_TRACE);
3095				foreach (path; range) { mixin(S_TRACE);
3096					searchAll(path, count, (CWXPath path, ref uint count) { mixin(S_TRACE);
3097						if (cancel) return;
3098						auto et = cast(EventTree) path;
3099						if (et) { mixin(S_TRACE);
3100							foreach (s; et.starts[1 .. $]) { mixin(S_TRACE);
3101								if (et.startUseCounter.get(toStartId(s.name)) == 0) { mixin(S_TRACE);
3102									addResult(s, count);
3103								}
3104							}
3105						}
3106					});
3107				}
3108			}
3109			if (unusePathSel) { mixin(S_TRACE);
3110				auto files = _summ.notUsedFiles(_comm.skin, _prop.var.etc.ignorePaths, _prop.var.etc.logicalSort);
3111				foreach (file; files) { mixin(S_TRACE);
3112					if (cancel) break;
3113					addResult(encodePath(file), count);
3114				}
3115			}
3116		}
3117
3118		_inProc = true;
3119		_comm.refreshToolBar();
3120		auto cursors = setWaitCursors(_win);
3121		auto thr = new core.thread.Thread({ mixin(S_TRACE);
3122			auto exit = new class Runnable {
3123				override void run() { mixin(S_TRACE);
3124					_inProc = false;
3125					setResultStatus(count);
3126					resetCursors(cursors);
3127					after();
3128				}
3129			};
3130			scope (exit) _display.syncExec(exit);
3131			try { mixin(S_TRACE);
3132				search();
3133			} catch (Throwable e) {
3134				debugln(e);
3135			}
3136		});
3137		thr.start();
3138	}
3139	private void searchErrorImpl() { mixin(S_TRACE);
3140		if (!_summ) return;
3141		uint count = 0;
3142		auto froot = _summ.flagDirRoot;
3143		auto sPath = _summ.scenarioPath;
3144		auto skin = _comm.skin;
3145		auto targVer = _prop.var.etc.targetVersion;
3146		reset();
3147		_lastFind = _tabf.getSelection();
3148
3149		_result.setHeaderVisible(true);
3150		auto mainColumn = new TableColumn(_result, SWT.NONE);
3151		mainColumn.setText(_prop.msgs.searchResultColumnError);
3152		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
3153		auto subColumn = new TableColumn(_result, SWT.NONE);
3154		subColumn.setText(_prop.msgs.searchResultColumnParent);
3155		saveColumnWidth!("prop.var.etc.searchResultColumnParent")(_prop, subColumn);
3156		auto descColumn = new TableColumn(_result, SWT.NONE);
3157		descColumn.setText(_prop.msgs.searchResultColumnErrorDesc);
3158		saveColumnWidth!("prop.var.etc.searchResultColumnErrorDesc")(_prop, descColumn);
3159
3160		auto range = searchRange;
3161
3162		void search(CWXPath path) { mixin(S_TRACE);
3163			searchAll(path, count, (CWXPath path, ref uint count) { mixin(S_TRACE);
3164				if (cancel) return;
3165				auto warnings = .warnings(_prop.parent, skin, _summ, path, targVer);
3166				foreach (warning; warnings) { mixin(S_TRACE);
3167					addResult(path, count, warning);
3168				}
3169			});
3170		}
3171		void searchFileErrors() { mixin(S_TRACE);
3172			string sPath = _summ.scenarioPath;
3173			string[string] digests;
3174			void recurse(string file) { mixin(S_TRACE);
3175				try { mixin(S_TRACE);
3176					bool dir = .isDir(file);
3177					if (_summ.isSystemFile(file, dir)) return;
3178					if (containsPath(_prop.var.etc.ignorePaths, file.baseName())) return;
3179					if (dir) { mixin(S_TRACE);
3180						foreach (string sub; clistdir(file)) { mixin(S_TRACE);
3181							recurse(file.buildPath(sub));
3182						}
3183					} else { mixin(S_TRACE);
3184						auto size = file.getSize();
3185						if (!size) { mixin(S_TRACE);
3186							addResult(abs2rel(file, sPath), count, _prop.msgs.searchErrorEmptyFile);
3187							return;
3188						}
3189						auto digest = file.fileToMD5Digest();
3190						if (!digest.length) return;
3191						digest = .format("%s-%s", digest, size);
3192
3193						auto p = digest in digests;
3194						if (!p) { mixin(S_TRACE);
3195							digests[digest] = file;
3196							return;
3197						}
3198						addResult(abs2rel(file, sPath), count, .tryFormat(_prop.msgs.searchErrorDupFile, abs2rel(*p, sPath)));
3199					}
3200				} catch (Exception e) {
3201					debugln(e);
3202				}
3203			}
3204			recurse(sPath);
3205		}
3206
3207		_inProc = true;
3208		_comm.refreshToolBar();
3209		auto cursors = setWaitCursors(_win);
3210		auto thr = new core.thread.Thread({ mixin(S_TRACE);
3211			auto exit = new class Runnable {
3212				override void run() { mixin(S_TRACE);
3213					_inProc = false;
3214					setResultStatus(count);
3215					resetCursors(cursors);
3216					after();
3217				}
3218			};
3219			scope (exit) _display.syncExec(exit);
3220			try { mixin(S_TRACE);
3221				foreach (path; range) { mixin(S_TRACE);
3222					search(path);
3223				}
3224				searchFileErrors();
3225			} catch (Throwable e) {
3226				debugln(e);
3227			}
3228		});
3229		thr.start();
3230	}
3231	private void replaceTextImpl(CWXPath c, ref size_t count) { mixin(S_TRACE);
3232		if (cancel) return;
3233		bool oldIgnoreMod = ignoreMod;
3234		ignoreMod = true;
3235		scope (exit) ignoreMod = oldIgnoreMod;
3236		size_t dmy = 0;
3237		auto summ = cast(Summary) c;
3238		if (summ) { mixin(S_TRACE);
3239			bool sr = false;
3240			Undo[] uArr;
3241			if (_summarySel) { mixin(S_TRACE);
3242				sr |= repl(null, summ.scenarioName, &summ.scenarioName, count, uArr);
3243				sr |= repl(null, summ.desc, &summ.desc, count, uArr);
3244			}
3245			if (_couponSel) { mixin(S_TRACE);
3246				sr |= replRqCoupons(null, summ, count, uArr);
3247			}
3248			if (sr) { mixin(S_TRACE);
3249				if (_replMode) store(summ, uArr);
3250				addResult(summ, dmy);
3251			}
3252		}
3253		auto cc = cast(CastCard) c;
3254		if (cc) { mixin(S_TRACE);
3255			Undo[] uArr;
3256			bool r = replCard!(CastCard)(null, cc, count, uArr);
3257			if (_couponSel) { mixin(S_TRACE);
3258				Coupon[] coupons = null;
3259				if (_replMode) coupons = new Coupon[cc.coupons.length];
3260				foreach (i, cp; cc.coupons) { mixin(S_TRACE);
3261					Coupon cp2 = null;
3262					r |= repl(null, cp.name,
3263						(string t) {cp2 = new Coupon(t, cp.value);}, count, uArr);
3264					if (_replMode) coupons[i] = cp2 ? cp2 : new Coupon(cp);
3265				}
3266				if (_replMode) cc.coupons = coupons;
3267			}
3268			if (r) { mixin(S_TRACE);
3269				if (_replMode) store(cc, uArr);
3270				addResult(cc, dmy);
3271			}
3272		}
3273		Undo[] nArr;
3274		auto eff = cast(EffectCard) c;
3275		if (eff) { mixin(S_TRACE);
3276			replCard(eff, eff, count, nArr);
3277		}
3278		auto info = cast(InfoCard) c;
3279		if (info) { mixin(S_TRACE);
3280			replCard(info, info, count, nArr);
3281		}
3282		auto a = cast(AbstractArea) c;
3283		if (a) { mixin(S_TRACE);
3284			if (_areaSel) { mixin(S_TRACE);
3285				repl(a, a.name, &a.name, count, nArr);
3286			}
3287		}
3288		auto menu = cast(MenuCard) c;
3289		if (menu) { mixin(S_TRACE);
3290			replCard(menu, menu, count, nArr);
3291		}
3292		auto back = cast(BgImage) c;
3293		if (back) { mixin(S_TRACE);
3294			replBgImage(back, back, count, nArr);
3295		}
3296		auto f = cast(Flag) c;
3297		if (f && _flagSel) { mixin(S_TRACE);
3298			Undo[] uArr = new Undo[0];
3299			bool r = replFlagName!Flag(f.parent, f, count, uArr);
3300			r |= repl(null, f.on, &f.on, count, uArr);
3301			r |= repl(null, f.off, &f.off, count, uArr);
3302			if (r) { mixin(S_TRACE);
3303				if (_replMode) store(f, uArr);
3304				addResult(f, dmy);
3305			}
3306		}
3307		auto s = cast(Step) c;
3308		if (s && _flagSel) { mixin(S_TRACE);
3309			Undo[] uArr;
3310			bool r = replFlagName!Step(s.parent, s, count, uArr);
3311			foreach (i, v; s.values) { mixin(S_TRACE);
3312				r |= repl(null, v, (string t) {s.setValue(i, t);}, count, uArr);
3313			}
3314			if (r) { mixin(S_TRACE);
3315				if (_replMode) store(s, uArr);
3316				addResult(s, dmy);
3317			}
3318		}
3319		auto et = cast(EventTree) c;
3320		if (et) { mixin(S_TRACE);
3321			replFKeyCode(et, et, count, nArr);
3322		}
3323		auto content = cast(Content) c;
3324		if (content) { mixin(S_TRACE);
3325			replContent(content, count);
3326		}
3327	}
3328	private void initText(string from, string to) { mixin(S_TRACE);
3329		if (_useRegex.getSelection()) { mixin(S_TRACE);
3330			try { mixin(S_TRACE);
3331				_regex = .regex!(dstring)(toUTF32(from), _notIgnoreCase.getSelection() ? "gm" : "gim");
3332				_regexTarg = true;
3333				_toTemp = toUTF32(to);
3334			} catch (Exception e) {
3335				MessageBox.showWarning
3336					(_prop.msgs.regexError ~ "\n" ~ e.msg,
3337					_prop.msgs.dlgTitWarning, _win);
3338				return;
3339			}
3340		} else if (_useWildcard.getSelection()) { mixin(S_TRACE);
3341			_wildcard = Wildcard(from, !_notIgnoreCase.getSelection());
3342		} else { mixin(S_TRACE);
3343			if (from == to) _replMode = false;
3344		}
3345	}
3346	private void exitText() { mixin(S_TRACE);
3347		if (!_win || _win.isDisposed()) return;
3348		_wildcard = null;
3349		_regex = typeof(_regex).init;
3350		_regexTarg = false;
3351		_toTemp = ""d;
3352	}
3353	private static void addHist(Combo combo, void delegate(string[]) set,
3354			string[] delegate() get, int max, string text) { mixin(S_TRACE);
3355		if (text.length) { mixin(S_TRACE);
3356			string[] list = get();
3357			if (.contains(list, text)) { mixin(S_TRACE);
3358				list = cwx.utils.remove(list, text);
3359			}
3360			list = [text] ~ list;
3361			if (list.length > max) { mixin(S_TRACE);
3362				list = list[0 .. $ - 1];
3363			}
3364			set(list);
3365			setComboItems(combo, list);
3366			combo.select(0);
3367		}
3368	}
3369	private void replaceTextImpl() { mixin(S_TRACE);
3370		if (!_summ) return;
3371		string from = _from.getText();
3372		string to = _to.getText();
3373		if (!from.length) return;
3374		string fromName = from.length ? .tryFormat(_prop.msgs.replaceValue, from) : _prop.msgs.emptyText;
3375		string toName = to.length ? .tryFormat(_prop.msgs.replaceValue, to) : _prop.msgs.emptyText;
3376		if (!cautionReplace(fromName, toName)) return;
3377		initText(from, to);
3378
3379		size_t count = 0;
3380		reset();
3381		_lastFind = _tabf.getSelection();
3382
3383		_result.setHeaderVisible(true);
3384		auto mainColumn = new TableColumn(_result, SWT.NONE);
3385		mainColumn.setText(_prop.msgs.searchResultColumnMain);
3386		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
3387		auto subColumn = new TableColumn(_result, SWT.NONE);
3388		subColumn.setText(_prop.msgs.searchResultColumnParent);
3389		saveColumnWidth!("prop.var.etc.searchResultColumnParent")(_prop, subColumn);
3390
3391		auto range = searchRange;
3392		_inProc = true;
3393		_comm.refreshToolBar();
3394		addHist(_from, (string[] s) {_prop.var.etc.searchHistories = s;},
3395			{return _prop.var.etc.searchHistories.dup;},
3396			_prop.var.etc.searchHistoryMax, from);
3397		if (_replMode) { mixin(S_TRACE);
3398			addHist(_to, (string[] s) {_prop.var.etc.replaceHistories = s;},
3399				{return _prop.var.etc.replaceHistories.dup;},
3400				_prop.var.etc.searchHistoryMax, to);
3401		}
3402		_comm.refSearchHistories.call(this);
3403
3404		void search() { mixin(S_TRACE);
3405			foreach (path; range) { mixin(S_TRACE);
3406				searchAll(path, count, &replaceTextImpl);
3407			}
3408			if (_jptxSel) { mixin(S_TRACE);
3409				foreach (string file; .dirEntries(_summ.scenarioPath, SpanMode.depth, false)) { mixin(S_TRACE);
3410					if (cancel) break;
3411					if (cfnmatch(.extension(file), ".jptx")) { mixin(S_TRACE);
3412						try { mixin(S_TRACE);
3413							bool isSJIS;
3414							auto errInfo = new EffectBoosterError;
3415							string value = readJPYFile(file, _prop.parent, errInfo, isSJIS);
3416							auto jText = jptxText(value);
3417							Undo[] uArr;
3418							string file2 = file;
3419							bool r = repl(null, jText, (string jText) { mixin(S_TRACE);
3420								string value = jptxText(value, jText);
3421								try { mixin(S_TRACE);
3422									writeJPYFile(file2, value, isSJIS);
3423								} catch (Exception e) {
3424									debugln(e);
3425								}
3426							}, count, uArr, true);
3427							if (r) { mixin(S_TRACE);
3428								file = abs2rel(file, _summ.scenarioPath);
3429								size_t dmy = 0;
3430								addResult(file, dmy);
3431								store(file, uArr);
3432							}
3433						} catch (Exception e) {
3434							debugln(e);
3435						}
3436					}
3437				}
3438			}
3439		}
3440
3441		auto cursors = setWaitCursors(_win);
3442		auto thr = new core.thread.Thread({ mixin(S_TRACE);
3443			auto exit = new class Runnable {
3444				override void run() { mixin(S_TRACE);
3445					_inProc = false;
3446					setResultStatus(count);
3447					exitText();
3448					if (_replMode && !_after.length) _comm.replText.call();
3449
3450					resetCursors(cursors);
3451					after();
3452				}
3453			};
3454			scope (exit) _display.syncExec(exit);
3455
3456			try { mixin(S_TRACE);
3457				search();
3458			} catch (Throwable e) {
3459				debugln(e);
3460			}
3461		});
3462		thr.start();
3463	}
3464	private void grepImpl() { mixin(S_TRACE);
3465		string from = _from.getText();
3466		auto dirBase = _grepDir.getText();
3467		auto dir = _prop.toAppAbs(dirBase);
3468		initText(from, "");
3469		_replMode = false;
3470
3471		size_t count = 0;
3472		reset();
3473		_grepCount = 0;
3474		_lastFind = _tabf.getSelection();
3475
3476		_result.setHeaderVisible(true);
3477		auto mainColumn = new TableColumn(_result, SWT.NONE);
3478		mainColumn.setText(_prop.msgs.searchResultColumnMain);
3479		saveColumnWidth!("prop.var.etc.searchResultColumnMain")(_prop, mainColumn);
3480		auto subColumn = new TableColumn(_result, SWT.NONE);
3481		subColumn.setText(_prop.msgs.searchResultColumnParent);
3482		saveColumnWidth!("prop.var.etc.searchResultColumnParent")(_prop, subColumn);
3483		auto scColumn = new TableColumn(_result, SWT.NONE);
3484		scColumn.setText(_prop.msgs.searchResultColumnScenario);
3485		saveColumnWidth!("prop.var.etc.searchResultColumnScenario")(_prop, scColumn);
3486
3487		if (!dir.exists()) return;
3488		LoadOption opt;
3489		opt.doubleIO = _prop.var.etc.doubleIO;
3490		opt.cardOnly = false;
3491		opt.textOnly = true;
3492		opt.expandXMLs = false;
3493		opt.summaryOnly = true;
3494		foreach (b; _noSummText) { mixin(S_TRACE);
3495			if (b.getSelection()) { mixin(S_TRACE);
3496				opt.summaryOnly = false;
3497				break;
3498			}
3499		}
3500		if (0 == from.length) { mixin(S_TRACE);
3501			opt.summaryOnly = true;
3502		}
3503		bool subDir = _grepSubDir.getSelection();
3504
3505		void findSumm(string summFile) { mixin(S_TRACE);
3506			if (cancel) return;
3507			_grepFile = summFile;
3508			scope (exit) _grepFile = "";
3509			refResultStatus(count, true);
3510			auto summ = Summary.loadScenarioFromFile(_prop.parent, opt, summFile, _prop.tempPath);
3511			if (!summ) return;
3512			_grepSumm = summ;
3513			_grepCount++;
3514			scope (exit) {
3515				summ.delTemp();
3516				_grepSkin = null;
3517				destroy(summ);
3518				_grepSumm = null;
3519				core.memory.GC.collect();
3520				core.memory.GC.minimize();
3521			}
3522			if (!_fromText.length) { mixin(S_TRACE);
3523				addResult(summ, count);
3524				return;
3525			}
3526			refResultStatus(count, true);
3527			auto range = rangeTree(summ);
3528			foreach (path; range) { mixin(S_TRACE);
3529				if (cancel) return;
3530				searchAll(path, count, &replaceTextImpl);
3531			}
3532			if (_jptxSel) { mixin(S_TRACE);
3533				foreach (string file; .dirEntries(summ.scenarioPath, SpanMode.depth, false)) { mixin(S_TRACE);
3534					if (cancel) break;
3535					if (cfnmatch(.extension(file), ".jptx")) { mixin(S_TRACE);
3536						bool isSJIS;
3537						auto errInfo = new EffectBoosterError;
3538						try { mixin(S_TRACE);
3539							string value = readJPYFile(file, _prop.parent, errInfo, isSJIS);
3540							auto jText = jptxText(value);
3541							Undo[] uArr;
3542							string file2 = file;
3543							bool r = repl(null, jText, null, count, uArr, true);
3544							if (r) { mixin(S_TRACE);
3545								file = abs2rel(file, summ.scenarioPath);
3546								size_t dmy = 0;
3547								addResult(file, dmy);
3548							}
3549						} catch (Exception e) {
3550							debugln(e);
3551						}
3552					}
3553				}
3554			}
3555			refResultStatus(count, true);
3556		}
3557		void recurse(string dir, uint rec) { mixin(S_TRACE);
3558			if (cancel) return;
3559			if (dir.buildPath("Summary.xml").exists() || dir.buildPath("Summary.wsm").exists()) { mixin(S_TRACE);
3560				try { mixin(S_TRACE);
3561					findSumm(dir);
3562				} catch (Exception e) {
3563					debugln(e);
3564				}
3565			}
3566			foreach (file; clistdir(dir)) { mixin(S_TRACE);
3567				if (cancel) break;
3568				try { mixin(S_TRACE);
3569					file = dir.buildPath(file);
3570					if (file.isDir()) { mixin(S_TRACE);
3571						if (subDir || 0 == rec) recurse(file, rec + 1);
3572					} else { mixin(S_TRACE);
3573						auto ext = file.extension();
3574						if (cfnmatch(ext, ".wsn") || cfnmatch(ext, ".zip") || (canUncab && cfnmatch(ext, ".cab"))) { mixin(S_TRACE);
3575							findSumm(file);
3576						}
3577					}
3578				} catch (Exception e) {
3579					debugln(e);
3580				}
3581			}
3582		}
3583		_inProc = true;
3584		_inGrep = true;
3585		_comm.refreshToolBar();
3586		addHist(_from, (string[] s) {_prop.var.etc.searchHistories = s;},
3587			{return _prop.var.etc.searchHistories.dup;},
3588			_prop.var.etc.searchHistoryMax, from);
3589		addHist(_grepDir, (string[] s) {_prop.var.etc.grepDirHistories = s;},
3590			{return _prop.var.etc.grepDirHistories.dup;},
3591			_prop.var.etc.searchHistoryMax, dirBase);
3592		_comm.refSearchHistories.call(this);
3593		auto cursors = setWaitCursors(_win);
3594		auto thr = new core.thread.Thread({ mixin(S_TRACE);
3595			auto exit = new class Runnable {
3596				override void run() { mixin(S_TRACE);
3597					_inProc = false;
3598					_inGrep = false;
3599					exitText();
3600					setResultStatus(count);
3601					resetCursors(cursors);
3602					after();
3603				}
3604			};
3605			scope (exit) _display.syncExec(exit);
3606			try { mixin(S_TRACE);
3607				recurse(dir, 0);
3608			} catch (Throwable e) {
3609				debugln(e);
3610			}
3611		});
3612		thr.start();
3613	}
3614	private void refSearchHistories(Object sender) { mixin(S_TRACE);
3615		if (sender is this) return;
3616		updateFromHistory();
3617		updateToHistory();
3618		setComboItems(_grepDir, _prop.var.etc.grepDirHistories.dup);
3619	}
3620	private void updateFromHistory() {
3621		string ft = _from.getText();
3622		_from.removeAll();
3623		foreach (hist; _prop.var.etc.searchHistories) {
3624			if (!_fromIncSearch.match(hist)) continue;
3625			_from.add(hist);
3626		}
3627		_from.setText(ft);
3628	}
3629	private void updateToHistory() {
3630		string tt = _to.getText();
3631		_to.removeAll();
3632		foreach (hist; _prop.var.etc.replaceHistories) {
3633			if (!_toIncSearch.match(hist)) continue;
3634			_to.add(hist);
3635		}
3636		_to.setText(tt);
3637	}
3638	private Regex!(dchar) _regex;
3639	private bool _regexTarg = false;
3640	private Wildcard _wildcard = null;
3641	private dstring _toTemp = ""d;
3642	private string fTextRepl(string s) { mixin(S_TRACE);
3643		if (_regexTarg) { mixin(S_TRACE);
3644			return toUTF8(std.regex.replace(toUTF32(s), _regex, _toTemp));
3645		}
3646		string to = _toText;
3647		if (_wildcard) { mixin(S_TRACE);
3648			return _wildcard.replace(s, to);
3649		}
3650		string from = _fromText;
3651		if (_notIgnoreCaseSel) { mixin(S_TRACE);
3652			if (_exactSel) { mixin(S_TRACE);
3653				return 0 == cmp(s, from) ? to : from;
3654			} else { mixin(S_TRACE);
3655				return .replace(s, from, to);
3656			}
3657		} else { mixin(S_TRACE);
3658			if (_exactSel) { mixin(S_TRACE);
3659				return 0 == icmp(s, from) ? to : from;
3660			} else { mixin(S_TRACE);
3661				return .ireplace(s, from, to);
3662			}
3663		}
3664	}
3665	private size_t fTextCount(string s) { mixin(S_TRACE);
3666		if (_ignoreReturnCodeSel) s = .singleLine(s);
3667		if (_regexTarg) { mixin(S_TRACE);
3668			size_t c = 0;
3669			try { mixin(S_TRACE);
3670				foreach (m; std.regex.match(toUTF32(s), _regex)) { mixin(S_TRACE);
3671					c++;
3672				}
3673			} catch (Throwable e) {
3674 				debugln(_fromText, " -> ", s);
3675				throw e;
3676			}
3677			return c;
3678		}
3679		if (_wildcard) { mixin(S_TRACE);
3680			return _wildcard.count(s);
3681		}
3682		string from = _fromText;
3683		if (_notIgnoreCaseSel) { mixin(S_TRACE);
3684			if (_exactSel) { mixin(S_TRACE);
3685				return 0 == cmp(s, from) ? 1 : 0;
3686			} else { mixin(S_TRACE);
3687				return std.algorithm.count(s, from);
3688			}
3689		} else { mixin(S_TRACE);
3690			if (_exactSel) { mixin(S_TRACE);
3691				return 0 == icmp(s, from) ? 1 : 0;
3692			} else { mixin(S_TRACE);
3693				return .icount(s, from);
3694			}
3695		}
3696	}
3697	private void exit() { mixin(S_TRACE);
3698		_win.close();
3699	}
3700	private bool _replMode = false;
3701
3702	private bool canOpenPath() { mixin(S_TRACE);
3703		auto sels = _result.getSelection();
3704		if (!sels.length) return false;
3705		foreach (itm; sels) { mixin(S_TRACE);
3706			auto d = itm.getData();
3707			if (cast(CWXPathString) d !is null || cast(FilePathString) d !is null) { mixin(S_TRACE);
3708				return true;
3709			}
3710		}
3711		return false;
3712	}
3713	private void openPath() { mixin(S_TRACE);
3714		auto i = _result.getSelectionIndex();
3715		if (-1 == i) return;
3716		foreach (itm; [_result.getItem(i)] ~ _result.getItems()) { mixin(S_TRACE);
3717			auto d = itm.getData();
3718			auto rp = cast(CWXPathString) d;
3719			if (rp) { mixin(S_TRACE);
3720				auto path = rp.array;
3721				if (_prop.var.etc.searchOpenDialog) { mixin(S_TRACE);
3722					path = cpaddattr(path, "opendialog");
3723				}
3724				if (rp.scPath !is null) { mixin(S_TRACE);
3725					exec(_prop.parent.appPath ~ " " ~ rp.scPath ~ " " ~ path);
3726					return;
3727				}
3728				if (!_summ) return;
3729				try { mixin(S_TRACE);
3730					if (_comm.openCWXPath(path, false)) { mixin(S_TRACE);
3731						if (!_prop.var.etc.searchOpenDialog) _win.setActive();
3732						return;
3733					}
3734				} catch (Exception e) {
3735					debugln(e);
3736				}
3737				MessageBox.showWarning(.tryFormat(_prop.msgs.cwxPathOpenError, path), _prop.msgs.dlgTitWarning, _win);
3738				return;
3739			}
3740			if (!_summ) return;
3741			auto p = cast(FilePathString) d;
3742			if (p) { mixin(S_TRACE);
3743				auto path = nabs(std.path.buildPath(_summ.scenarioPath, p.array));
3744				if (p.scPath !is null) { mixin(S_TRACE);
3745					exec(_prop.parent.appPath ~ " -selectfile " ~ p.array ~ " " ~ p.scPath);
3746					return;
3747				}
3748				if (_comm.openFilePath(path, false)) { mixin(S_TRACE);
3749					_win.setActive();
3750					return;
3751				}
3752				MessageBox.showWarning(.tryFormat(_prop.msgs.filePathOpenError, path), _prop.msgs.dlgTitWarning, _win);
3753				return;
3754			}
3755		}
3756	}
3757	Image fimage(string file, Skin skin) { mixin(S_TRACE);
3758		return .fimage(_prop, file, skin);
3759	}
3760	private void copyResult() { mixin(S_TRACE);
3761		string[] t;
3762		foreach (itm; _result.getSelection()) { mixin(S_TRACE);
3763			string[] line;
3764			foreach (i; 0 .. _result.getColumnCount()) { mixin(S_TRACE);
3765				line ~= itm.getText(i).replace("\n", .newline);
3766			}
3767			t ~= std.string.join(line, "\t");
3768		}
3769		if (!t.length) return;
3770		auto text = new ArrayWrapperString(std.string.join(t, .newline));
3771		_comm.clipboard.setContents([text], [TextTransfer.getInstance()]);
3772		_comm.refreshToolBar();
3773	}
3774	private void addResult(string path, ref size_t count, string desc = "") { mixin(S_TRACE);
3775		if (cancel) return;
3776		count++;
3777		auto addResultPath = new AddResultPath;
3778		addResultPath.path = path;
3779		addResultPath.desc = desc;
3780		addResultPath.count = count;
3781		_display.syncExec(addResultPath);
3782	}
3783	private void refContentText() { mixin(S_TRACE);
3784		foreach (itm; _result.getItems()) { mixin(S_TRACE);
3785			auto c = cast(CWXPathString) itm.getData();
3786			if (c) { mixin(S_TRACE);
3787				string text1, text2;
3788				Image img1, img2;
3789				getPathParams(c.path, text1, text2, img1, img2);
3790				itm.setImage(0, img1);
3791				itm.setText(0, text1);
3792				itm.setImage(1, img2);
3793				itm.setText(1, text2);
3794			}
3795		}
3796	}
3797	private void getPathParams(CWXPath path, out string text, out string text2, out Image img, out Image img2, bool par = false) { mixin(S_TRACE);
3798		if (!path) return;
3799		auto summ = _grepSumm ? _grepSumm : _summ;
3800		getSymbols(_comm, summ, path, text, text2, img, img2, par);
3801	}
3802	private void addResult(CWXPath path, ref size_t count, string desc = "", int index = -1) { mixin(S_TRACE);
3803		if (cancel) return;
3804		count++;
3805		auto addResultCWXPath = new AddResultCWXPath;
3806		addResultCWXPath.path = path;
3807		addResultCWXPath.index = index;
3808		addResultCWXPath.desc = desc;
3809		addResultCWXPath.count = count;
3810		_display.syncExec(addResultCWXPath);
3811	}
3812	private void addResult(string name, Image delegate() image, ref size_t count, int index = -1) { mixin(S_TRACE);
3813		if (cancel) return;
3814		count++;
3815		auto addResultMsg = new AddResultMsg;
3816		addResultMsg.name = name;
3817		addResultMsg.image = image;
3818		addResultMsg.index = index;
3819		addResultMsg.count = count;
3820		_display.syncExec(addResultMsg);
3821	}
3822	private void addResult(string name, uint use, Image delegate() image, ref size_t count, int index = -1) { mixin(S_TRACE);
3823		if (cancel) return;
3824		count++;
3825		auto addResultUse = new AddResultUse;
3826		addResultUse.name = name;
3827		addResultUse.use = use;
3828		addResultUse.image = image;
3829		addResultUse.index = index;
3830		addResultUse.count = count;
3831		_display.syncExec(addResultUse);
3832	}
3833	private bool repl(CWXPath path, string text, void delegate(string) set, ref size_t count, ref Undo[] uArr, bool storeToArr = false) { mixin(S_TRACE);
3834		auto c = fTextCount(text);
3835		count += c;
3836		if (c > 0) { mixin(S_TRACE);
3837			string n;
3838			if (_replMode && set) { mixin(S_TRACE);
3839				n = fTextRepl(text);
3840				if (!path || storeToArr) uArr ~= new StrUndo(text, n, set);
3841				set(n);
3842			}
3843			if (path) { mixin(S_TRACE);
3844				if (_replMode && set && !storeToArr) store(path, text, n, set);
3845				size_t dmy = 0;
3846				addResult(path, dmy);
3847			}
3848			return true;
3849		}
3850		return false;
3851	}
3852	private bool replFilePath(string text, void delegate(string) set, ref size_t count, ref Undo[] uArr) { mixin(S_TRACE);
3853		auto c = fTextCount(encodePath(text));
3854		count += c;
3855		if (c > 0) { mixin(S_TRACE);
3856			if (_replMode) { mixin(S_TRACE);
3857				auto o = decodePath(text);
3858				string n = fTextRepl(o);
3859				uArr ~= new StrUndo(o, n, set);
3860				set(n);
3861			}
3862			return true;
3863		}
3864		return false;
3865	}
3866
3867	private bool replFlagName(F)(FlagDir parent, F flag, ref size_t count, ref Undo[] uArr) { mixin(S_TRACE);
3868		string text = flag.name;
3869		auto c = fTextCount(text);
3870		count += c;
3871		if (c > 0) { mixin(S_TRACE);
3872			if (_replMode) { mixin(S_TRACE);
3873				string oldPath = flag.path;
3874				string n = fTextRepl(text);
3875				uArr ~= new StrUndo(text, n, (string name) { mixin(S_TRACE);
3876					auto parent = flag.parent;
3877					if (parent) { mixin(S_TRACE);
3878						flag.name = parent.validName(name);
3879					} else { mixin(S_TRACE);
3880						flag.name = name;
3881					}
3882				});
3883				flag.name = parent.validName(n);
3884				_after ~= { mixin(S_TRACE);
3885					string newPath = flag.path;
3886					auto oldID = F.toID(oldPath);
3887					auto newID = F.toID(newPath);
3888					foreach (v; _summ.useCounter.values(oldID)) { mixin(S_TRACE);
3889						v.id = newID;
3890						storeID(null, v, oldID, newID, &v.id);
3891					}
3892				};
3893			}
3894			return true;
3895		}
3896		return false;
3897	}
3898
3899	private bool replRqCoupons(C)(CWXPath path, C targ, ref size_t count, ref Undo[] uArr, bool storeToArr = false) { mixin(S_TRACE);
3900		string[] coupons = targ.rCoupons;
3901		string[] old = coupons.dup;
3902		bool r = false;
3903		foreach (i, cp; coupons) { mixin(S_TRACE);
3904			Undo[] nArr;
3905			r |= repl(null, cp, (string t) {cp = t;}, count, nArr);
3906			if (_replMode) coupons[i] = cp;
3907		}
3908		if (r) { mixin(S_TRACE);
3909			if (_replMode) { mixin(S_TRACE);
3910				if (!path || storeToArr) uArr ~= new StrArrUndo(old, coupons.dup, &targ.rCoupons);
3911				targ.rCoupons = coupons;
3912			}
3913			if (path) { mixin(S_TRACE);
3914				if (_replMode && !storeToArr) store(path, old, coupons.dup, &targ.rCoupons);
3915				size_t dmy = 0;
3916				addResult(targ, dmy);
3917			}
3918			return true;
3919		}
3920		return false;
3921	}
3922
3923	private bool replKeyCode(C)(CWXPath path, C targ, ref size_t count, ref Undo[] uArr) { mixin(S_TRACE);
3924		if (_keyCodeSel) { mixin(S_TRACE);
3925			auto kcs = targ.keyCodes.dup;
3926			auto old = targ.keyCodes.dup;
3927			bool r = false;
3928			Undo[] nArr;
3929			foreach (i, kc; kcs) { mixin(S_TRACE);
3930				r |= repl(null, kc, (string t) {kc = t;}, count, nArr);
3931				if (_replMode) kcs[i] = kc;
3932			}
3933			if (r) { mixin(S_TRACE);
3934				if (_replMode) { mixin(S_TRACE);
3935					if (!path) uArr ~= new StrArrUndo(old, kcs.dup, &targ.keyCodes);
3936					targ.keyCodes = kcs;
3937				}
3938				if (path) { mixin(S_TRACE);
3939					if (_replMode) store(path, old, kcs.dup, &targ.keyCodes);
3940					size_t dmy = 0;
3941					addResult(path, dmy);
3942				}
3943				return true;
3944			}
3945		}
3946		return false;
3947	}
3948	private bool replFKeyCode(C)(CWXPath path, C targ, ref size_t count, ref Undo[] uArr) { mixin(S_TRACE);
3949		if (_keyCodeSel) { mixin(S_TRACE);
3950			auto kcs = targ.keyCodes.dup;
3951			auto old = targ.keyCodes.dup;
3952			bool r = false;
3953			Undo[] nArr;
3954			foreach (i, fkc; kcs) { mixin(S_TRACE);
3955				auto kc = _prop.sys.convFireKeyCode(fkc);
3956				r |= repl(null, kc, (string t) {kc = t;}, count, nArr);
3957				if (_replMode) kcs[i] = _prop.sys.toFKeyCode(kc);
3958			}
3959			if (r) { mixin(S_TRACE);
3960				if (_replMode) { mixin(S_TRACE);
3961					if (!path) uArr ~= new FKeyCodesUndo(old, kcs.dup, (FKeyCode[] fkc) {targ.keyCodes = fkc;});
3962					targ.keyCodes = kcs;
3963				}
3964				if (path) { mixin(S_TRACE)