4 Website: http://www.vultaire.net/software/wxkanjipad/files/
5 License: GNU General Public License (GPL) version 2
6 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
8 File: panel_kanjipad.cpp
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc.,
22 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "panel_kanjipad.h"
26 #include "string_utils.h"
28 #define JB_DATADIR "."
30 #ifndef KPENGINE_DATADIR
32 #define KPENGINE_DATADIR JB_DATADIR "\\kpengine_data"
34 #define KPENGINE_DATADIR JB_DATADIR "/kpengine_data"
38 BEGIN_EVENT_TABLE(PanelKanjiPad
, wxPanel
)
39 EVT_LEFT_DOWN(PanelKanjiPad::OnMouseDown
)
40 EVT_LEFT_UP(PanelKanjiPad::OnMouseUp
)
41 EVT_LEAVE_WINDOW(PanelKanjiPad::OnLeaveWindow
)
42 EVT_MOTION(PanelKanjiPad::OnMouseMove
)
43 EVT_RIGHT_DOWN(PanelKanjiPad::OnMouseRightDown
)
44 EVT_PAINT(PanelKanjiPad::OnPaint
)
45 EVT_END_PROCESS(wxID_ANY
, PanelKanjiPad::AfterEngineCall
)
48 PanelKanjiPad::PanelKanjiPad(wxWindow
*owner
,
53 const wxString
& name
) : wxPanel(owner
, id
, pos
,
58 kpStdout
=kpStderr
=NULL
;
60 for(int i
=0;i
<KANJIPAD_MAX_KANJI
;i
++) results
[i
]=_T('\0');
63 void PanelKanjiPad::OnMouseDown(wxMouseEvent
& ev
) {
64 currentStroke
.push_back(ev
.GetPosition());
66 printf("MouseDown: [%d/%d]\n", currentStroke
.back().x
, currentStroke
.back().y
);
71 void PanelKanjiPad::OnMouseUp(wxMouseEvent
& ev
) {
75 printf("MouseUp: [%d/%d]\n", currentStroke
.back().x
, currentStroke
.back().y
);
77 strokes
.push_back(currentStroke
);
78 currentStroke
.clear();
82 void PanelKanjiPad::OnLeaveWindow(wxMouseEvent
& ev
) {
83 if(isDrawing
) OnMouseUp(ev
);
86 void PanelKanjiPad::OnMouseMove(wxMouseEvent
& ev
) {
88 wxPoint pCurrent
= ev
.GetPosition();
89 wxPoint pLast
= currentStroke
.back();
93 dc
.SetBrush(*wxBLACK_BRUSH
);
94 dc
.DrawLine(pLast
.x
, pLast
.y
, pCurrent
.x
, pCurrent
.y
);
95 dc
.SetBrush(wxNullBrush
);
97 /* Append point to stroke */
98 currentStroke
.push_back(pCurrent
);
100 printf("MouseMove: [%d/%d]\n", currentStroke
.back().x
, currentStroke
.back().y
);
105 void PanelKanjiPad::Clear() {
106 currentStroke
.clear();
110 void PanelKanjiPad::OnPaint(wxPaintEvent
& ev
) {
112 dc
.SetBackground(*wxWHITE_BRUSH
);
113 dc
.SetBrush(*wxBLACK_BRUSH
);
119 /* Draw all strokes */
120 for(list
< list
<wxPoint
> >::iterator li
= strokes
.begin();
121 li
!=strokes
.end(); li
++) {
123 pList
= new wxPoint
[pCount
];
125 for(list
<wxPoint
>::iterator pi
= li
->begin();
126 pi
!= li
->end(); pi
++) {
130 dc
.DrawLines(pCount
, pList
);
134 dc
.SetBrush(wxNullBrush
);
137 void PanelKanjiPad::OnMouseRightDown(wxMouseEvent
& ev
) {
139 wxPoint p
= ev
.GetPosition();
140 currentStroke
.clear();
141 currentStroke
.push_back(p
);
143 /* For some reason, this call is slow! */
144 if(strokes
.size()>0) strokes
.pop_back();
149 list
< list
<wxPoint
> > const* PanelKanjiPad::GetStrokes() {return &strokes
;}
151 bool PanelKanjiPad::Search() {
152 /* Create string to send to back end */
153 /* kpengine takes alternating x y args for points via stdin.
154 '\n' breaks between the strokes. */
160 if(strokes
.size()<1) return false;
161 for(list
< list
<wxPoint
> >::const_iterator li
=strokes
.begin();
162 li
!=strokes
.end(); li
++) {
163 for(list
<wxPoint
>::const_iterator pi
=li
->begin();
164 pi
!=li
->end(); pi
++) {
165 charsWritten
= sprintf(buffer
, "%d %d ", pi
->x
, pi
->y
);
166 buffer
[charsWritten
]='\0';
167 points
.append(buffer
);
173 /* Connect to back end */
174 kpengine
= new wxProcess(this);
175 kpengine
->Redirect();
176 wxString command
= _T("jben_kpengine -d " KPENGINE_DATADIR
);
177 kpPid
= wxExecute(command
, wxEXEC_ASYNC
, kpengine
);
179 /* Grab our streams */
180 kpStdin
= kpengine
->GetOutputStream();
181 kpStdout
= kpengine
->GetInputStream();
182 kpStderr
= kpengine
->GetErrorStream();
185 wxMessageBox(_T("ERROR: kpengine could not start!"),
186 _T("Error!"), wxOK
| wxICON_ERROR
, this);
187 } else if(!kpStdin
|| !kpStdout
|| !kpStderr
) {
188 wxMessageBox(_T("ERROR: Could not capture streams from kpengine!"),
189 _T("Error!"), wxOK
| wxICON_ERROR
, this);
190 wxKillError killres
= wxProcess::Kill(kpPid
, wxSIGTERM
);
191 if(killres
!=wxKILL_OK
)
192 wxMessageBox(wxString::Format(
193 _T("ERROR: Sending SIGTERM to kpengine returned "
194 "code %d!\n"), killres
),
195 _T("Error!"), wxOK
| wxICON_ERROR
, this);
198 /* If either of the above errors occurred, then bail. */
206 /* Write all data out to kpengine's stdin */
207 size_t len
= points
.length();
209 while(charsWritten
<len
) {
210 kpStdin
->Write((const void *)(points
.c_str() + charsWritten
),
212 charsWritten
+=kpStdin
->LastWrite();
216 /* Wait until the child process terminates */
217 /* However, don't wait forever! After 3 seconds, force it to close! */
218 wxLongLong stime
= wxGetLocalTime();
219 while(kpengine
&& (wxGetLocalTime() - stime
< 3000))
222 return (results
[0] != _T('\0'));
226 void PanelKanjiPad::AfterEngineCall(wxProcessEvent
& ev
) {
227 if(ev
.GetPid()==kpPid
) {
232 memset((void *)buffer
, 0, 81);
234 for(int i
=0;i
<KANJIPAD_MAX_KANJI
;i
++) results
[i
]=_T('\0');
235 if(kpStdout
->CanRead()) {
236 kpStdout
->Read(buffer
, 80);
240 len
= strlen(buffer
);
241 for(int i
=0;i
<KANJIPAD_MAX_KANJI
;i
++) {
242 if(index
<strlen(buffer
)) {
243 results
[i
] = atoi(buffer
+index
);
244 index
= strchr(buffer
+index
, ' ') - buffer
+ 1;
250 if(kpStderr
->CanRead()) {
251 kpStderr
->Read(buffer
, 80);
254 if(strlen(buffer
)>0) {
256 errstr
.append(buffer
);
257 while(kpStderr
->CanRead()) {
258 kpStderr
->Read(buffer
, 80);
259 errstr
.append(buffer
);
261 errstr
= string("Errors: [").append(Trim(errstr
)).append("]");
262 wxMessageBox(wxString(errstr
.c_str(), wxConvUTF8
).Trim(true).Trim(false),
263 _T("Error on kpengine call"),
264 wxOK
| wxICON_ERROR
, this);