1 #include "ide.h"
2 
3 struct OptionDisplay : Display {
PaintOptionDisplay4 	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink,
5 	                   Color paper, dword style) const
6 	{
7 		WString txt = q;
8 		w.DrawRect(r, paper);
9 		w.Clipoff(r.left + Zx(10), r.top, r.Width() - Zx(20), r.Height());
10 		int tcy = GetTLTextHeight(txt, StdFont());
11 		DrawTLText(w, 0, max((r.Height() - tcy) / 2, 0), r.Width(), txt, StdFont(), ink);
12 		w.End();
13 	}
GetStdSizeOptionDisplay14 	virtual Size GetStdSize(const Value& q) const
15 	{
16 		WString txt = q;
17 		Size tsz = GetTLTextSize(txt, StdFont());
18 		tsz.cx += Zx(20);
19 		return tsz;
20 	}
21 };
22 
23 struct OptionHeaderDisplay : Display {
PaintOptionHeaderDisplay24 	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink,
25 	                   Color paper, dword style) const
26 	{
27 		WString txt = q;
28 		w.DrawRect(r, AdjustIfDark(Color(255, 255, 204)));
29 		w.Clipoff(r.left + Zx(5), r.top, r.Width() - Zx(10), r.Height());
30 		int tcy = GetTLTextHeight(txt, StdFont().Bold());
31 		DrawTLText(w, 0, max((r.Height() - tcy) / 2, 0), r.Width(), txt,
32 		           StdFont().Bold(), SColorText());
33 		w.End();
34 	}
GetStdSizeOptionHeaderDisplay35 	virtual Size GetStdSize(const Value& q) const
36 	{
37 		WString txt = q;
38 		Size tsz = GetTLTextSize(txt, StdFont());
39 		tsz.cx += Zx(10);
40 		return tsz;
41 	}
42 };
43 
44 struct DependsDisplay : Display {
PaintDependsDisplay45 	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink,
46 	                   Color paper, dword style) const
47 	{
48 		WString txt = q;
49 		w.DrawRect(r, paper);
50 		w.Clipoff(r.left + Zx(10), r.top, r.Width() - Zx(20), r.Height());
51 		Image img = IdeFileImage(q, false, false);
52 		Size isz = img.GetSize();
53 		w.DrawImage(0, (r.Height() - isz.cy) / 2, img);
54 		int tcy = GetTLTextHeight(txt, StdFont());
55 		DrawTLText(w, isz.cx + Zx(4), max((r.Height() - tcy) / 2, 0), r.Width(), txt, StdFont(), ink);
56 		w.End();
57 	}
GetStdSizeDependsDisplay58 	virtual Size GetStdSize(const Value& q) const
59 	{
60 		WString txt = q;
61 		Size sz = GetTLTextSize(txt, StdFont());
62 		sz.cx += Zx(24);
63 		Size isz = IdeFileImage(q, false, false).GetSize();
64 		sz.cy = max(isz.cy, sz.cy);
65 		sz.cx += isz.cx;
66 		return sz;
67 	}
68 };
69 
70 struct UsesDisplay : Display {
PaintUsesDisplay71 	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink,
72 	                   Color paper, dword style) const
73 	{
74 		WString txt = q;
75 		w.DrawRect(r, paper);
76 		w.Clipoff(r.left + Zx(10), r.top, r.Width() - Zx(20), r.Height());
77 		Size isz = IdeImg::Package().GetSize();
78 		w.DrawImage(0, (r.Height() - isz.cy) / 2, IdeImg::Package());
79 		int tcy = GetTLTextHeight(txt, StdFont());
80 		DrawTLText(w, isz.cx + Zx(4), max((r.Height() - tcy) / 2, 0), r.Width(), txt, StdFont(), ink);
81 		w.End();
82 	}
GetStdSizeUsesDisplay83 	virtual Size GetStdSize(const Value& q) const
84 	{
85 		WString txt = q;
86 		Size sz = GetTLTextSize(txt, StdFont());
87 		sz.cx += Zx(24);
88 		Size isz = IdeImg::Package().GetSize();
89 		sz.cy = max(isz.cy, sz.cy);
90 		sz.cx += isz.cx;
91 		return sz;
92 	}
93 };
94 
FlagFilter(int c)95 int FlagFilter(int c) {
96 	return IsAlNum(c) || c == '_' || c == ' ' ? ToUpper(c) : 0;
97 }
98 
FlagFilterM(int c)99 int FlagFilterM(int c) {
100 	return c == '.' ? '.' : FlagFilter(c);
101 }
102 
CondFilter(int c)103 int CondFilter(int c) {
104 	return c == '!' || c == '(' || c == ')' || c == '&' || c == '|' ? c : FlagFilter(c);
105 }
106 
New()107 bool UsesDlg::New()
108 {
109 	String s = SelectPackage("Select package");
110 	text <<= s;
111 	return !IsNull(s);
112 }
113 
UsesDlg()114 UsesDlg::UsesDlg()
115 {
116 	CtrlLayoutOKCancel(*this, "Uses");
117 	when.SetFilter(CondFilter);
118 	text.SetDisplay(Single<UsesDisplay>());
119 	text.WhenPush = [=] { New(); };
120 }
121 
SaveOptions()122 void PackageEditor::SaveOptions() {
123 	if(!actualpackage.IsEmpty()) {
124 		actual.description = ~description;
125 		actual.ink = ~ink;
126 		actual.bold = ~bold;
127 		actual.italic = ~italic;
128 		actual.charset = (byte)(int)~charset;
129 		actual.tabsize = ~tabsize;
130 		actual.spellcheck_comments = ~spellcheck_comments;
131 		actual.accepts = Split(accepts.GetText().ToString(), ' ');
132 		actual.noblitz = noblitz;
133 		actual.nowarnings = nowarnings;
134 		if(IsActiveFile()) {
135 			Package::File& f = ActiveFile();
136 			f.pch = pch_file;
137 			f.nopch = nopch_file;
138 			f.noblitz = noblitz_file;
139 		}
140 		SavePackage();
141 	}
142 }
143 
Key(dword key,int count)144 bool PackageEditor::Key(dword key, int count)
145 {
146 	if(key == K_ESCAPE) {
147 		Close();
148 		return true;
149 	}
150 	return TopWindow::Key(key, count);
151 }
152 
Empty()153 void PackageEditor::Empty()
154 {
155 	FileEmpty();
156 	charset.Disable();
157 	tabsize.Disable();
158 	spellcheck_comments.Disable();
159 	noblitz.Disable();
160 	nowarnings.Disable();
161 	description.Disable();
162 	ink.Disable();
163 	italic.Disable();
164 	bold.Disable();
165 	filelist.Clear();
166 	filelist.Disable();
167 	option.Clear();
168 	option.Disable();
169 }
170 
FileEmpty()171 void PackageEditor::FileEmpty()
172 {
173 	fileoption.Clear();
174 	fileoption.Disable();
175 	pch_file = false;
176 	pch_file.Disable();
177 	nopch_file = false;
178 	nopch_file.Disable();
179 	noblitz_file = false;
180 	noblitz_file.Disable();
181 	includeable_file = false;
182 	includeable_file.Disable();
183 }
184 
OptionAdd(ArrayCtrl & option,int type,const char * title,const Array<OptItem> & o)185 void PackageEditor::OptionAdd(ArrayCtrl& option, int type, const char *title, const Array<OptItem>& o)
186 {
187 	if(o.GetCount() == 0)
188 		return;
189 	option.Add(-1, -1, type == INCLUDE ? "" : "when", title);
190 	option.SetDisplay(option.GetCount() - 1, 0, Single<OptionHeaderDisplay>());
191 	option.SetDisplay(option.GetCount() - 1, 1, Single<OptionHeaderDisplay>());
192 	for(int i = 0; i < o.GetCount(); i++) {
193 		option.Add(type, i, o[i].when, o[i].text);
194 		if(type == USES)
195 			option.SetDisplay(option.GetCount() - 1, 1, Single<UsesDisplay>());
196 		if(type == FILEDEPENDS)
197 			option.SetDisplay(option.GetCount() - 1, 1, Single<DependsDisplay>());
198 	}
199 }
200 
OptionAdd(int type,const char * title,const Array<OptItem> & o)201 void PackageEditor::OptionAdd(int type, const char *title, const Array<OptItem>& o)
202 {
203 	OptionAdd(option, type, title, o);
204 }
205 
PackageCursor()206 void PackageEditor::PackageCursor()
207 {
208 	WorkspaceWork::PackageCursor();
209 	if(IsNull(actualpackage))
210 		Empty();
211 	else {
212 		description <<= actual.description;
213 		ink <<= actual.ink;
214 		bold <<= actual.bold;
215 		italic <<= actual.italic;
216 		charset <<= (int)actual.charset;
217 		tabsize <<= actual.tabsize;
218 		spellcheck_comments <<= actual.spellcheck_comments;
219 		noblitz = actual.noblitz;
220 		nowarnings = actual.nowarnings;
221 		String s;
222 		for(int i = 0; i < actual.accepts.GetCount(); i++) {
223 			if(i) s << ' ';
224 			s << actual.accepts[i];
225 		}
226 		accepts <<= s.ToWString();
227 		description.Enable();
228 		ink.Enable();
229 		bold.Enable();
230 		italic.Enable();
231 		charset.Enable();
232 		tabsize.Enable();
233 		spellcheck_comments.Enable();
234 		noblitz.Enable();
235 		nowarnings.Enable();
236 		accepts.Enable();
237 		option.Enable();
238 		option.Clear();
239 		for(int i = FLAG; i <= PKG_LAST; i++)
240 			OptionAdd(i, opt_name[i], *opt[i]);
241 	}
242 }
243 
AdjustOptionCursor(ArrayCtrl & option)244 void PackageEditor::AdjustOptionCursor(ArrayCtrl& option)
245 {
246 	int q = option.GetCursor();
247 	if(q < 0)
248 		return;
249 	if((int)option.Get(q, 0) < 0 && q + 1 < option.GetCount())
250 		option.SetCursor(q + 1);
251 }
252 
AdjustPackageOptionCursor()253 void PackageEditor::AdjustPackageOptionCursor()
254 {
255 	AdjustOptionCursor(option);
256 }
257 
FindOpt(ArrayCtrl & option,int type,const String & when,const String & text)258 void PackageEditor::FindOpt(ArrayCtrl& option, int type, const String& when, const String& text)
259 {
260 	for(int i = 0; i < option.GetCount(); i++)
261 		if((int)option.Get(i, 0) == type &&
262 		   (String)option.Get(i, 2) == when && (String)option.Get(i, 3) == text) {
263 			option.SetCursor(i);
264 			option.SetFocus();
265 			break;
266 		 }
267 }
268 
FindOpt(ArrayCtrl & option,int type,int ii)269 void PackageEditor::FindOpt(ArrayCtrl& option, int type, int ii)
270 {
271 	for(int i = 0; i < option.GetCount(); i++)
272 		if((int)option.Get(i, 0) == type && (int)option.Get(i, 1) == ii) {
273 			option.SetCursor(i);
274 			option.SetFocus();
275 			break;
276 		 }
277 }
278 
SetOpt(ArrayCtrl & opt,int type,OptItem & m,const String & when,const String & text)279 void PackageEditor::SetOpt(ArrayCtrl& opt, int type, OptItem& m, const String& when, const String& text)
280 {
281 	m.when = when;
282 	m.text = text;
283 	SaveLoadPackage();
284 	FindOpt(opt, type, when, text);
285 }
286 
FlagFilterR(int c)287 int FlagFilterR(int c)
288 {
289 	return c == '-' ? c : FlagFilter(c);
290 }
291 
Prepare(WithUppOptDlg<TopWindow> & dlg,int type)292 void PackageEditor::Prepare(WithUppOptDlg<TopWindow>& dlg, int type)
293 {
294 	CtrlLayoutOKCancel(dlg, opt_name[type]);
295 	dlg.when.SetFilter(CondFilter);
296 	dlg.when.Enable(type != INCLUDE);
297 	if(type == FLAG) {
298 		dlg.text.SetFilter(FlagFilterR);
299 		dlg.info.SetLabel("Use '-' prefix to remove the flag");
300 	}
301 }
302 
AddOption(int type)303 void PackageEditor::AddOption(int type)
304 {
305 	if(IsNull(actualpackage))
306 		return;
307 	if(type == USES) {
308 		UsesDlg dlg;
309 		if(dlg.New() && dlg.Run() == IDOK)
310 			SetOpt(option, USES, actual.uses.Add(), ~dlg.when, ~dlg.text);
311 		return;
312 	}
313 	WithUppOptDlg<TopWindow> dlg;
314 	Prepare(dlg, type);
315 	if(dlg.Run() != IDOK)
316 		return;
317 	SetOpt(option, type, opt[type]->Add(), ~dlg.when, ~dlg.text);
318 }
319 
EditOption(bool duplicate)320 void PackageEditor::EditOption(bool duplicate)
321 {
322 	if(!option.IsCursor() || IsNull(actualpackage))
323 		return;
324 	int type = option.Get(0);
325 	if(type == USES) {
326 		Array<OptItem>& m = *opt[type];
327 		int i = option.Get(1);
328 		if(i >= 0 && i < m.GetCount()) {
329 			UsesDlg dlg;
330 			if(duplicate)
331 				dlg.Title(GetTitle().ToString() + " - duplicate");
332 			dlg.when <<= m[i].when;
333 			dlg.text <<= m[i].text;
334 			if(dlg.Run() == IDOK)
335 				SetOpt(option, USES, duplicate ? actual.uses.Add() : m[i], ~dlg.when, ~dlg.text);
336 		}
337 		return;
338 	}
339 	if(type >= FLAG && type <= PKG_LAST) {
340 		Array<OptItem>& m = *opt[type];
341 		int i = option.Get(1);
342 		if(i >= 0 && i < m.GetCount()) {
343 			WithUppOptDlg<TopWindow> dlg;
344 			Prepare(dlg, type);
345 			if(duplicate)
346 				dlg.Title(GetTitle().ToString() + " - duplicate");
347 			dlg.when <<= m[i].when;
348 			dlg.text <<= m[i].text;
349 			if(dlg.Run() != IDOK)
350 				return;
351 			SetOpt(option, type, duplicate ? opt[type]->Add() : m[i], ~dlg.when, ~dlg.text);
352 		}
353 	}
354 }
355 
RemoveOption()356 void PackageEditor::RemoveOption()
357 {
358 	if(!option.IsCursor() || IsNull(actualpackage))
359 		return;
360 	int type = option.Get(0);
361 	if(type >= FLAG && type <= PKG_LAST) {
362 		Array<OptItem>& m = *opt[type];
363 		int i = option.Get(1);
364 		if(i >= 0 && i < m.GetCount())
365 			m.Remove(i);
366 		SaveLoadPackage();
367 	}
368 }
369 
MoveOption(int d)370 void PackageEditor::MoveOption(int d)
371 {
372 	if(!option.IsCursor() || IsNull(actualpackage))
373 		return;
374 	int type = option.Get(0);
375 	if(type >= FLAG && type <= PKG_LAST) {
376 		Array<OptItem>& m = *opt[type];
377 		int i = option.Get(1);
378 		if(min(i, i + d) >= 0 && max(i, i + d) < m.GetCount()) {
379 			Swap(m[i], m[i + d]);
380 			SaveLoadPackage();
381 			FindOpt(option, type, i + d);
382 		}
383 	}
384 }
385 
OptionMenu(Bar & bar)386 void PackageEditor::OptionMenu(Bar& bar)
387 {
388 	bool b = !IsNull(actualpackage);
389 	bar.Add(b, "Add package..", IdeImg::package_add(), THISBACK1(AddOption, USES));
390 	for(int j = FLAG; j <= PKG_LAST; j++)
391 		if(j != USES)
392 			bar.Add(b, "New " + opt_name[j] + "..", THISBACK1(AddOption, j));
393 	bar.Separator();
394 	b = option.IsCursor() && (int)option.Get(0) >= 0;
395 	bar.Add(b, "Edit..", [=] { EditOption(false); })
396 		.Key(K_CTRL_ENTER);
397 	bar.Add(b, "Duplicate..", [=] { EditOption(true); })
398 	   .Key(K_CTRL_D);
399 	bar.Add(b, "Remove", THISBACK(RemoveOption))
400 	   .Key(K_DELETE);
401 	bar.Separator();
402 	int type = option.IsCursor() ? (int)option.Get(0) : -1;
403 	int i = -1;
404 	Array<OptItem> *m = NULL;
405 	if(type >= FLAG && type <= PKG_LAST) {
406 		m = opt[type];
407 		i = option.Get(1);
408 	}
409 	bar.Add(i >= 0 && min(i, i - 1) >= 0,
410 	        "Move up", THISBACK1(MoveOption, -1))
411 	   .Key(K_CTRL_UP);
412 	bar.Add(m && i >= 0 && max(i, i + 1) < m->GetCount(),
413 	        "Move down", THISBACK1(MoveOption, 1))
414 	   .Key(K_CTRL_DOWN);
415 }
416 
FileCursor()417 void PackageEditor::FileCursor()
418 {
419 	WorkspaceWork::FileCursor();
420 	if(IsActiveFile()) {
421 		Package::File& f = ActiveFile();
422 		if(!f.separator) {
423 			String p = GetActiveFilePath();
424 			String ext = ToLower(GetFileExt(p));
425 			bool tpp = ext == ".tpp" && IsFolder(p);
426 			bool hdr = IsHeaderExt(ext) && !tpp;
427 			pch_file.Enable(hdr);
428 			pch_file <<= f.pch;
429 			nopch_file.Enable(!hdr);
430 			nopch_file <<= f.nopch;
431 			noblitz_file.Enable(!tpp);
432 			noblitz_file <<= f.noblitz;
433 			includeable_file.Enable(tpp);
434 			includeable_file <<= FileExists(AppendFileName(p, "all.i"));
435 			fileoption.Enable();
436 			fileoption.Clear();
437 			OptionAdd(fileoption, FILEOPTION, "Additional compiler options for the file",
438 			          f.option);
439 			OptionAdd(fileoption, FILEDEPENDS, "Additional dependencies for the file",
440 			          f.depends);
441 			return;
442 		}
443 	}
444 	FileEmpty();
445 }
446 
AdjustFileOptionCursor()447 void PackageEditor::AdjustFileOptionCursor()
448 {
449 	AdjustOptionCursor(fileoption);
450 }
451 
FileOptionMenu(Bar & bar)452 void PackageEditor::FileOptionMenu(Bar& bar)
453 {
454 	bool b = IsActiveFile();
455 	bar.Add(b, "Add compiler flags..", THISBACK(AddFileOption)).Key(K_INSERT);
456 	bar.Add(b, "Add dependence..", THISBACK1(AddDepends, false)).Key(K_CTRL_INSERT);
457 	bar.Add(b, "Add external dependence..", THISBACK1(AddDepends, true)).Key(K_SHIFT_INSERT);
458 	bar.Separator();
459 	b = fileoption.IsCursor() && (int)fileoption.Get(0) >= 0;
460 	int type = b ? (int)fileoption.Get(0) : -1;
461 	bar.Add(b, "Edit..", THISBACK(EditFileOption)).Key(K_CTRL_ENTER);
462 	bar.Add(b, "Remove", THISBACK(RemoveFileOption)).Key(K_DELETE);
463 	bar.Separator();
464 	int i = -1;
465 	Array<OptItem> *m = NULL;
466 	if(type >= 0) {
467 		m = type == FILEDEPENDS ? &ActiveFile().depends : &ActiveFile().option;
468 		i = fileoption.Get(1);
469 	}
470 	bar.Add(i >= 0 && min(i, i - 1) >= 0,
471 	        "Move up", THISBACK1(MoveFileOption, -1))
472 	   .Key(K_CTRL_UP);
473 	bar.Add(m && i >= 0 && max(i, i + 1) < m->GetCount(),
474 	        "Move down", THISBACK1(MoveFileOption, 1))
475 	   .Key(K_CTRL_DOWN);
476 }
477 
MoveFileOption(int d)478 void PackageEditor::MoveFileOption(int d)
479 {
480 	if(!fileoption.IsCursor() || !IsActiveFile())
481 		return;
482 	int type = fileoption.Get(0);
483 	if(type < 0)
484 		return;
485 	Array<OptItem>& m = type == FILEDEPENDS ? ActiveFile().depends : ActiveFile().option;
486 	int i = fileoption.Get(1);
487 	if(min(i, i + d) >= 0 && max(i, i + d) < m.GetCount()) {
488 		Swap(m[i], m[i + d]);
489 		SaveLoadPackage();
490 		FindOpt(fileoption, type, i + d);
491 	}
492 }
493 
New()494 void DependsDlg::New()
495 {
496 	FileSel *fs;
497 	if(!IsNull(package)) {
498 		fs = &BasedSourceFs();
499 		fs->BaseDir(GetFileFolder(PackagePath(package)));
500 		fs->Multi(false);
501 	}
502 	else {
503 		fs = &OutputFs();
504 		fs->Multi(false);
505 	}
506 	if(fs->ExecuteOpen("Additional file dependency"))
507 		text <<= ~*fs;
508 	fs->Multi();
509 }
510 
DependsDlg()511 DependsDlg::DependsDlg()
512 {
513 	CtrlLayoutOKCancel(*this, "Additional file dependency");
514 	when.SetFilter(CondFilter);
515 	text.SetDisplay(Single<DependsDisplay>());
516 	text.WhenPush = THISBACK(New);
517 }
518 
AddDepends(bool extdep)519 void PackageEditor::AddDepends(bool extdep)
520 {
521 	if(!IsActiveFile())
522 		return;
523 	DependsDlg dlg;
524 	if(!extdep)
525 		dlg.package = GetActivePackage();
526 	dlg.New();
527 	if(dlg.Run() == IDOK)
528 		SetOpt(fileoption, FILEDEPENDS, ActiveFile().depends.Add(), ~dlg.when, ~dlg.text);
529 }
530 
AddFileOption()531 void PackageEditor::AddFileOption()
532 {
533 	if(!IsActiveFile())
534 		return;
535 	WithUppOptDlg<TopWindow> dlg;
536 	CtrlLayoutOKCancel(dlg, "Compiler options for the file");
537 	dlg.when.SetFilter(CondFilter);
538 	if(dlg.Run() == IDOK)
539 		SetOpt(fileoption, FILEDEPENDS, ActiveFile().option.Add(), ~dlg.when, ~dlg.text);
540 }
541 
EditFileOption()542 void PackageEditor::EditFileOption()
543 {
544 	if(!IsActiveFile() || !fileoption.IsCursor())
545 		return;
546 	int ii = (int)fileoption.Get(1);
547 	Package::File& f = ActiveFile();
548 	if(ii < 0 || ii >= f.option.GetCount())
549 		return;
550 	OptItem& m = f.option[(int)fileoption.Get(1)];
551 	WithUppOptDlg<TopWindow> dlg;
552 	CtrlLayoutOKCancel(dlg, "Compiler options for the file");
553 	dlg.when.SetFilter(CondFilter);
554 	dlg.when <<= m.when;
555 	dlg.text <<= m.text;
556 	if(dlg.Run() != IDOK)
557 		return;
558 	m.when = ~dlg.when;
559 	m.text = ~dlg.text;
560 	SaveLoadPackage();
561 	FindOpt(fileoption, FILEOPTION, ~dlg.when, ~dlg.text);
562 }
563 
RemoveFileOption()564 void PackageEditor::RemoveFileOption()
565 {
566 	if(!IsActiveFile() || !fileoption.IsCursor())
567 		return;
568 	int ii = (int)fileoption.Get(1);
569 	Package::File& f = ActiveFile();
570 	int type = fileoption.Get(0);
571 	if(type == FILEOPTION && ii >= 0 && ii < f.option.GetCount())
572 		f.option.Remove(ii);
573 	if(type == FILEDEPENDS && ii >= 0 && ii < f.depends.GetCount())
574 		f.depends.Remove(ii);
575 	SaveLoadPackage();
576 }
577 
Serialize(Stream & s)578 void PackageEditor::Serialize(Stream& s) {
579 	int version = 3;
580 	s / version;
581 	if(version >= 3) {
582 		filelist.SerializeSettings(s);
583 		package.SerializeSettings(s);
584 	}
585 	else {
586 		s % filelist;
587 		s % package % package;
588 	}
589 	SerializePlacement(s);
590 	if(version >= 1 && version <= 2) {
591 		Splitter dummy;
592 		s % dummy % dummy % dummy % dummy % dummy % dummy;
593 	}
594 }
595 
Add(const char * name,Array<OptItem> & m)596 void PackageEditor::Add(const char *name, Array<OptItem>& m)
597 {
598 	opt.Add(&m);
599 	opt_name.Add(name);
600 }
601 
Init(ArrayCtrl & option)602 void PackageEditor::Init(ArrayCtrl& option)
603 {
604 	option.AddIndex();
605 	option.AddIndex();
606 	option.AddColumn("").SetDisplay(Single<OptionDisplay>()).Margin(0);
607 	option.AddColumn("", 2).SetDisplay(Single<OptionDisplay>()).Margin(0);
608 	option.NoHeader();
609 	option.SetLineCy(max(IdeImg::Package().GetSize().cy, Draw::GetStdFontCy()));
610 }
611 
SaveOptionsLoad()612 void PackageEditor::SaveOptionsLoad()
613 {
614 	SaveOptions();
615 	SaveLoadPackage();
616 }
617 
Description()618 void PackageEditor::Description()
619 {
620 	WithDescriptionLayout<TopWindow> dlg;
621 	CtrlLayoutOKCancel(dlg, "Package description");
622 	dlg.text <<= ~description;
623 	if(dlg.Run() != IDOK)
624 		return;
625 	description <<= ~dlg.text;
626 	SaveOptions();
627 }
628 
PackageEditor()629 PackageEditor::PackageEditor()
630 {
631 	organizer = true;
632 	CtrlLayoutOKCancel(*this, "Package organizer");
633 	description.Disable();
634 	description <<= THISBACK(Description);
635 
636 	spellcheck_comments.Add(Null, "Default");
637 	DlSpellerLangs(spellcheck_comments);
638 	DlCharsetD(charset);
639 	charset.Disable();
640 	filelist.Disable();
641 	spellcheck_comments.Disable();
642 	accepts.SetFilter(FlagFilter);
643 	accepts ^= spellcheck_comments ^= charset ^= tabsize ^= THISFN(SaveOptions);
644 	noblitz <<=
645 	nowarnings <<=
646 	pch_file <<=
647 	nopch_file <<=
648 	noblitz_file <<= THISBACK(SaveOptionsLoad);
649 
650 	includeable_file <<= THISBACK(ToggleIncludeable);
651 
652 	Add("Add/remove flags", actual.flag);
653 	Add("Uses", actual.uses);
654 	Add("Targets", actual.target);
655 	Add("Libraries", actual.library);
656 	Add("Static libraries", actual.static_library);
657 	Add("Link options", actual.link);
658 	Add("Compiler options", actual.option);
659 	Add("Internal includes", actual.include);
660 	Add("pkg-config", actual.pkg_config);
661 
662 	Init(option);
663 	option.WhenCursor = THISBACK(AdjustPackageOptionCursor);
664 	option.WhenBar = THISBACK(OptionMenu);
665 	option.WhenLeftDouble << [=] { EditOption(false); };
666 
667 	Init(fileoption);
668 	fileoption.WhenCursor = THISBACK(AdjustFileOptionCursor);
669 	fileoption.WhenBar = THISBACK(FileOptionMenu);
670 	fileoption.WhenLeftDouble = THISBACK(EditFileOption);
671 
672 	ink.NullText("(std)");
673 	ink <<=
674 	bold <<=
675 	italic <<= THISBACK(SaveOptionsLoad);
676 
677 	FileCursor();
678 }
679 
EditPackages(const char * main,const char * startwith,String & cfg)680 void EditPackages(const char *main, const char *startwith, String& cfg) {
681 	InvalidatePackageCache();
682 	PackageEditor pe;
683 	pe.Sizeable();
684 	StringStream in(cfg);
685 	pe.Serialize(in);
686 	pe.SetMain(main);
687 	pe.ScanWorkspace();
688 	pe.SyncWorkspace();
689 	pe.FindSetPackage(startwith);
690 	if(pe.Run() != IDOK)
691 		pe.RestoreBackup();
692 	StringStream out;
693 	pe.Serialize(out);
694 	cfg = out;
695 }
696