1 /*
2   KeePass Password Safe - The Open-Source Password Manager
3   Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 
20 using System;
21 using System.Collections.Generic;
22 using System.ComponentModel;
23 using System.Diagnostics;
24 using System.Drawing;
25 using System.Text;
26 using System.Windows.Forms;
27 
28 using KeePass.App;
29 using KeePass.App.Configuration;
30 using KeePass.Resources;
31 using KeePass.UI;
32 using KeePass.Util;
33 
34 using KeePassLib;
35 
36 namespace KeePass.Forms
37 {
38 	public partial class AutoTypeCtxForm : Form
39 	{
40 		private List<AutoTypeCtx> m_lCtxs = null;
41 		private ImageList m_ilIcons = null;
42 
43 		private string m_strInitialFormRect = string.Empty;
44 		private string m_strInitialColWidths = string.Empty;
45 		private int m_nBannerWidth = -1;
46 		private bool m_bCanShowPasswords = true;
47 
48 		private CustomContextMenuStripEx m_ctxTools = null;
49 		private ToolStripMenuItem m_tsmiColumns = null;
50 
51 		private AutoTypeCtx m_atcSel = null;
52 		public AutoTypeCtx SelectedCtx
53 		{
54 			get { return m_atcSel; }
55 		}
56 
InitEx(List<AutoTypeCtx> lCtxs, ImageList ilIcons)57 		public void InitEx(List<AutoTypeCtx> lCtxs, ImageList ilIcons)
58 		{
59 			m_lCtxs = lCtxs;
60 			m_ilIcons = UIUtil.CloneImageList(ilIcons, true);
61 		}
62 
AutoTypeCtxForm()63 		public AutoTypeCtxForm()
64 		{
65 			InitializeComponent();
66 			GlobalWindowManager.InitializeForm(this);
67 		}
68 
OnFormLoad(object sender, EventArgs e)69 		private void OnFormLoad(object sender, EventArgs e)
70 		{
71 			Size sz = this.ClientSize;
72 			this.MinimumSize = new Size((int)(0.949f * (float)sz.Width),
73 				(int)(0.824f * (float)sz.Height));
74 
75 			GlobalWindowManager.AddWindow(this);
76 
77 			Debug.Assert(!m_lblText.AutoSize); // For RTL support
78 			m_lblText.Text = KPRes.AutoTypeEntrySelectionDescLong2;
79 
80 			this.Text = KPRes.AutoTypeEntrySelection;
81 			this.Icon = AppIcons.Default;
82 
83 			m_strInitialFormRect = UIUtil.SetWindowScreenRectEx(this,
84 				Program.Config.UI.AutoTypeCtxRect);
85 
86 			UIUtil.SetExplorerTheme(m_lvItems, true);
87 
88 			if(m_ilIcons != null) m_lvItems.SmallImageList = m_ilIcons;
89 			else { Debug.Assert(false); m_ilIcons = new ImageList(); }
90 
91 			m_bCanShowPasswords = AppPolicy.Current.UnhidePasswords;
92 
93 			RecreateEntryList();
94 
95 			string strColWidths = Program.Config.UI.AutoTypeCtxColumnWidths;
96 			if(strColWidths.Length > 0) UIUtil.SetColumnWidths(m_lvItems, strColWidths);
97 			m_strInitialColWidths = UIUtil.GetColumnWidths(m_lvItems);
98 
99 			ProcessResize();
100 			BringToFront();
101 			Activate();
102 			UIUtil.SetFocus(m_lvItems, this, true);
103 		}
104 
RecreateEntryList()105 		private void RecreateEntryList()
106 		{
107 			long lFlags = Program.Config.UI.AutoTypeCtxFlags;
108 
109 			if(!m_bCanShowPasswords)
110 				lFlags &= ~(long)AceAutoTypeCtxFlags.ColPassword;
111 
112 			UIUtil.CreateEntryList(m_lvItems, m_lCtxs, (AceAutoTypeCtxFlags)lFlags,
113 				m_ilIcons);
114 		}
115 
OnFormClosed(object sender, FormClosedEventArgs e)116 		private void OnFormClosed(object sender, FormClosedEventArgs e)
117 		{
118 			CleanUpEx();
119 			GlobalWindowManager.RemoveWindow(this);
120 		}
121 
CleanUpEx()122 		private void CleanUpEx()
123 		{
124 			string strColWidths = UIUtil.GetColumnWidths(m_lvItems);
125 			if(strColWidths != m_strInitialColWidths)
126 				Program.Config.UI.AutoTypeCtxColumnWidths = strColWidths;
127 
128 			string strRect = UIUtil.GetWindowScreenRect(this);
129 			if(strRect != m_strInitialFormRect) // Don't overwrite ""
130 				Program.Config.UI.AutoTypeCtxRect = strRect;
131 
132 			DestroyToolsContextMenu();
133 
134 			if(m_ilIcons != null)
135 			{
136 				m_lvItems.SmallImageList = null; // Detach event handlers
137 				m_ilIcons.Dispose();
138 				m_ilIcons = null;
139 			}
140 		}
141 
ProcessResize()142 		private void ProcessResize()
143 		{
144 			if(m_lCtxs == null) return; // TrlUtil or design mode
145 
146 			string strSub = KPRes.AutoTypeEntrySelectionDescShort;
147 			int n = m_lCtxs.Count;
148 			if(n == 1) strSub = KPRes.SearchEntriesFound1 + ".";
149 			else if(n <= 0)
150 			{
151 				strSub = KPRes.SearchEntriesFound + ".";
152 				strSub = strSub.Replace(@"{PARAM}", "0");
153 			}
154 
155 			BannerFactory.UpdateBanner(this, m_bannerImage,
156 				Properties.Resources.B48x48_KGPG_Key2, KPRes.AutoTypeEntrySelection,
157 				strSub, ref m_nBannerWidth);
158 		}
159 
GetSelectedEntry()160 		private bool GetSelectedEntry()
161 		{
162 			ListView.SelectedListViewItemCollection slvic = m_lvItems.SelectedItems;
163 			if(slvic.Count == 1)
164 			{
165 				m_atcSel = (slvic[0].Tag as AutoTypeCtx);
166 				return (m_atcSel != null);
167 			}
168 
169 			return false;
170 		}
171 
ProcessItemSelection()172 		private void ProcessItemSelection()
173 		{
174 			if(this.DialogResult == DialogResult.OK) return; // Already closing
175 
176 			if(GetSelectedEntry()) this.DialogResult = DialogResult.OK;
177 		}
178 
OnListItemActivate(object sender, EventArgs e)179 		private void OnListItemActivate(object sender, EventArgs e)
180 		{
181 			ProcessItemSelection();
182 		}
183 
184 		// The item activation handler has a slight delay when clicking an
185 		// item, thus as a performance optimization we additionally handle
186 		// item clicks
OnListClick(object sender, EventArgs e)187 		private void OnListClick(object sender, EventArgs e)
188 		{
189 			ProcessItemSelection();
190 		}
191 
OnFormResize(object sender, EventArgs e)192 		private void OnFormResize(object sender, EventArgs e)
193 		{
194 			ProcessResize();
195 		}
196 
DestroyToolsContextMenu()197 		private void DestroyToolsContextMenu()
198 		{
199 			if(m_ctxTools == null) return;
200 
201 			foreach(ToolStripItem tsi in m_tsmiColumns.DropDownItems)
202 				tsi.Click -= this.OnToggleColumn;
203 
204 			m_tsmiColumns = null;
205 			m_ctxTools.Dispose();
206 			m_ctxTools = null;
207 		}
208 
RecreateToolsContextMenu()209 		private void RecreateToolsContextMenu()
210 		{
211 			DestroyToolsContextMenu();
212 
213 			m_ctxTools = new CustomContextMenuStripEx();
214 			m_tsmiColumns = new ToolStripMenuItem(KPRes.Columns);
215 			m_ctxTools.Items.Add(m_tsmiColumns);
216 
217 			long lFlags = Program.Config.UI.AutoTypeCtxFlags;
218 
219 			ToolStripMenuItem tsmi = new ToolStripMenuItem(KPRes.Title);
220 			UIUtil.SetChecked(tsmi, true);
221 			tsmi.Tag = AceAutoTypeCtxFlags.ColTitle;
222 			tsmi.Click += this.OnToggleColumn;
223 			tsmi.Enabled = false;
224 			m_tsmiColumns.DropDownItems.Add(tsmi);
225 
226 			tsmi = new ToolStripMenuItem(KPRes.UserName);
227 			UIUtil.SetChecked(tsmi, ((lFlags & (long)AceAutoTypeCtxFlags.ColUserName) != 0));
228 			tsmi.Tag = AceAutoTypeCtxFlags.ColUserName;
229 			tsmi.Click += this.OnToggleColumn;
230 			m_tsmiColumns.DropDownItems.Add(tsmi);
231 
232 			tsmi = new ToolStripMenuItem(KPRes.Password);
233 			UIUtil.SetChecked(tsmi, (((lFlags & (long)AceAutoTypeCtxFlags.ColPassword) != 0) &&
234 				m_bCanShowPasswords));
235 			tsmi.Tag = AceAutoTypeCtxFlags.ColPassword;
236 			tsmi.Click += this.OnToggleColumn;
237 			if(!m_bCanShowPasswords) tsmi.Enabled = false;
238 			m_tsmiColumns.DropDownItems.Add(tsmi);
239 
240 			tsmi = new ToolStripMenuItem(KPRes.Url);
241 			UIUtil.SetChecked(tsmi, ((lFlags & (long)AceAutoTypeCtxFlags.ColUrl) != 0));
242 			tsmi.Tag = AceAutoTypeCtxFlags.ColUrl;
243 			tsmi.Click += this.OnToggleColumn;
244 			m_tsmiColumns.DropDownItems.Add(tsmi);
245 
246 			tsmi = new ToolStripMenuItem(KPRes.Notes);
247 			UIUtil.SetChecked(tsmi, ((lFlags & (long)AceAutoTypeCtxFlags.ColNotes) != 0));
248 			tsmi.Tag = AceAutoTypeCtxFlags.ColNotes;
249 			tsmi.Click += this.OnToggleColumn;
250 			m_tsmiColumns.DropDownItems.Add(tsmi);
251 
252 			tsmi = new ToolStripMenuItem(KPRes.Sequence + " - " + KPRes.Comments);
253 			UIUtil.SetChecked(tsmi, ((lFlags & (long)AceAutoTypeCtxFlags.ColSequenceComments) != 0));
254 			tsmi.Tag = AceAutoTypeCtxFlags.ColSequenceComments;
255 			tsmi.Click += this.OnToggleColumn;
256 			m_tsmiColumns.DropDownItems.Add(tsmi);
257 
258 			tsmi = new ToolStripMenuItem(KPRes.Sequence);
259 			UIUtil.SetChecked(tsmi, ((lFlags & (long)AceAutoTypeCtxFlags.ColSequence) != 0));
260 			tsmi.Tag = AceAutoTypeCtxFlags.ColSequence;
261 			tsmi.Click += this.OnToggleColumn;
262 			m_tsmiColumns.DropDownItems.Add(tsmi);
263 		}
264 
OnToggleColumn(object sender, EventArgs e)265 		private void OnToggleColumn(object sender, EventArgs e)
266 		{
267 			ToolStripMenuItem tsmi = (sender as ToolStripMenuItem);
268 			if(tsmi == null) { Debug.Assert(false); return; }
269 
270 			AceAutoTypeCtxFlags f = (AceAutoTypeCtxFlags)tsmi.Tag;
271 			long lFlags = Program.Config.UI.AutoTypeCtxFlags;
272 
273 			lFlags ^= (long)f;
274 			lFlags |= (long)AceAutoTypeCtxFlags.ColTitle; // Enforce title
275 
276 			Program.Config.UI.AutoTypeCtxFlags = lFlags;
277 			RecreateEntryList();
278 		}
279 
OnBtnTools(object sender, EventArgs e)280 		private void OnBtnTools(object sender, EventArgs e)
281 		{
282 			RecreateToolsContextMenu();
283 			m_ctxTools.ShowEx(m_btnTools);
284 		}
285 	}
286 }
287