-
Notifications
You must be signed in to change notification settings - Fork 11
/
jeforth.hta
308 lines (288 loc) · 12.6 KB
/
jeforth.hta
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head id=head>
<!-- Introduction to HTML Applications (HTAs) http://msdn.microsoft.com/en-us/library/ms536496%28v=vs.85%29.aspx#Compatibility -->
<!-- HTML Applications Reference http://msdn.microsoft.com/en-us/library/ms536473(v=vs.85).aspx -->
<title class=appname>appname</title>
<meta http-equiv="x-ua-compatible" content="ie=9" />
<HTA:APPLICATION
ID="hta"
APPLICATIONNAME="jeforth.3hta"
VERSION="205"
/>
<meta charset="utf-8" />
<!-- link rel="stylesheet" type="text/css" href="common.css" -->
<!-- 分別定義 textarea:focus 才可以隨時修改,隨 editMode 改變顏色 -->
<style id=styleTextareaFocus type="text/css">
.console3we textarea:focus {
background:#E0E0E0;
}
</style>
</head>
<body id=body onload="init()">
<div id=header>
<div style="opacity:0.2;position:absolute;top:40px;left:90px;width:300px;height:75px;background-color:#20B3DF">
<center><span style="color:#FFFFFF;"><br>FigTaiwan</span></center></div>
<div style="font-family:verdana;">
<b><div class=appname style="letter-spacing:16px;color:#555555;">appname</div></b>
<div style="color:#40B3DF;">
Revision <span id=rev style="background-color:#B4009E;color:#ffffff;">rev</span><br>
Top on <span id=jsengine>jsengine</span><br>
Source code http://github.com/hcchengithub/jeforth.3we<br>
Program path <span id=loc>location</span><br>
</div>
</div>
</div>
<p>
<div class=console3we>
<div id="outputbox"></div>
<textarea id="inputbox" rows=1></textarea>
<span id=endofinputbox class=std>
<input type="radio" id="forthbtn" value="forth" name="lang" checked="checked"><label class=std>FORTH</label>
<input type="radio" id="jsbtn" value="js" name="lang"><label class=std>JavaScript</label>
</span>
</div>
</body>
<script src="js/jquery-1.11.2.js"></script>
<script src="https://hcchengithub.github.io/project-k/projectk.js"></script>
<Script src="project-k/projectk.js"></Script>
<script src="js/version.js"></script>
<script>
// 人家都把 script 放在 head 或 body。我怎麼發現可以放在這裡的,為什麼?
// 原因: 你看這 source code 不是很清爽嗎? head , body 都很短很清晰。大片 script 放在下面,整整齊齊。
// 簡單用 <body onload="init();"> 即銜接良好。
// 時間: 想必是把 jquery 抽出去時改的。
// HTA 在 Windows XP, Windows 7 都有很多問題,如果太早 include jQuery 馬
// 上就會撞上。延後到 jeforth.f 都起來了之後是比較好的安排。
var jeforth_project_k_virtual_machine_object = new jeForth(); // A permanent name.
var kvm = jeforth_project_k_virtual_machine_object; // "kvm" may not be so permanent.
kvm.minor_version = jeforth3we_minor_version; // from js/version.js, was hta.version from the < HTA > tag
kvm.appname = hta.applicationName;
kvm.host = window; // global 掛那裡的根據。
kvm.path = ["dummy", "doc", "f", "3htm/f", "3htm/canvas", "3htm", "3hta/f", "3hta/vbs", "3hta/excel", "3hta", "demo", "playground", "private"];
kvm.selftest_visible = true; // static variable, self-test adjusts it, type() checks it. both sides need to access it.
kvm.lang = 'forth'; // 'js' or 'forth' let console support two languages
// Useful common tool, need to be redefined after jQuery also.
kvm.plain = function (s) {
// Origin in jeforth.hta before jQuery available
var ss = s + ""; // avoid numbers to fail at s.replace()
ss = ss.replace(/\t/g,'\u00a0\u00a0\u00a0\u00a0')
.replace(/ /g,'\u00a0') // utf-8 space ce@ :: textContent="a\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0b"
.replace(/</g,'<') // jQuery append() needs this
.replace(/>/g,'>') // jQuery append() needs this
.replace(/\r?\n\r?/g,'<br>');
return ss;
}
// kvm.type = function (s) {
// // No jquery, more efforts.
// try {
// var ss = s + ''; // Print-able test
// } catch(err) {
// ss = Object.prototype.toString.apply(s);
// }
// if(kvm.screenbuffer!=null) kvm.screenbuffer += ss; // 填 null 就可以關掉。
// if(kvm.selftest_visible){
// // was: $('#outputbox').append(kvm.plain(ss)); 不用 jQuery 變成一大片還缺特性。
// // HTA 在 Windows XP, Windows 7 都有很多問題,如果太早 include jQuery 馬
// // 上就會撞上。延後到 jeforth.f 都起來了之後是比較好的安排。
// var aa = (kvm.plain(ss)+'\n').split('\n').slice(0,-1); // [aaa,bbb,]
// for(i=0; i<aa.length-1; i++){
// outputbox.appendChild(document.createTextNode(aa[i]));
// outputbox.appendChild(document.createElement("br"));
// }
// if(aa[i]) outputbox.appendChild(document.createTextNode(aa[i]));
// }
// };
kvm.type = function (s) {
// Use jquery.f, simpler.
try {
var ss = s + ''; // Print-able test
} catch(err) {
ss = Object.prototype.toString.apply(s);
}
if(kvm.screenbuffer!=null) kvm.screenbuffer += ss; // 填 null 就可以關掉。
if(kvm.selftest_visible) $('#outputbox').append(kvm.plain(ss));
};
// minor version is from js/version.js, major version is from projectk.js kernel.
var version = parseFloat(kvm.major_version+"."+kvm.minor_version);
kvm.greeting = function(){
kvm.type("j e f o r t h . 3 h t a -- v"+version+'\n');
kvm.type(jsengine.innerText+'\n');
kvm.type("source code http://github.com/hcchengithub/jeforth.3we\n");
kvm.type("Root " + window.location.toString()+'\n');
kvm.type("argv " + hta.commandLine+'\n');
return(version);
}
kvm.debug = false;
kvm.screenbuffer = ""; // kvm.type() to screenbuffer before I/O ready
kvm.prompt = "OK";
kvm.ado = new ActiveXObject("ADODB.Stream");
kvm.fso = new ActiveXObject("Scripting.FileSystemObject");
// allow spaces in jeforth.hta path
kvm.argv = (hta.commandLine + " dummy").split(/\"/).slice(1); // use double quote cut and get [0]pathname [1]argv+dummy
kvm.argv = kvm.argv.slice(0,1).concat(kvm.argv[1].split(/\s+/).slice(1,-1)); // jeforth does not allow double quote in command line
kvm.bye = function(){window.close()}; // vb.f will improve it
kvm.clearScreen = function(){outputbox.innerHTML=""};
// kvm.panic() is the master panic handler. The panic() function defined in
// project-k kernel projectk.js is the one called in code ... end-code and it's
// not visible here.
kvm.panic = function(state){
kvm.type(state.msg);
if (state.serious) debugger;
}
// -------------------- GitHub CRLF issue ----------------------------------
// New lines become LF only, they should be CRLF for Microsoft HTA, if were
// [Download Zip] from GitHub. 3nd, 3nw, 3htm are all fine with LF. HTA should
// handle this problem by application itself.
function guaranteeCRLF (ss) { // return a new string with new lines be CRLF
return(replaceLF2CRLF(removeCR(ss))); // remove all CR then replace LF to CRLF.
function removeCR (aa) { // Remove all CR 13 from the string
var bb = "";
for(var i=0; i<aa.length; i++)
if (aa.charCodeAt(i) != 13) bb += aa[i];
return(bb);
}
function replaceLF2CRLF (aa) { // Replace all LF 10 to CRLF 13 10.
var bb = "";
for(var i=0; i<aa.length; i++) {
if (aa.charCodeAt(i) == 10)
bb += String.fromCharCode(13);
bb += aa[i];
}
return(bb);
}
}
// -------------------- read/write local file ----------------------------------
// through either FSO or ADO
// FSO does not support utf-8. http://www.w3schools.com/asp/ado_ref_stream.asp
// ADO does not work well on Windows XP, not good enough on Windows 7 neither on some computers.
// I use ADO, my computers are Windows 8 or 10.
// When used in forth words, inner() handles the try{}catch{} thing.
function writeTextFile_fso (pathname, data) {
var flag = false,
ForReading = 1,
ForWriting = 2,
ForAppending = 8,
TristateUseDefault = -2,
TristateTrue = -1,
TristateFalse = 0; // JScript switch constants.
var ts = kvm.fso.OpenTextFile(
pathname,
ForWriting,
true, // create when not existing
TristateUseDefault // ASCII or Unicode depends on the system default.
);
if(ts){
ts.Write(data);
ts.Close();
flag = true;
}
}
// When used in forth words, inner() handles the try{}catch{} thing.
function readTextFile_fso (pathname) {
var data = "";
var txtFile = kvm.fso.OpenTextFile(
pathname,
1, // ForReading
false,
0 // TristateFalse
);
if (txtFile){
data = txtFile.ReadAll();
txtFile.Close();
}
return(guaranteeCRLF(data));
}
// When used in forth words, inner() handles the try{}catch{} thing.
function writeTextFile_ado (pathname, data) {
var objStream = kvm.ado;
try{objStream.Close()}catch(err){}
objStream.CharSet="utf-8"
objStream.Open();
objStream.WriteText(data); // option: adWriteChar=0(default), adWriteLine=1(\r\n)
objStream.SaveToFile(pathname,2) // adSaveCreateOverWrite=2, adSaveCreateNotExist=1(can't overwite)
objStream.Close()
}
// When used in forth words, inner() handles the try{}catch{} thing.
function readTextFile_ado (pathname) {
var data, objStream = kvm.ado;
try{objStream.Close()}catch(err){}
objStream.CharSet = "utf-8";
objStream.Open();
objStream.LoadFromFile(pathname);
data = objStream.ReadText();
objStream.Close();
return(guaranteeCRLF(data));
}
// Use fso because no Chinese yet and compatibility first.
// Use ado because I give up Windows 7 and older hcchen5600 2015/12/02 08:36:39
kvm.writeTextFile = writeTextFile_ado;
kvm.readTextFile = readTextFile_ado;
// -------------------- End of the read/write local file section -------------------------------
// There's no main loop, event driven call back function is this.
kvm.scroll2inputbox = function(){window.scrollTo(0,endofinputbox.offsetTop)}
kvm.consoleHandler = function (cmd) {
// Defined in jeforth.hta
kvm.lang = forthbtn.checked ? 'forth' : 'js';
if (kvm.lang == 'js' || kvm.lang != 'forth'){
kvm.type((cmd?'\n> ':"")+cmd+'\n');
result = eval(cmd);
if(result != undefined) kvm.type(result + "\n");
window.scrollTo(0,endofinputbox.offsetTop); inputbox.focus();
}else{
var rlwas = kvm.rstack().length; // r)stack l)ength was
kvm.type((cmd?'\n> ':"")+cmd+'\n');
kvm.dictate(cmd); // Pass the command line to jeForth VM
(function retry(){
// rstack 平衡表示這次 command line 都完成了,這才打 'OK'。
// event handler 從 idle 上手,又回到 idle 不會讓別人看到它的 rstack。
// 雖然未 OK, 仍然可以 key in 新的 command line 且立即執行。
if(kvm.rstack().length!=rlwas)
setTimeout(retry,100);
else {
kvm.type(" " + kvm.prompt + " ");
if ($(inputbox).is(":focus")) // more accurate, Ctrl-Enter usages need this
kvm.scroll2inputbox();
}
})();
}
}
// onkeydown,onkeypress,onkeyup
// event.shiftKey event.ctrlKey event.altKey event.metaKey
// KeyCode test page http://www.asquare.net/javascript/tests/KeyCode.html
function hotKeyHandler(e) {
// document.onkeydown() initial version defined in jeforth.hta, will be reDef by platform.f
e = (e) ? e : event; var keycode = (e.keyCode) ? e.keyCode : (e.which) ? e.which : false;
switch(keycode) {
case 13: /* Enter */
var cmd = inputbox.value; // w/o the '\n' character ($10).
inputbox.value = ""; // 少了這行,如果壓下 Enter 不放,就會變成重複執行。
kvm.consoleHandler(cmd);
return(false);
}
return (true); // pass down to following handlers
}
// System initialization
function init() { // jQuery(document).ready(function($) {
rev.innerHTML = version; // also .commandLine, .applicationName, ...
loc.innerHTML = window.location.toString(); // it's built-in in DOM
jsengine.innerHTML = (
// http://stackoverflow.com/questions/19567887/javascript-version-in-hta
ScriptEngine() + ' v' +
ScriptEngineMajorVersion() + '.' +
ScriptEngineMinorVersion() + '.' +
ScriptEngineBuildVersion()
);
if(document.getElementsByClassName){
document.getElementsByClassName('appname')[0].innerHTML=kvm.appname;
document.getElementsByClassName('appname')[1].innerHTML=kvm.appname;
} else{
alert("Warning: Your system is old, IE10 or newer preferred. Try Windows upgrade.");
}
document.onkeydown = hotKeyHandler; // Must be using onkeydown so as to grab the control.
kvm.dictate(kvm.readTextFile("f/jeforth.f")+kvm.readTextFile("3hta/f/quit.f")); // Run once.
// dictate() 之後不能再有任何東西,否則因為有 sleep/suspend/resume 之故,會被意外執行到。
};
</script>
</html>