1 /*
2 FXiTe - The Free eXtensIble Text Editor
3 Copyright (c) 2009-2013 Jeffrey Pohlmeyer <yetanothergeek@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License version 3 as
7 published by the Free Software Foundation.
8
9 This software is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <fx.h>
20 #include <fxkeys.h>
21
22 #ifdef WIN32
23 # include <windows.h>
24 #endif
25
26 #include "appwin.h"
27 #include "menuspec.h"
28 #include "intl.h"
29
30 #include "cmd_utils.h"
31
32
33 static const char* dont_freeze_me = "don't taze me, bro!";
34
35
Freeze(FXWindow * win,bool frozen)36 void CommandUtils::Freeze(FXWindow*win, bool frozen)
37 {
38 FXWindow*w;
39 for (w=win->getFirst(); w; w=w->getNext()) {
40 if (w->getUserData()==dont_freeze_me) { continue; }
41 if (frozen) {
42 w->disable();
43 w->repaint();
44 } else {w->enable();}
45 Freeze(w,frozen);
46 }
47 }
48
49
50
DontFreezeMe()51 const char* CommandUtils::DontFreezeMe()
52 {
53 return dont_freeze_me;
54 }
55
56
57
SetKillKey(FXHotKey k)58 void CommandUtils::SetKillKey(FXHotKey k)
59 {
60 killkey=k;
61 #ifdef WIN32
62 winkey=VkKeyScan(FXSELID(killkey));
63 #endif
64 }
65
66
67
InitKillKey()68 void CommandUtils::InitKillKey()
69 {
70 MenuSpec*killcmd=MenuMgr::LookupMenu(TopWindow::ID_KILL_COMMAND);
71 SetKillKey(parseAccel(killcmd->accel));
72 if (killkey && FXSELID(killkey)) {
73 temp_accels=new FXAccelTable();
74 temp_accels->addAccel(killkey,this,FXSEL(SEL_COMMAND,TopWindow::ID_KILL_COMMAND),0);
75 } else {
76 FXMessageBox::warning(tw->getApp(), MBOX_OK, _("Configuration error"),
77 "%s \"%s\"\n%s",
78 _("Failed to parse accelerator for"),
79 killcmd->pref,
80 _("disabling support for macros and external commands.")
81 );
82 temp_accels=NULL;
83 }
84 }
85
86
87
CommandUtils(TopWindowBase * win)88 CommandUtils::CommandUtils(TopWindowBase*win)
89 {
90 saved_accels=NULL;
91 temp_accels=NULL;
92 command_busy=false;
93 tw=(TopWindow*)win;
94 app=tw->getApp();
95 InitKillKey();
96 }
97
98
99
~CommandUtils()100 CommandUtils::~CommandUtils()
101 {
102 delete temp_accels;
103 delete saved_accels;
104 }
105
106
107
SetKillCommandAccelKey(FXHotKey acckey)108 void CommandUtils::SetKillCommandAccelKey(FXHotKey acckey)
109 {
110 SetKillKey(acckey);
111 delete temp_accels;
112 temp_accels=new FXAccelTable();
113 temp_accels->addAccel(acckey,this,FXSEL(SEL_COMMAND,TopWindow::ID_KILL_COMMAND),0);
114 }
115
116
117
DisableUI(bool disabled)118 void CommandUtils::DisableUI(bool disabled)
119 {
120 if (tw->Destroying()) { return; }
121 if (disabled) {
122 saved_accels=tw->getAccelTable();
123 tw->setAccelTable(temp_accels);
124 temp_accels=NULL;
125 } else {
126 temp_accels=tw->getAccelTable();
127 tw->setAccelTable(saved_accels);
128 saved_accels=NULL;
129 }
130 CommandUtils::Freeze(tw,disabled);
131 }
132
133
134
IsCommandReady()135 bool CommandUtils::IsCommandReady()
136 {
137 if (command_busy) {
138 FXMessageBox::error(tw, MBOX_OK, _("Command error"),
139 _("Multiple commands cannot be executed at the same time."));
140 return false;
141 }
142 if (!temp_accels) {
143 FXMessageBox::error(tw, MBOX_OK, _("Command support disabled"),
144 _("Support for running macros and external commands has been\n"
145 "disabled, because the interrupt key sequence is invalid.\n\n"
146 "To fix this, go to:\n"
147 " Edit->Preferences->Keybindings\n"
148 "and enter a valid setting for \"%s\""),
149 MenuMgr::LookupMenu(TopWindow::ID_KILL_COMMAND)->pref
150 );
151 return false;
152 }
153 return true;
154 }
155
156
157
SetShellEnv(const char * file,long line)158 void CommandUtils::SetShellEnv(const char*file, long line)
159 {
160 char linenum[8]="\0\0\0\0\0\0\0";
161 snprintf(linenum,sizeof(linenum)-1, "%ld", line+1);
162 #ifdef WIN32
163 FXSystem::setEnvironment("l",linenum);
164 FXSystem::setEnvironment("f",file);
165 #else
166 setenv("l",linenum,1);
167 setenv("f",file,1);
168 #endif
169 }
170
171
172
FixUpCmdLineEnv(const FXString & command)173 const FXString CommandUtils::FixUpCmdLineEnv(const FXString&command)
174 {
175 #ifdef WIN32
176 FXString cmd=command;
177 cmd.substitute("%F%", FXSystem::getEnvironment("f"), true);
178 cmd.substitute("%f%", FXSystem::getEnvironment("f"), true);
179 cmd.substitute("%L%", FXSystem::getEnvironment("l"), true);
180 cmd.substitute("%l%", FXSystem::getEnvironment("l"), true);
181 return cmd;
182 #else
183 return command;
184 #endif
185 }
186
187
188
189 #ifdef WIN32
190 # define kill_key_down() ( GetKeyState(winkey) & 0x8000 )
191 # define ctrl_key_down() ( GetKeyState(VK_CONTROL) & 0x8000 )
192 # define alt_key_down() ( GetKeyState(VK_MENU) & 0x8000 )
193 # define shift_key_down() ( GetKeyState(VK_SHIFT) & 0x8000 )
194 #else
195 # define kill_key_down() ( app->getKeyState(FXSELID(killkey)) )
196 # define ctrl_key_down() ( app->getKeyState(KEY_Control_L) || app->getKeyState(KEY_Control_R) )
197 # define alt_key_down() ( app->getKeyState(KEY_Alt_L) || app->getKeyState(KEY_Alt_R) )
198 # define shift_key_down() ( app->getKeyState(KEY_Shift_L) || app->getKeyState(KEY_Shift_R) )
199 #endif
200
201 /*
202 Usually, the application will catch the kill command key sequence by itself,
203 but if the event queue gets really full e.g. when appending large amounts
204 of data to the output window, the key event may get buried underneath
205 everything else that's happening. This function "manually" checks for
206 the key sequence and returns true if the user is trying to cancel.
207 */
IsMacroCancelled(bool & command_timeout)208 bool CommandUtils::IsMacroCancelled(bool &command_timeout)
209 {
210 if (command_timeout) { return true; }
211 if (kill_key_down()) {
212 FXushort mods=FXSELTYPE(killkey);
213 if ( (mods&CONTROLMASK) && (!ctrl_key_down()) ) { return false; }
214 if ( (mods&SHIFTMASK) && (!shift_key_down()) ) { return false; }
215 if ( (mods&ALTMASK) && (!alt_key_down()) ) { return false; }
216 command_timeout=true;
217 }
218 return command_timeout;
219 }
220
221