• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:			ocrshell.cpp
3  * Description:	Code for the OCR side of the OCR API.
4  * Author:		Hewlett-Packard Co
5  *
6  * (C) Copyright 1996, Hewlett-Packard Co.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  *
17  **********************************************************************/
18 
19 /**********************************************************************
20  * This file contains code for the OCR side of the HP OCR interface.
21  * The code is designed to be used with either an ANSI C or C++ compiler.
22  * The structures are designed to allow them to be used with any
23  * structure alignment upto 8.
24  **********************************************************************/
25 
26 #include          "mfcpch.h"
27 #include          "ocrshell.h"
28 #include          "tprintf.h"
29 #include          <stdlib.h>
30 
31 #define EXTERN
32 
33 #ifdef __UNIX__
34 EXTERN ESHM_INFO shm;            /*info on shm */
35 #define TICKS       1
36 #endif
37 
38 #ifdef __MSW32__
39 EXTERN ESHM_INFO shm;            /*info on shm */
40 #define TICKS       1000
41 #endif
42 
43 #ifdef __MAC__
44 
45 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
46 #pragma import on
47 #endif
48 
49 extern volatile ESHM_INFO shm;   /*info on shm */
50 extern unsigned short WaitForSingleObject(  /*"C" */
51                                           volatile Boolean &semaphore,
52                                           unsigned long timeout);
53 extern unsigned short ReleaseSemaphore(  /*"C" */
54                                        volatile Boolean &semaphore);
55 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
56 #pragma import reset
57 #endif
58 #define WAIT_OBJECT_0   1
59 #define TICKS       60
60 #endif
61 
62 typedef enum {
63   OCS_UNINIT,                    /*uninitialized */
64   OCS_SETUP_SHM,                 /*shm setup done */
65   OCS_SETUP_INFO,                /*startinfo sent */
66   OCS_READING_STRIPS,            /*read first but more to come */
67   OCS_READ_STRIPS,               /*read all but no monitor yet */
68   OCS_RECOGNIZING,               /*OCR incomplete */
69   OCS_SENDING_TEXT,              /*sent buffer but more to come */
70   OCS_DEAD                       /*disconnected */
71 } OCR_STATE;
72 
73 /* forward declarations - not in .h file as not needed outside this file*/
74 inT16 ocr_internal_shutdown();  /*closedown */
75 inT16 wait_for_mutex();  /*wait for HP to be ready */
76 inT16 wait_for_hp(               /*wait for semaphore */
77                   inT32 timeout  /*in seconds */
78                  );
79 inT16 release_mutex();  /*release mutex */
80 inT16 release_ocr();  /*release semaphore */
81 
82 static inT32 font_count = 0;     /*number of fonts */
83 static inT16 lines_read = 0;     /*no read in this image */
84                                  /*current state */
85 static OCR_STATE ocr_state = OCS_UNINIT;
86 
87 #ifdef __MAC__
TerminateOCR(AppleEvent * theEvent,AppleEvent * theReply,long refCon)88 pascal short TerminateOCR(AppleEvent *theEvent,
89                           AppleEvent *theReply,
90                           long refCon) {
91   ocr_internal_shutdown();
92   ExitToShell();
93 
94 }
95 #endif
96 
97 /**********************************************************************
98  * ocr_open_shm
99  *
100  * Attempt to connect to the shared memory segment and semaphores used
101  * in talking to the OCR engine. Called from OCR engine.
102  * The parameters are the command line arguments in order.
103  **********************************************************************/
104 #ifdef __MAC__
105 inT16
ocr_open_shm(uinT16 * lang)106 ocr_open_shm (uinT16 * lang)
107 #else
108 inT16
109 ocr_open_shm (                   /*open the shm */
110 const char *shm_h,               /*handle of shm */
111 const char *shm_size,            /*size of shm segment */
112 const char *mutex_h,             /*hp mutex */
113 const char *ocr_h,               /*ocr semaphore */
114 const char *hp_h,                /*hp semaphore */
115 const char *lang_str,            /*language */
116 uinT16 * lang                    /*required language */
117 )
118 #endif
119 {
120   font_count = 0;                /*no fonts yet */
121   #ifdef __MAC__
122   if (shm.OCRProcess.lowLongOfPSN && shm.OCRProcess.highLongOfPSN)
123     return HPERR;
124   *lang = shm.language;
125   GetCurrentProcess (&shm.OCRProcess);
126   if (WakeUpProcess (&shm.IPEProcess))
127     ExitToShell();
128   AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
129     (AEEventHandlerUPP) TerminateOCR, 0, FALSE);
130   #else
131   if (lang != NULL)
132                                  /*get language */
133     *lang = (uinT16) strtol (lang_str, NULL, 10);
134   #endif
135   if (ocr_state != OCS_UNINIT) {
136     ocr_error(OCR_ERR_BAD_STATE);
137     return OCR_API_BAD_STATE;    /*incorrect state */
138   }
139   #ifdef __MSW32__
140   shm.shm_size = strtol (shm_size, NULL, 10);
141                                  /*convert to handle */
142   shm.shm_hand = (HANDLE) strtol (shm_h, NULL, 10);
143   shm.shm_mem = MapViewOfFile (shm.shm_hand, FILE_MAP_WRITE, 0, 0, 0);
144   if (shm.shm_mem == NULL)
145     return HPERR;                /*failed */
146                                  /*convert to handle */
147   shm.mutex = (HANDLE) strtol (mutex_h, NULL, 10);
148                                  /*convert to handle */
149   shm.ocr_sem = (HANDLE) strtol (ocr_h, NULL, 10);
150                                  /*convert to handle */
151   shm.hp_sem = (HANDLE) strtol (hp_h, NULL, 10);
152   #endif
153 
154   ocr_state = OCS_SETUP_SHM;     /*record state */
155   return OKAY;
156 
157 }
158 
159 
160 /**********************************************************************
161  * ocr_error
162  *
163  * Inform the HP side of an error.
164  * The OCR engine should do any cleanup of its own and exit aferwards.
165  * Uses the current state to determine how to send it and cleanup.
166  **********************************************************************/
167 
ocr_error(OCR_ERR_CODE code)168 void ocr_error(                   /*send an error code */
169                OCR_ERR_CODE code  /*error code */
170               ) {
171   ESTRIP_DESC *strip = (ESTRIP_DESC *) shm.shm_mem;
172   /*strip info */
173   ETEXT_DESC *monitor = (ETEXT_DESC *) shm.shm_mem;
174   /*progress monitor */
175 
176   switch (ocr_state) {
177     case OCS_UNINIT:             /*uninitialized */
178     case OCS_DEAD:               /*uninitialized */
179       return;                    /*can't do anything else */
180     case OCS_SETUP_SHM:          /*shm setup done */
181       if (font_count < 1)
182         font_count = 1;
183       ocr_setup_startinfo_ansi (-code, LANGE_NONE, "", "");
184       /*report error */
185       break;
186     case OCS_SETUP_INFO:         /*startinfo sent */
187       if (ocr_get_first_image_strip () == NULL)
188         break;                   /*disconnected */
189     case OCS_READING_STRIPS:     /*read first but more to come */
190       strip->x_size = -code;     /*report error */
191       release_ocr();  /*send ack */
192       release_mutex();
193       break;
194     case OCS_READ_STRIPS:        /*read all but no monitor yet */
195       monitor->count = 0;        /*chars in this buffer(-1) */
196       monitor->progress = 0;     /*percent complete increasing (0-100) */
197                                  /*text not complete */
198       monitor->more_to_come = FALSE;
199       monitor->ocr_alive = TRUE; /*ocr sets to 1, hp 0 */
200       monitor->err_code = -code; /*report error */
201       monitor->cancel = FALSE;   /*0=continue, 1=cancel */
202       release_ocr();  /*send ack */
203       break;
204     case OCS_RECOGNIZING:        /*OCR incomplete */
205     case OCS_SENDING_TEXT:       /*sent buffer but more to come */
206       monitor->err_code = -code; /*report error */
207       release_ocr();  /*send ack */
208   }
209   ocr_internal_shutdown();  /*get ready for exit */
210 }
211 
212 
213 /**********************************************************************
214  * ocr_append_fontinfo
215  *
216  * Initialize one of the font descriptors.
217  **********************************************************************/
218 
ocr_append_fontinfo(uinT16 language,uinT8 font_family,uinT8 char_set,uinT8 pitch,const char * name)219 inT16 ocr_append_fontinfo(                    /*put info into shm */
220                           uinT16 language,    /*default language */
221                           uinT8 font_family,  /*serif/not, fixed/not */
222                           uinT8 char_set,     /*character set standard */
223                           uinT8 pitch,        /*fixed or prop */
224                           const char *name    /*plain ascii name */
225                          ) {
226   EOCR_DESC *desc;               /*ocr engine info */
227   int index;                     /*char index */
228   inT32 font_index;              /*which font */
229 
230   if (ocr_state != OCS_SETUP_SHM) {
231     ocr_error(OCR_ERR_BAD_STATE);
232     return OCR_API_BAD_STATE;    /*incorrect state */
233   }
234 
235                                  /*turn to right type */
236   desc = (EOCR_DESC *) shm.shm_mem;
237   if (font_count >
238     (inT32) ((shm.shm_size - sizeof (EOCR_DESC)) / sizeof (EFONT_DESC)))
239     return OCR_API_NO_MEM;       /*insufficient space */
240   font_index = font_count++;     /*add a font */
241                                  /*setup structure */
242   desc->fonts[font_index].language = language;
243                                  /*setup structure */
244   desc->fonts[font_index].font_family = font_family;
245                                  /*setup structure */
246   desc->fonts[font_index].char_set = char_set;
247                                  /*setup structure */
248   desc->fonts[font_index].pitch = pitch;
249   if (name != NULL) {
250     for (index = 0; index < MAX_FONT_NAME && name[index] != 0; index++)
251       desc->fonts[font_index].name[index] = name[index];
252   }
253   else
254     index = 0;
255   desc->fonts[font_index].name[index] = 0;
256   return OKAY;
257 }
258 
259 
260 /**********************************************************************
261  * ocr_setup_startinfo
262  *
263  * Setup the info on the OCR engine. Uses 16 bit chars to name the
264  * engine.
265  **********************************************************************/
266 
ocr_setup_startinfo(inT32 protocol,uinT16 language,const uinT16 * name,const uinT16 * version)267 inT16 ocr_setup_startinfo(                       /*put info into shm */
268                           inT32 protocol,        /*interface version */
269                           uinT16 language,       /*default language */
270                           const uinT16 *name,    /*name of engine */
271                           const uinT16 *version  /*version of engine */
272                          ) {
273   EOCR_DESC *desc;               /*ocr engine info */
274   int index;                     /*char index */
275   inT16 result;                  /*from open */
276 
277   if (ocr_state != OCS_SETUP_SHM || font_count < 1) {
278     ocr_error(OCR_ERR_BAD_STATE);
279     return OCR_API_BAD_STATE;    /*incorrect state */
280   }
281 
282                                  /*turn to right type */
283   desc = (EOCR_DESC *) shm.shm_mem;
284   desc->protocol = protocol;     /*setup structure */
285   desc->font_count = font_count;
286   desc->language = language;
287   for (index = 0; index < MAX_OCR_NAME && name[index] != 0; index++)
288     desc->name[index] = name[index];
289   desc->name[index] = 0;
290   for (index = 0; index < MAX_OCR_VERSION && version[index] != 0; index++)
291     desc->version[index] = version[index];
292   desc->version[index] = 0;
293 
294   result = release_ocr ();
295   if (result != OKAY)
296     return result;
297   ocr_state = OCS_SETUP_INFO;    /*record state */
298   return OKAY;
299 }
300 
301 
302 /**********************************************************************
303  * ocr_setup_startinfo_ansi
304  *
305  * Setup the info on the OCR engine. Uses 8 bit chars to name the
306  * engine.
307  **********************************************************************/
308 
ocr_setup_startinfo_ansi(uinT32 protocol,uinT16 language,const char * name,const char * version)309 inT16 ocr_setup_startinfo_ansi(                     /*put info into shm */
310                                uinT32 protocol,     /*interface version */
311                                uinT16 language,     /*default language */
312                                const char *name,    /*name of engine */
313                                const char *version  /*version of engine */
314                               ) {
315   EOCR_DESC *desc;               /*ocr engine info */
316   int index;                     /*char index */
317   inT16 result;                  /*from open */
318 
319   if (ocr_state != OCS_SETUP_SHM || font_count < 1) {
320     ocr_error(OCR_ERR_BAD_STATE);
321     return OCR_API_BAD_STATE;    /*incorrect state */
322   }
323 
324                                  /*turn to right type */
325   desc = (EOCR_DESC *) shm.shm_mem;
326   desc->protocol = protocol;     /*setup structure */
327   desc->font_count = font_count;
328   desc->language = language;
329   for (index = 0; index < MAX_OCR_NAME && name[index] != 0; index++)
330     desc->name[index] = name[index];
331   desc->name[index] = 0;
332   for (index = 0; index < MAX_OCR_VERSION && version[index] != 0; index++)
333     desc->version[index] = version[index];
334   desc->version[index] = 0;
335 
336   result = release_ocr ();
337   if (result != OKAY)
338     return result;
339   ocr_state = OCS_SETUP_INFO;    /*record state */
340   return OKAY;
341 }
342 
343 
344 /**********************************************************************
345  * ocr_get_first_image_strip
346  *
347  * Wait for the master to send the first image strip and return a
348  * pointer to it. The result is NULL if it is time to exit.
349  **********************************************************************/
350 
ocr_get_first_image_strip()351 ESTRIP_DESC *ocr_get_first_image_strip() {  /*get image strip */
352   ESTRIP_DESC *strip;            /*strip info */
353   inT16 result;                  /*of wait/release */
354 
355   if (ocr_state != OCS_SETUP_INFO) {
356     tprintf ("Bad state reading strip");
357     ocr_error(OCR_ERR_BAD_STATE);
358     return NULL;                 /*incorrect state */
359   }
360 
361                                  /*strip info */
362   strip = (ESTRIP_DESC *) shm.shm_mem;
363   lines_read = 0;
364 
365   result = wait_for_mutex ();
366   if (result != OKAY) {
367     tprintf ("Mutax wait failed reading strip");
368     return NULL;                 /*HP dead */
369   }
370   result = release_mutex ();
371   if (result != OKAY) {
372     tprintf ("Mutax release failed reading strip");
373     return NULL;                 /*HP dead */
374   }
375   result = wait_for_hp (READIM_TIMEOUT);
376   if (result != OKAY) {
377     tprintf ("Wait for HP failed reading strip");
378     return NULL;                 /*HP dead */
379   }
380   lines_read = strip->strip_size;/*lines read so far */
381   if (lines_read < strip->y_size)
382                                  /*record state */
383       ocr_state = OCS_READING_STRIPS;
384   else
385     ocr_state = OCS_READ_STRIPS;
386   if (strip->x_size == 0 || strip->y_size == 0)
387     return NULL;                 /*end of job */
388 
389   return strip;
390 }
391 
392 
393 /**********************************************************************
394  * ocr_get_next_image_strip
395  *
396  * Wait for the master to send the next image strip and return a
397  * pointer to it. The result is NULL if it is time to exit.
398  **********************************************************************/
399 
ocr_get_next_image_strip()400 ESTRIP_DESC *ocr_get_next_image_strip() {  /*get image strip */
401   ESTRIP_DESC *strip;            /*strip info */
402   inT16 result;                  /*of wait/release */
403 
404   if (ocr_state != OCS_READING_STRIPS) {
405     ocr_error(OCR_ERR_BAD_STATE);
406     return NULL;                 /*incorrect state */
407   }
408 
409                                  /*strip info */
410   strip = (ESTRIP_DESC *) shm.shm_mem;
411   result = release_ocr ();
412   if (result != OKAY)
413     return NULL;                 /*HP dead */
414   result = wait_for_hp (READIM_TIMEOUT);
415   if (result != OKAY)
416     return NULL;                 /*HP dead */
417                                  /*lines read so far */
418   lines_read += strip->strip_size;
419   if (lines_read < strip->y_size)
420                                  /*record state */
421       ocr_state = OCS_READING_STRIPS;
422   else
423     ocr_state = OCS_READ_STRIPS;
424 
425   return strip;
426 }
427 
428 
429 /**********************************************************************
430  * ocr_setup_monitor
431  *
432  * Setup the progress monitor. Call before starting the recognize task.
433  **********************************************************************/
434 
ocr_setup_monitor()435 ETEXT_DESC *ocr_setup_monitor() {  /*setup monitor */
436   ETEXT_DESC *monitor;           /*progress monitor */
437 
438                                  /*text info */
439   monitor = (ETEXT_DESC *) shm.shm_mem;
440   monitor->count = 0;            /*chars in this buffer(-1) */
441   monitor->progress = 0;         /*percent complete increasing (0-100) */
442   monitor->more_to_come = TRUE;  /*text not complete */
443   monitor->ocr_alive = TRUE;     /*ocr sets to 1, hp 0 */
444   monitor->err_code = 0;         /*used by ocr_error */
445   monitor->cancel = FALSE;       /*0=continue, 1=cancel */
446 
447 
448 //by jetsoft
449 //the sem functions are old and were meant for an hp product
450  // if (release_ocr () != OKAY)
451    // return NULL;                 /*release failed */
452 
453   ocr_state = OCS_RECOGNIZING;   /*record state */
454   return monitor;
455 }
456 
457 
458 /**********************************************************************
459  * ocr_char_space
460  *
461  * Return the number of chars that can be fitted into the buffer.
462  **********************************************************************/
463 
ocr_char_space()464 inT32 ocr_char_space() {  /*put char into shm */
465   ETEXT_DESC *buf;               /*text buffer */
466   int result;
467 
468                                  /*progress info */
469   buf = (ETEXT_DESC *) shm.shm_mem;
470   if (buf == NULL)
471     return 0;
472 
473   result =
474     (shm.shm_size - sizeof (ETEXT_DESC)) / sizeof (EANYCODE_CHAR) -
475     buf->count + 1;
476 
477   //      while (buf->hp_alive==-1)
478   //              Sleep(50);                                                                              /*wait for HP*/
479 
480   return result;
481 }
482 
483 
484 /**********************************************************************
485  * ocr_append_char
486  *
487  * Add a character to the output. Returns OKAY if successful, OCR_API_NO_MEM
488  * if there was insufficient room in the buffer.
489  **********************************************************************/
490 
ocr_append_char(uinT16 char_code,inT16 left,inT16 right,inT16 top,inT16 bottom,inT16 font_index,uinT8 confidence,uinT8 point_size,inT8 blanks,uinT8 enhancement,OCR_CHAR_DIRECTION text_dir,OCR_LINE_DIRECTION line_dir,OCR_NEWLINE_TYPE nl_type)491 inT16 ocr_append_char(                              /*put char into shm */
492                       uinT16 char_code,             /*character itself */
493                       inT16 left,                   /*of char (-1) */
494                       inT16 right,                  /*of char (-1) */
495                       inT16 top,                    /*of char (-1) */
496                       inT16 bottom,                 /*of char (-1) */
497                       inT16 font_index,             /*what font (-1) */
498                       uinT8 confidence,             /*0=perfect, 100=reject (0/100) */
499                       uinT8 point_size,             /*of char, 72=i inch, (10) */
500                       inT8 blanks,                  /*no of spaces before this char (1) */
501                       uinT8 enhancement,            /*char enhancement (0) */
502                       OCR_CHAR_DIRECTION text_dir,  /*rendering direction (OCR_CDIR_RIGHT_LEFT) */
503                       OCR_LINE_DIRECTION line_dir,  /*line rendering direction (OCR_LDIR_DOWN_RIGHT) */
504                       OCR_NEWLINE_TYPE nl_type      /*type of newline (if any) (OCR_NL_NONE) */
505                      ) {
506   ETEXT_DESC *buf;               /*text buffer */
507   int index;                     /*char index */
508   inT16 result;                  /*of callback */
509 
510   if (ocr_state != OCS_RECOGNIZING && ocr_state != OCS_SENDING_TEXT) {
511     ocr_error(OCR_ERR_BAD_STATE);
512     return OCR_API_BAD_STATE;    /*incorrect state */
513   }
514 
515   if (char_code == ' ' || char_code == '\n' || char_code == '\r'
516     || char_code == '\t')
517     return OCR_API_BAD_CHAR;     /*illegal char */
518 
519                                  /*progress info */
520   buf = (ETEXT_DESC *) shm.shm_mem;
521 
522   result =
523     (shm.shm_size - sizeof (ETEXT_DESC)) / sizeof (EANYCODE_CHAR) -
524     buf->count;
525   if (result < 1)
526     return OCR_API_NO_MEM;       /*insufficient room */
527 
528   index = buf->count++;          /*count of chars */
529                                  /*setup structure */
530   buf->text[index].char_code = char_code;
531   buf->text[index].left = left;  /*setup structure */
532   buf->text[index].right = right;/*setup structure */
533   buf->text[index].top = top;    /*setup structure */
534                                  /*setup structure */
535   buf->text[index].bottom = bottom;
536                                  /*setup structure */
537   buf->text[index].font_index = font_index;
538                                  /*setup structure */
539   buf->text[index].confidence = confidence;
540                                  /*setup structure */
541   buf->text[index].point_size = point_size;
542                                  /*setup structure */
543   buf->text[index].blanks = blanks;
544   if (nl_type == OCR_NL_NONE) {
545     if (text_dir == OCR_CDIR_TOP_BOTTOM || text_dir == OCR_CDIR_BOTTOM_TOP)
546       buf->text[index].formatting = (text_dir << 5) | 128;
547     /*setup structure */
548     else
549                                  /*setup structure */
550       buf->text[index].formatting = text_dir << 5;
551   }
552   else {
553     buf->text[index].formatting = (nl_type << 6) | (line_dir << 5);
554     /*setup structure */
555   }
556   buf->text[index].formatting |= enhancement & (~EUC_FORMAT_MASK);
557   return OKAY;
558 }
559 
560 
561 /**********************************************************************
562  * ocr_send_text
563  *
564  * Send the text to the host and wait for the ack.
565  * Use this function after a sequence of ocr_append_char calls to
566  * actually sent the text to the master process.
567  * Set more to come TRUE if there is more text in this page, FALSE
568  * if the OCR engine is now ready to receive another image.
569  **********************************************************************/
570 
ocr_send_text(BOOL8 more_to_come)571 inT16 ocr_send_text(                    /*send shm */
572                     BOOL8 more_to_come  /*any text left */
573                    ) {
574   ETEXT_DESC *buf;               /*text buffer */
575 
576   if (ocr_state != OCS_RECOGNIZING && ocr_state != OCS_SENDING_TEXT) {
577     ocr_error(OCR_ERR_BAD_STATE);
578     return OCR_API_BAD_STATE;    /*incorrect state */
579   }
580 
581                                  /*progress info */
582   buf = (ETEXT_DESC *) shm.shm_mem;
583 
584                                  /*setup structure */
585   buf->more_to_come = more_to_come;
586   if (more_to_come) {
587     if ((buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWLINE
588     && (buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWPARA) {
589                                  /*force line end */
590       buf->text[buf->count - 1].formatting &= 63;
591       buf->text[buf->count - 1].formatting |= OCR_NL_NEWLINE << 6;
592     }
593   }
594   else {
595     if (buf->count < 1)
596       ocr_append_char ('~', -1, -1, -1, -1, 0, 100, 10, 0,
597         0, OCR_CDIR_RIGHT_LEFT, OCR_LDIR_DOWN_RIGHT,
598         OCR_NL_NEWPARA);
599     /*dummy character */
600     else if ((buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWPARA) {
601                                  /*force para end */
602       buf->text[buf->count - 1].formatting &= 63;
603       buf->text[buf->count - 1].formatting |= OCR_NL_NEWPARA << 6;
604     }
605   }
606 
607   if (release_ocr () != OKAY)
608     return HPERR;                /*release failed */
609   if (wait_for_hp (READTEXT_TIMEOUT) != OKAY)
610     return HPERR;
611   if (more_to_come) {
612     buf->count = 0;              /*setup structure */
613     ocr_state = OCS_SENDING_TEXT;/*record state */
614   }
615   else
616     ocr_state = OCS_SETUP_INFO;  /*record state */
617   return OKAY;
618 }
619 
620 
621 /**********************************************************************
622  * ocr_shutdown
623  *
624  * Closedown communications with the HP side and free up handles.
625  **********************************************************************/
626 
ocr_shutdown()627 inT16 ocr_shutdown() {  /*closedown */
628   #ifdef __MAC__
629   shm.OCRProcess.lowLongOfPSN = kNoProcess;
630   shm.OCRProcess.highLongOfPSN = 0;
631   #endif
632   ocr_error(OCR_ERR_CLEAN_EXIT);  /*signal exit */
633 
634   return OKAY;
635 }
636 
637 
638 /**********************************************************************
639  * ocr_internal_shutdown
640  *
641  * Free up handles or whatever to clean up without attempting to communicate.
642  **********************************************************************/
643 
ocr_internal_shutdown()644 inT16 ocr_internal_shutdown() {  /*closedown */
645   ocr_state = OCS_DEAD;          /*record state */
646   #ifdef __MSW32__
647   if (shm.shm_mem != NULL) {
648     UnmapViewOfFile (shm.shm_mem);
649     CloseHandle (shm.shm_hand);  /*no longer used */
650     CloseHandle (shm.mutex);     /*release handles */
651     CloseHandle (shm.ocr_sem);
652     CloseHandle (shm.hp_sem);
653     shm.shm_mem = NULL;
654   }
655   #elif defined (__MAC__)
656   shm.OCRProcess.lowLongOfPSN = kNoProcess;
657   shm.OCRProcess.highLongOfPSN = 0;
658   #endif
659   return OKAY;
660 }
661 
662 
663 /**********************************************************************
664  * wait_for_mutex
665  *
666  * Wait for the HP side to release its mutex.
667  * The return value is HPERR if the HP side has terminated.
668  **********************************************************************/
669 
wait_for_mutex()670 inT16 wait_for_mutex() {  /*wait for HP to be ready */
671   inT16 result = HPERR;          /*return code */
672   #if defined (__MSW32__) || defined (__MAC__)
673   result = WaitForSingleObject (shm.mutex, (unsigned long) -1)
674   /*wait for thread to move */
675                                  /*bad if timeout */
676     == WAIT_OBJECT_0 ? OKAY : HPERR;
677   #endif
678   if (result != OKAY)
679     ocr_internal_shutdown();
680   return result;
681 }
682 
683 
684 /**********************************************************************
685  * wait_for_hp
686  *
687  * Wait for the HP side to release its semaphore.
688  * The return value is HPERR if the timeout (in seconds) elapsed.
689  **********************************************************************/
690 
wait_for_hp(inT32 timeout)691 inT16 wait_for_hp(               /*wait for semaphore */
692                   inT32 timeout  /*in seconds */
693                  ) {
694   inT16 result = HPERR;          /*return code */
695   #if defined (__MSW32__) || defined (__MAC__)
696                                  /*wait for thread to move */
697   result = WaitForSingleObject (shm.hp_sem, timeout * TICKS)
698                                  /*bad if timeout */
699     == WAIT_OBJECT_0 ? OKAY : HPERR;
700   #endif
701   if (result != OKAY)
702     ocr_internal_shutdown();
703   return result;
704 }
705 
706 
707 /**********************************************************************
708  * release_mutex
709  *
710  * Release the HP mutex.
711  * The return value is OKAY if the call succeeds.
712  **********************************************************************/
713 
release_mutex()714 inT16 release_mutex() {  /*release mutex */
715   inT16 result = HPERR;          /*return code */
716   #ifdef __MSW32__
717                                  /*release it */
718   result = ReleaseMutex (shm.mutex) ? OKAY : HPERR;
719   #elif defined (__MAC__)
720                                  /*release it */
721   result = ReleaseSemaphore (shm.mutex) ? OKAY : HPERR;
722   #endif
723   if (result != OKAY)
724     ocr_internal_shutdown();
725   return result;
726 }
727 
728 
729 /**********************************************************************
730  * release_ocr
731  *
732  * Release the OCR semaphore.
733  * The return value is OKAY if the call succeeds.
734  **********************************************************************/
735 
release_ocr()736 inT16 release_ocr() {  /*release semaphore */
737   inT32 timeout;                 //time allowed
738 
739   timeout = RELEASE_TIMEOUT * TICKS;
740   #ifdef __MSW32__
741 
742 //jetsoft
743 // this stuff is old and no longer applies
744 
745   return OKAY;
746 //
747 
748   BOOL result = 0;               //of release
749   do {
750                                  //release it
751     result = ReleaseSemaphore (shm.ocr_sem, 1, NULL);
752     if (result == FALSE) {
753       timeout -= 50;
754       Sleep (50);
755     }
756   }
757   while (result == FALSE && timeout > 0);
758   if (!result)
759     ocr_internal_shutdown();
760   return OKAY;
761   #elif defined (__MAC__)
762   inT16 result = HPERR;          /*return code */
763                                  /*release it */
764   result = ReleaseSemaphore (shm.ocr_sem) ? OKAY : HPERR;
765 
766   if (result != OKAY)
767     ocr_internal_shutdown();
768   return result;
769   #elif defined (__UNIX__)
770   return 0;
771   #endif
772 }
773