OSDN Git Service

二語前の取得時、カーソル位置の計算が間違っていた
[dokopop/dokopop.git] / amodi / amodi / MainForm.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Text.RegularExpressions;
9 using System.Windows.Forms;
10 using System.IO;
11 using System.Runtime.InteropServices;
12
13 namespace amodi
14 {
15     public partial class AutoMODIMainForm : Form
16     {
17
18                 const int MARGIN_UNDER_CLICK = 2;       // 次の行までの空白
19
20         const int WM_COPYDATA = 0x4A;
21         const int WM_APP = 0x8000;
22         const int WM_AMODI = (WM_APP + 0x400);
23         const int WM_EXEC_OCR = (WM_APP + 0x410);
24
25         // WM_COPYDATA command
26         const int WMCD_EXISTCHECK = 0x4000;
27                 const int WMCD_SETPOINT = 0x4001;
28                 const int WMCD_RESTORE_WINDOW = 0x4002;
29
30
31         //[StructLayout(LayoutKind.Sequential)]
32         private struct COPYDATASTRUCT
33         {
34             public IntPtr dwData;
35             public int cbData;
36             public IntPtr lpData;
37         }
38
39         public struct COPYDATASTRUCT_send {
40             public Int32 dwData;        //送信する32ビット値
41             public Int32 cbData;    //lpDataのバイト数
42             public string lpData;   //送信するデータへのポインタ(0も可能)
43         }
44
45         [DllImport("user32.dll", SetLastError = true)]
46         private static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
47         [DllImport("user32.dll", SetLastError = true)]
48         private static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref COPYDATASTRUCT_send lparam);
49         [DllImport("User32.dll", EntryPoint = "FindWindow")]
50         public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
51
52         MODI.Document md;
53         System.IO.FileSystemWatcher fsw;
54         Queue<string> FileNameQue;
55
56                 // parser output //
57                 int CurLoc;     // mouse cursor position in text.
58
59         public AutoMODIMainForm()
60         {
61                         InitializeComponent();
62             md = new MODI.Document();
63             FileNameQue = new Queue<string>();
64
65 #if true
66             string exepath = System.IO.Path.GetTempPath();
67             exepath += "amodi\\";
68
69                         try
70                         {
71                                 System.IO.Directory.Delete(exepath);
72                         } catch { }
73             System.IO.Directory.CreateDirectory(exepath);
74 #else
75             string exepath = Application.StartupPath;
76             lbFileName.Text = "Watching... - " + exepath;
77 #endif
78             fsw = new System.IO.FileSystemWatcher();
79             fsw.Path = exepath;
80             fsw.IncludeSubdirectories = false;
81             fsw.SynchronizingObject = this;
82             fsw.Changed += new System.IO.FileSystemEventHandler(watcher_Changed);
83             fsw.EnableRaisingEvents = true;
84         }
85         void Cleanup()
86         {
87             fsw.EnableRaisingEvents = false;
88             fsw.Dispose();
89             fsw= null;
90         }
91
92         private void btnDoOCR_Click(object sender, EventArgs e)
93         {
94             DoOCR(tbFileName.Text);
95         }
96
97         private bool DoingOCR = false;
98         bool DoOCR(string filename)
99         {
100             if (DoingOCR) return false;
101             DoingOCR = true;
102
103             bool capture_page = miCapturePage.Checked;
104
105                         ParseFileName(filename);
106
107             lbStatus.Text = "Recognizing... " + filename;
108             tbText.Text = "";
109             tbInfo.Text = "";
110             for (int i = 0; i < 10; i++){
111                 try {
112                     md.Create(filename);
113                 } catch {
114                     tbInfo.AppendText("MODI Create failure: " + filename + "\r\n");
115                     DBW("MODI Create file failure: " + filename);
116                     System.Threading.Thread.Sleep(30);
117                     continue;
118                 }
119                 break;
120             }
121             DBW("DoOCR:OCR");
122             try {
123                                 if (miUseDefLang.Checked){
124                                         md.OCR(MODI.MiLANGUAGES.miLANG_SYSDEFAULT, true, true);
125                                 } else {
126                                         md.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, true, true);
127                                 }
128             } catch {
129                 DBW("MODI OCR Error: " + filename);
130                 md.Close();
131                 DBW("DoOCR:Closed");
132                 lbStatus.Text = "OCR Error: " + filename;
133                 DoingOCR = false;
134                 return false;
135             }
136             DBW("DoOCR:Completed");
137             const int UnderGap = MARGIN_UNDER_CLICK; // 単語のある領域より少し下のpointでも検索対象と認識する空白部分(Y方向)
138             int last_x = 0;
139             int lineno = 0;
140                         CurLoc = 0;
141             lbPoint.Text = "" + CursorPoint.X + "," + CursorPoint.Y;
142             tbInfo.AppendText("Page:" + md.Images.Count + " pt:" + CursorPoint.X + "," + CursorPoint.Y + "\r\n");
143             for (int i = 0; i < md.Images.Count; i++)
144             {
145                 MODI.Image image = (MODI.Image)md.Images[i];
146                 MODI.Layout layout = image.Layout;
147                                 bool outok = capture_page;
148                                 string prevWord = "";
149                                 string prevWord2 = "";
150                                 for (int j = 0; j < layout.Words.Count; j++)
151                 {
152                     MODI.Word word = (MODI.Word)layout.Words[j];
153                     bool cr = false;
154                     bool curLocSet = false;
155
156                     for (int k = 0; k < word.Rects.Count; k++)
157                     {
158                         MODI.MiRect rc = (MODI.MiRect)word.Rects[k];
159                         int h = rc.Bottom - rc.Top;
160                         int w = rc.Right - rc.Left;
161
162                         //bool incursor;
163                                                 //tbText.AppendText(word.Text + " (" + rc.Left + "," + rc.Top+ ")\r\n");
164                         if (CursorPoint.Y >= rc.Top && CursorPoint.Y <= rc.Bottom+UnderGap){
165                             //incursor = true;
166                                                         if (!outok)
167                                                         {
168                                 if (CursorPoint.X < rc.Left     // cursorを飛び越えた
169                                         || (CursorPoint.X >= rc.Left && CursorPoint.X <= rc.Right)      // cursorが矩形内
170                                         ){
171                                     outok = true;
172                                                                         curLocSet = true;
173                                         if (prevWord.Length != 0) {
174                                                                                 if (NumPrevWords >= 2 && prevWord2.Length != 0){
175                                                                                         tbText.AppendText(prevWord2 + " " + prevWord + " ");
176                                             CurLoc = prevWord2.Length + 1 + prevWord.Length + 1;
177                                                                                 } else {
178                                                     tbText.AppendText(prevWord + " ");
179                                             CurLoc = prevWord.Length + 1;
180                                         }
181                                         }
182                                 } else {
183                                                                         prevWord2 = prevWord;
184                                                                         prevWord = word.Text;
185                                                                 }
186                                                         }
187                         } else {
188                             //incursor = false;
189                         }
190
191                         if (outok){
192                             tbInfo.AppendText(word.Text + " (" + w + "x" + h + ":" + rc.Left + "," + rc.Top + ")\r\n");
193                         }
194
195                         if (last_x > rc.Left){
196                             if (tbText.Text!="")
197                                 cr = true;
198                             lineno++;
199                         }
200                         last_x = rc.Left;
201                     }
202
203                     if (outok){
204                         if (cr){
205                             tbText.AppendText("\r\n");
206                             if (curLocSet)
207                                 CurLoc += 2;    // CR+LF
208                         }
209
210                         tbText.AppendText(word.Text + " ");
211                     }
212                 }
213             }
214             md.Close(false);
215             lbStatus.Text = "Done. " + filename;
216             DoingOCR = false;
217             return true;
218         }
219                 private void ParseFileName(string filename)
220                 {
221                         Regex r = new Regex(@"\((?<x>\d+),(?<y>\d+)\)");
222                         Match m = r.Match(filename);
223                         if (m.Success)
224                         {
225                                 CursorPoint.X = int.Parse(m.Groups["x"].Value);
226                                 CursorPoint.Y = int.Parse(m.Groups["y"].Value);
227                         }
228                         r = new Regex(@"-n(?<n>\d+)");
229                         m = r.Match(filename);
230                         if (m.Success)
231                         {
232                                 NumPrevWords = int.Parse(m.Groups["n"].Value);
233                         }
234                 }
235
236         //イベントハンドラ
237         private void watcher_Changed(System.Object source,
238             System.IO.FileSystemEventArgs e)
239         {
240             switch (e.ChangeType)
241             {
242                 case System.IO.WatcherChangeTypes.Changed:
243                     string ext = System.IO.Path.GetExtension(e.FullPath);
244                     if (ext==".gif" || ext==".jpg" || ext==".png" || ext==".tif" || ext==".bmp" || ext==".dib")
245                     {
246                         PostOCR(e.FullPath);
247                     }
248                     break;
249 //                case System.IO.WatcherChangeTypes.Created:
250                     //break;
251 //                case System.IO.WatcherChangeTypes.Deleted:
252   //                  break;
253             }
254         }
255
256         private void PostOCR(string filename)
257         {
258             FileNameQue.Enqueue(filename);
259             PostMessage(this.Handle, WM_EXEC_OCR, IntPtr.Zero, IntPtr.Zero);
260         }
261
262         private void ExecOCR(string filename)
263         {
264             if (DoOCR(filename)) {
265                 string textname = filename + ".txt";
266                 for (int i = 0; i < 10; i++) {
267                     try {
268                         StreamWriter writer = new StreamWriter(textname, false, System.Text.Encoding.GetEncoding("utf-16"));
269                         writer.WriteLine(CurLoc.ToString());
270                         writer.Write(tbText.Text);
271                         writer.Close();
272                     } catch {
273                         tbInfo.AppendText("Write Error:" + textname + "\r\n");
274                         System.Threading.Thread.Sleep(30);
275                         continue;
276                     }
277                     break;
278                 }
279             }
280             if (!miDebugMode.Checked) {
281                 try {
282                     System.IO.File.Delete(filename);
283                 }
284                 catch
285                 {
286                     // 連続して.bmpファイルが作られているため
287                     tbInfo.AppendText("Delete Error:" + filename + "\r\n");
288                 }
289             }
290         }
291
292         private void miExit_Click(object sender, EventArgs e)
293         {
294             Close();
295         }
296
297         enum AMODI_CMD
298         {
299             QUERY = 0,
300             PAGE_CAPTURE = 1,
301         };
302         struct POINT
303         {
304             public int x;
305             public int y;
306         };
307         Point CursorPoint;
308         unsafe static Point int2point(IntPtr param)
309         {
310                         POINT pt = (POINT)Marshal.PtrToStructure((IntPtr)param, typeof(POINT));
311             Point p = new Point();
312             p.X = pt.x;
313             p.Y = pt.y;
314             return p;
315         }
316         int NumPrevWords = 1;
317         // interface for external app
318         protected override void WndProc(ref Message m)
319         {
320             if (m.Msg == WM_AMODI)
321             {
322                 switch ((AMODI_CMD)m.WParam)
323                 {
324                     case AMODI_CMD.QUERY:
325                         m.Result = (IntPtr)m.LParam;
326                         return;
327                     case AMODI_CMD.PAGE_CAPTURE:
328                         m.Result = (IntPtr)(miCapturePage.Checked ? 1 : 0);
329                         return;
330                     default:
331                         break;
332                 }
333             } else
334             if (m.Msg == WM_EXEC_OCR) {
335                 string filename = "";
336                 while (FileNameQue.Count()!=0) {
337                     filename = FileNameQue.Dequeue();
338                 }
339                 if (filename != "") {
340                     ExecOCR(filename);
341                 }
342             } else
343             if (m.Msg == WM_COPYDATA)
344             {
345                 COPYDATASTRUCT cds = new COPYDATASTRUCT();
346                 cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
347                 if (cds.dwData == (IntPtr)WMCD_EXISTCHECK)
348                 {
349                     m.Result = (IntPtr)1;
350                     return;
351                 } else
352                                 if (cds.dwData == (IntPtr)WMCD_SETPOINT){
353                                         CursorPoint = int2point(cds.lpData);
354                                         Console.WriteLine("Cursor:" + CursorPoint.X + "," + CursorPoint.Y);
355                                         return;
356                                 } else
357                                 if (cds.dwData == (IntPtr)WMCD_RESTORE_WINDOW)
358                                 {
359                                         this.Show();
360                                 }
361 #if false   // 参考
362                 if (cds.cbData > 0)
363                 {
364                     byte[] data = new byte[cds.cbData];
365                     Marshal.Copy(cds.lpData, data, 0, cds.cbData);
366                     //あとは data に COPYDATA の内容が入ってるので適宜処理
367                 }
368                 m.Result = (IntPtr)1;
369 #endif
370             }
371             base.WndProc(ref m);
372         }
373
374         private void miCapturePage_Click(object sender, EventArgs e)
375         {
376             miCapturePage.Checked = !miCapturePage.Checked;
377         }
378
379                 private void AutoMODIMainForm_Activated(object sender, EventArgs e)
380                 {
381                         //this.Hide();
382                 }
383
384                 private void miDebugMode_Click(object sender, EventArgs e)
385                 {
386                         miDebugMode.Checked = !miDebugMode.Checked;
387                 }
388
389                 private void miUseDefLang_Click(object sender, EventArgs e)
390                 {
391                         miUseDefLang.Checked = !miUseDefLang.Checked;
392                 }
393
394         static int hWin = 0;
395         void DBW( string msg )
396         {
397                 if ( hWin==0 ){
398                         hWin = FindWindow( "TDbgMsgForm", "Debug Messenger" );
399                         if ( hWin==0 ) return;
400                 }
401             byte[] bytearray = System.Text.Encoding.Default.GetBytes(msg);
402             int len = bytearray.Length;
403                 COPYDATASTRUCT_send cds;
404                 cds.dwData = 1; // Indicate String
405                 cds.cbData = len + 1;
406             cds.lpData = msg;
407                 SendMessage( (IntPtr)hWin, WM_COPYDATA, IntPtr.Zero, ref cds );
408         }
409     }
410 }