-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpeama.ew
189 lines (176 loc) · 6.2 KB
/
peama.ew
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
--
-- peama.ew
--
-- Slightly modified version (of Edita\eama.ew) for Phix.
-- Does not attempt xl("Edita"), ie if you change
-- C:\Program Files\Edita\[or wherever]lang\elng_ENG[or whatever].txt
-- such that "Edita"!="Edita", then you'll only get warnings etc on the
-- console window, not in Edita's message area.
-- I have also stripped out the "closeExisting" functionality.
--
-- Monitor application. This is a standard include file which allows output
-- from an application to be shown in the message area of Edita.
--
-- After including this file, just call eamsg(text), which returns True on
-- success or False on failure. text may be any object, however it is
-- recommended you explicitly use sprint, since eg passing a sequence of
-- integers may work as you expect when some or all are <32, but then
-- suddenly put out "ABC" instead of the desired {65,66,67}.
--
-- Using eamsg() instead of "Capture Console Output" is recommended for
-- GUI programs.
--
-- Can also be used to integrate a program with edita, returning the current
-- open file name, etc.
--
--with trace
--include arwen.ew -- not needed, can be used in any (exw) program.
include builtins\dll.e
include builtins\machine.e
include builtins\misc.e
constant
True = (1=1),
False = (1=0),
CD_CONS = #20050226, -- text to appear in message area (like Captured console output)
CD_EDITA = #20050228, -- Are you really Edita?
CD_ISENS = #20130505, -- intellisense ready/still active
WM_COPYDATA = 74,
WM_GETTEXT = 13,
WM_GETTEXTLENGTH = 14
atom user32=0, xSendMessage, xEnumWindows
procedure uinit() -- platform()=WINDOWS only
user32 = open_dll("user32.dll")
xSendMessage = define_c_func(user32, "SendMessageA",
{C_PTR, -- HWND hwnd, // handle of destination window
C_UINT, -- UINT uMsg, // message to send
C_UINT, -- WPARAM wParam, // first message parameter
C_UINT}, -- LPARAM lParam // second message parameter
C_LONG) -- LRESULT (depends on whatever processes the message, so use object)
xEnumWindows = define_c_func(user32, "EnumWindows",
{C_PTR, -- WNDENUMPROC lpEnumFunc, // address of callback function
C_LONG}, -- LPARAM lParam // application-defined value
C_INT) -- BOOL
end procedure
atom mainHwnd
mainHwnd = 0
object void
constant Edita = "Edita",
minlength = length(Edita)
function EnumWindowsProc(atom hwnd, atom lParam)
-- (platform()=WINDOWS only)
atom mem
integer len
sequence text
atom CDS
integer isEdita
if lParam then end if -- suppress warnings
-- if user32=0 then uinit() end if
len = c_func(xSendMessage, {hwnd, WM_GETTEXTLENGTH, 0, 0})
if len>=minlength then
len += 1
mem = allocate(len)
len = c_func(xSendMessage, {hwnd, WM_GETTEXT, len, mem})
text = peek({mem, len})
free(mem)
if match(Edita,text)=1 then
CDS = allocate(12)
poke4(CDS,{CD_EDITA,0,0})
isEdita = (c_func(xSendMessage,{hwnd, WM_COPYDATA, NULL, CDS})=CD_EDITA)
free(CDS)
if isEdita then
mainHwnd = hwnd
return 0 -- cease enumeration
end if
end if
end if
return 1 -- continue enumeration
end function
--constant cb_EnumWindowsProc = call_back(routine_id("EnumWindowsProc"))
function stringify(object o)
object c
sequence x
if not sequence(o) then
x = sprint(o)
else
x = o
for i=length(x) to 1 by -1 do
c = x[i]
if not integer(c) or c>#FF then
x = sprint(o)
exit
end if
if c<' ' then
if c='\n' then
x = x[1..i-1]&"\r\n"&x[i+1..length(x)] -- being sent to EditText, use CRLF format
elsif c='\t' then
x = x[1..i-1]&"\\t"&x[i+1..length(x)]
else
x = sprint(o)
exit
end if
end if
end for
end if
if length(x)<2 or not equal(x[length(x)-1..length(x)],"\r\n") then
x &= "\r\n"
end if
return x
end function
function setmainHwnd()
if mainHwnd=0 then
-- (If Phix has 200 errors/warnings to display but Edita is
-- not running (or worse not responding), we seriously only
-- want to try this once, that is instead of pause/hang for
-- 15-30 seconds between each one...)
mainHwnd = -1
if platform()=WINDOWS then
if user32=0 then uinit() end if
-- void = c_func(xEnumWindows,{cb_EnumWindowsProc,NULL}) -- set mainHwnd
void = c_func(xEnumWindows,{call_back(routine_id("EnumWindowsProc")),NULL}) -- set mainHwnd
end if
end if
if mainHwnd=-1 then
-- puts(1,"Edita not running?")
return False
end if
return True
end function
global function eamsg(object text)
-- make the text appear in edita's message area.
-- returns 1 on success, 0 on failure.
integer res, lt
atom mem, CDS
if platform()=WINDOWS then
if not setmainHwnd() then return 0 end if
text = stringify(text)
lt = length(text)
mem = allocate(lt+1)
if not mem then return 0 end if
poke(mem, text)
poke(mem+lt, 0)
CDS = allocate(12)
poke4(CDS,{CD_CONS,lt+1,mem})
res = (c_func(xSendMessage, {mainHwnd, WM_COPYDATA, NULL, CDS}) = CD_EDITA)
free(CDS)
free(mem)
return res
elsif platform()=LINUX then
--DEV (do this as part of Edix)
return 0
end if
end function
global function getEditaHwnd() -- (for pgui.exw)
if setmainHwnd() then return mainHwnd end if
return 0
end function
global procedure sendCDISENS()
atom CDS
if platform()=WINDOWS then
if setmainHwnd() then
CDS = allocate(12)
poke4(CDS,{CD_ISENS,0,0})
void = c_func(xSendMessage,{mainHwnd, WM_COPYDATA, NULL, CDS})
free(CDS)
end if
end if
end procedure