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