1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-15 15:57:13 +00:00
Interlisp.maiko/src/ocrproc.c
Nick Briggs 6fb4b9a189
Remove sccs id lines (#98)
* Remove static char *id = from all source files.

The same information is included in a comment in each source file.

* Remove unused template file 'id'
2020-12-19 19:08:52 -08:00

905 lines
25 KiB
C

/* $Id: ocrproc.c,v 1.2 1999/01/03 02:07:27 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved
*/
/************************************************************************/
/* */
/* (C) Copyright 1989-95 Venue. All Rights Reserved. */
/* Manufactured in the United States of America. */
/* */
/************************************************************************/
#include "version.h"
#ifdef OCR
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <signal.h>
#include <scsi/targets/ocrio.h>
#include <stdio.h>
#include "ocr.h"
/*
* Cache parameter passed from Subr to postpone time consuming work
*/
static struct ocr_scan_para OCR_scan_para;
static struct ocr_up_para OCR_up_para;
/*
* Image size cache
*/
static int OCR_image_size = 0;
/*
* Number of regions to be read
*/
static int OCR_read_regions = 0;
/*
* Socket fd to communicate the primary emulator process
*/
int OCR_sv = -1;
/*
* Fd for the OCR device file
*/
int OCR_fd = -1;
/*
* Local definitions for clarify code
*/
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
/*
* Local functions
*/
static int ocr_handle_comm(), ocr_init_sv();
static int ocr_proc_scan(), ocr_proc_iminfo(), ocr_proc_set_rpara();
static int ocr_proc_clr_rpara(), ocr_proc_read(), ocr_conv_read_data();
static void ocr_do_postponed_work(), ocr_proc_img_upload();
static void ocr_proc_exit(), ocr_init_signal(), notify_ready();
static void ocr_proc_post_read();
/*
* OCR process
*
* Keep waiting 3 byte length command packet from the primary emulator process.
* The first byte of the packet indicates the work requested. The second and
* third byte indicate the extra packet length. The contents of the extra packet
* is command dependent.
*
* After finishing the work, sends back the another 3 byte length packet. The
* first byte of the returned packet indicates how the work has been done. 1 is
* success, and 0 is failure.
*
* If the work requested will take a long time, the packet with state 1 is just
* returned and the actual work will be postponed, After finishing the postponed
* work, another 3 byte length packet which indicates the result of the work
* is sent back to the primary emulator process, and SIGUSR1 is signalled to
* notify the completion of the initial request.
*/
void ocr_proc(pid_t ppid)
{
int len, postponed = 0;
u_char pkt[PKTLEN];
static u_char epkt[EPKTLEN]; /* Maximum size of extra packet */
if (!ocr_init_sv()) return;
ocr_init_signal();
while (1) {
if (postponed) {
ocr_do_postponed_work(postponed, ppid);
postponed = 0;
} else {
len = read(OCR_sv, pkt, sizeof(pkt));
if (len == 0) {
/*
* Broken socket will return size 0.
* Assumes the parent dies
*/
ocr_proc_exit();
} else if (len != sizeof(pkt)) {
pkt[0] = 0;
(void)write(OCR_sv, pkt, sizeof(pkt));
} else {
if (pkt[1] == 0 && pkt[2] == 0) {
ocr_handle_comm(pkt, NULL, &postponed);
} else {
int elen;
elen = pkt[1] << 8 | pkt[2];
len = read(OCR_sv, epkt, elen);
if (len != elen) {
pkt[0] = 0;
(void)write(OCR_sv, pkt, sizeof(pkt));
} else {
ocr_handle_comm(pkt, epkt, &postponed);
}
}
}
}
}
}
/*
* Try to resett the device then exit.
*/
static void ocr_proc_exit() {
if (OCR_fd > 0) {
ioctl(OCR_fd, OCR_ABORT);
close(OCR_fd);
OCR_fd = -1;
}
exit(1);
}
/*
* Handle the work requested from the primary emulator process
*/
static int ocr_handle_comm(u_char pkt[], u_char epkt[], int *reasonp)
{
int len;
*reasonp = 0;
switch (pkt[0]) {
case 'O': /* Open */
if (OCR_fd > 0) {
pkt[0] = 0;
} else {
OCR_fd = open(OCRDEV, O_RDWR);
if (OCR_fd < 0) {
perror("ocr_proc : OPEN");
pkt[0] = 0;
} else {
pkt[0] = 1;
}
}
break;
case 'S': /* Start scanning */
{
if ((pkt[1] << 8 | pkt[2]) == sizeof(struct ocr_scan_para)) {
bcopy(epkt, (char *)&OCR_scan_para, sizeof(struct ocr_scan_para));
*reasonp = OCR_ST_SCANNING;
pkt[0] = 1;
} else {
pkt[0] = 0;
}
} break;
case 'I': /* Start getting image info */
{
if ((pkt[1] << 8 | pkt[2]) == sizeof(struct ocr_up_para)) {
bcopy(epkt, (char *)&OCR_up_para, sizeof(struct ocr_up_para));
*reasonp = OCR_ST_UPLDING;
pkt[0] = 1;
} else {
pkt[0] = 0;
}
} break;
case 'P': /* Set read params */
{
int len;
len = pkt[1] << 8 | pkt[2];
if (len % sizeof(struct ocr_read_para)) {
pkt[0] = 0;
} else {
len = len / sizeof(struct ocr_read_para);
if (len + OCR_read_regions > OCR_MAX_RD_PARAMS) {
pkt[0] = 0;
} else if (ocr_proc_set_rpara((struct ocr_read_para *)epkt, len)) {
pkt[0] = 1;
} else {
pkt[0] = 0;
}
}
} break;
case 'C': /* Clear read params */
{
if (ocr_proc_clr_rpara()) {
pkt[0] = 1;
} else {
pkt[0] = 0;
}
} break;
case 'R': /* Start reading */
{
if (OCR_read_regions < 0) {
pkt[0] = 0;
} else {
*reasonp = OCR_ST_READING;
pkt[0] = 1;
}
} break;
case 'A':
if (OCR_fd > 0) ioctl(OCR_fd, OCR_ABORT);
exit(1);
default: return 0;
}
if (write(OCR_sv, pkt, PKTLEN) < 0)
return 0;
else
return 1;
}
/*
* Handle postponed time consuming work.
*/
static void ocr_do_postponed_work(int reason, pid_t ppid)
{
u_char pkt[PKTLEN];
switch (reason) {
case OCR_ST_SCANNING:
if (ocr_proc_scan(&OCR_scan_para)) {
pkt[0] = 1;
} else {
pkt[0] = 0;
}
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
break;
case OCR_ST_UPLDING: {
struct ocr_image_info iminfo;
if (!ocr_proc_iminfo(&OCR_up_para, &iminfo)) {
pkt[0] = 0;
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
} else {
ocr_proc_img_upload(&iminfo, ppid);
}
} break;
case OCR_ST_READING:
if (ocr_proc_read()) {
ocr_proc_post_read(ppid);
} else {
pkt[0] = 0;
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
}
break;
default:
pkt[0] = 0;
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
break;
}
return;
}
/*
* Notify primary emulator process that time consuming work has been done.
*/
static void notify_ready(pid_t ppid)
{ kill(ppid, SIGUSR1); }
/*
* Put the socket descriptor into blocking mode, and extend
* the buffer size.
*/
static int ocr_init_sv() {
int flags;
if (OCR_sv < 0) return 0;
flags = fcntl(OCR_sv, F_GETFL, 0);
if (flags < 0) {
perror("ocr_init_sv: fcntl");
return 0;
}
flags &= ~FNDELAY;
if (fcntl(OCR_sv, F_SETFL, flags) < 0) {
perror("ocr_init_sv: fcntl 2");
return 0;
}
return 1;
}
/*
* Make sure the fatal signall initialize the device then exit
*/
static void ocr_init_signal() {
struct sigvec sv;
sv.sv_flags = sv.sv_mask = 0;
sv.sv_handler = ocr_proc_exit;
sigvec(SIGHUP, &sv, NULL);
sigvec(SIGINT, &sv, NULL);
sigvec(SIGQUIT, &sv, NULL);
sigvec(SIGILL, &sv, NULL);
sigvec(SIGTRAP, &sv, NULL);
sigvec(SIGABRT, &sv, NULL);
sigvec(SIGEMT, &sv, NULL);
sigvec(SIGBUS, &sv, NULL);
sigvec(SIGSEGV, &sv, NULL);
sigvec(SIGSYS, &sv, NULL);
sigvec(SIGPIPE, &sv, NULL);
sigvec(SIGTERM, &sv, NULL);
sigvec(SIGLOST, &sv, NULL);
sigvec(SIGUSR1, &sv, NULL);
sigvec(SIGUSR2, &sv, NULL);
return;
}
/*
* Scan image
*/
static int ocr_proc_scan(struct ocr_scan_para *spp)
{
struct scan_params sp;
switch (spp->size) {
case OCR_SIZE_A4: sp.size = SIZE_A4; break;
case OCR_SIZE_B4: sp.size = SIZE_B4; break;
case OCR_SIZE_A5: sp.size = SIZE_A5; break;
case OCR_SIZE_B5: sp.size = SIZE_B5; break;
case OCR_SIZE_LG: sp.size = SIZE_LG; break;
case OCR_SIZE_LT: sp.size = SIZE_LT; break;
default: return 0;
}
switch (spp->direction) {
case OCR_DIRECT_VT: sp.direction = DIRECT_VT; break;
case OCR_DIRECT_HR: sp.direction = DIRECT_HR; break;
default: return 0;
}
switch (spp->resolution) {
case OCR_RES_200: sp.resolution = RES_200; break;
case OCR_RES_240: sp.resolution = RES_240; break;
case OCR_RES_300: sp.resolution = RES_300; break;
case OCR_RES_400: sp.resolution = RES_400; break;
default: return 0;
}
if (spp->adf) {
sp.scanner = SCANNER_AD;
} else {
sp.scanner = SCANNER_FL;
}
if (spp->binary) {
sp.dencity = DENC_AT;
switch (spp->filter) {
case OCR_FILTER_NR: sp.filter = FILTER_NR; break;
case OCR_FILTER_BP: sp.filter = FILTER_BP; break;
default: return 0;
}
switch (spp->threshold) {
case OCR_THRES_0: sp.threshold = THRES_0; break;
case OCR_THRES_1: sp.threshold = THRES_1; break;
case OCR_THRES_2: sp.threshold = THRES_2; break;
case OCR_THRES_3: sp.threshold = THRES_3; break;
case OCR_THRES_4: sp.threshold = THRES_4; break;
case OCR_THRES_5: sp.threshold = THRES_5; break;
default: return 0;
}
switch (spp->noise) {
case OCR_NOISE_0: sp.noise = NOISE_0; break;
case OCR_NOISE_2: sp.noise = NOISE_2; break;
case OCR_NOISE_3: sp.noise = NOISE_3; break;
case OCR_NOISE_4: sp.noise = NOISE_4; break;
case OCR_NOISE_5: sp.noise = NOISE_5; break;
default: return 0;
}
switch (spp->doc) {
case OCR_DOC_NR: sp.doc = DOC_NR; break;
case OCR_DOC_NW: sp.doc = DOC_NW; break;
default: return 0;
}
switch (spp->smooth) {
case OCR_SMTH_CH: sp.smooth = SMTH_CH; break;
case OCR_SMTH_IM: sp.smooth = SMTH_IM; break;
default: return 0;
}
switch (spp->compo) {
case OCR_COMPO_LD: sp.compo = COMPO_LD; break;
case OCR_COMPO_PN: sp.compo = COMPO_PN; break;
case OCR_COMPO_PH: sp.compo = COMPO_PH; break;
case OCR_COMPO_PL: sp.compo = COMPO_PL; break;
default: return 0;
}
} else {
switch (spp->dencity) {
case OCR_DENC_0: sp.dencity = DENC_0; break;
case OCR_DENC_1: sp.dencity = DENC_1; break;
case OCR_DENC_2: sp.dencity = DENC_2; break;
case OCR_DENC_3: sp.dencity = DENC_3; break;
case OCR_DENC_4: sp.dencity = DENC_4; break;
case OCR_DENC_5: sp.dencity = DENC_5; break;
case OCR_DENC_6: sp.dencity = DENC_6; break;
case OCR_DENC_7: sp.dencity = DENC_7; break;
default: return 0;
}
sp.filter = FILTER_NR;
sp.threshold = THRES_0;
sp.noise = NOISE_0;
sp.doc = DOC_NR;
sp.smooth = SMTH_CH;
sp.compo = COMPO_LD;
}
if (ioctl(OCR_fd, OCR_SCAN, &sp) < 0) {
/*
* We could return detailed info about error
* by examining the state field in sp.
*/
return 0;
} else {
return 1;
}
}
/*
* Kick start the image uploading and place the information about the
* image being uploaded into the ocr_image_infor structure.
*/
static int ocr_proc_iminfo(struct ocr_up_para *upp, struct ocr_image_info *infop)
{
struct img_params upara;
struct ocr_stat st;
switch (upp->resolution) {
case OCR_RES_200: upara.resolution = RES_200; break;
case OCR_RES_240: upara.resolution = RES_240; break;
case OCR_RES_300: upara.resolution = RES_300; break;
case OCR_RES_400: upara.resolution = RES_400; break;
default: return 0;
}
switch (upp->compress) {
case OCR_COMP_NONE: upara.compress = COMP_NONE; break;
case OCR_COMP_2: upara.compress = COMP_2; break;
case OCR_COMP_4: upara.compress = COMP_4; break;
case OCR_COMP_8: upara.compress = COMP_8; break;
default: return 0;
}
upara.region.xs = upp->xs;
upara.region.ys = upp->ys;
upara.region.xe = upp->xe;
upara.region.ye = upp->ye;
if (ioctl(OCR_fd, OCR_IMG_UPLOAD, &upara) < 0) return 0;
{
int i;
i = ioctl(OCR_fd, OCR_STAT, &st);
if (i < 0) {
return 0;
} else if (st.state != STATE_UPLDING) {
return 0;
}
}
/* if (!ioctl(OCR_fd, OCR_STAT, &st) || st.state != STATE_UPLDING) return 0; */
switch (st.data.image.resolution) {
case RES_200: infop->resolution = OCR_RES_200; break;
case RES_240: infop->resolution = OCR_RES_240; break;
case RES_300: infop->resolution = OCR_RES_300; break;
case RES_400: infop->resolution = OCR_RES_400; break;
default: return 0;
}
switch (st.data.image.compress) {
case COMP_NONE: infop->compress = OCR_COMP_NONE; break;
case COMP_2: infop->compress = OCR_COMP_2; break;
case COMP_4: infop->compress = OCR_COMP_4; break;
case COMP_8: infop->compress = OCR_COMP_8; break;
default: return 0;
}
infop->line_width = (u_int)st.data.image.line_width;
infop->size = (u_int)st.data.image.size;
infop->xs = st.data.image.region.xs;
infop->ys = st.data.image.region.ys;
infop->xe = st.data.image.region.xe;
infop->ye = st.data.image.region.ye;
OCR_image_size = (int)st.data.image.size;
return 1;
}
/*
* Set Read Parameters
*/
static int ocr_proc_set_rpara(register struct ocr_read_para *rpp, int len)
{
register int cnt = len;
struct read_params rpara;
if (OCR_fd < 0) {
return 0;
} else {
for (; cnt > 0; cnt--, rpp++) {
switch (rpp->format) {
case OCR_FMT_H1: rpara.format = FMT_H1; break;
case OCR_FMT_H2: rpara.format = FMT_H2; break;
case OCR_FMT_H3: rpara.format = FMT_H3; break;
case OCR_FMT_H4: rpara.format = FMT_H4; break;
case OCR_FMT_V1: rpara.format = FMT_V1; break;
case OCR_FMT_V2: rpara.format = FMT_V2; break;
case OCR_FMT_V3: rpara.format = FMT_V3; break;
case OCR_FMT_V4: rpara.format = FMT_V4; break;
default: return 0;
}
rpara.cunit = CUNIT_PO;
rpara.csize = CSIZE_DFLT;
rpara.ckind = 0;
rpara.ckind |= (rpp->ck_num) ? CK_NUM : 0;
rpara.ckind |= (rpp->ck_alph) ? CK_ALPH : 0;
rpara.ckind |= (rpp->ck_grk) ? CK_GRK : 0;
rpara.ckind |= (rpp->ck_jvt) ? CK_JVT : 0;
rpara.ckind |= (rpp->ck_jhr) ? CK_JHR : 0;
rpara.ckind |= (rpp->ck_sym) ? CK_SYM : 0;
rpara.ckind |= (rpp->ck_kana) ? CK_KANA : 0;
rpara.ckind |= (rpp->ck_joyou) ? CK_JOYOU : 0;
rpara.ckind |= (rpp->ck_jis1) ? CK_JIS1 : 0;
rpara.ckind |= (rpp->ck_jmisc) ? CK_JMISC : 0;
rpara.ckind |= (rpp->ck_gaiji) ? CK_GAIJI : 0;
switch (rpp->deform) {
case OCR_DFRM_1: rpara.cprop |= DFRM_1; break;
case OCR_DFRM_2: rpara.cprop |= DFRM_2; break;
case OCR_DFRM_3: rpara.cprop |= DFRM_3; break;
case OCR_DFRM_4: rpara.cprop |= DFRM_4; break;
case OCR_DFRM_NR: rpara.cprop |= DFRM_NR; break;
case OCR_DFRM_6: rpara.cprop |= DFRM_6; break;
case OCR_DFRM_7: rpara.cprop |= DFRM_7; break;
case OCR_DFRM_8: rpara.cprop |= DFRM_8; break;
case OCR_DFRM_9:
rpara.cprop |= DFRM_9;
break;
defaul:
return 0;
}
if (OCR_REJ_0 <= rpp->reject && rpp->reject <= OCR_REJ_5) {
rpara.cprop |= rpp->reject;
} else {
return 0;
}
rpara.region.xs = rpp->xs;
rpara.region.ys = rpp->ys;
rpara.region.xe = rpp->xe;
rpara.region.ye = rpp->ye;
if (ioctl(OCR_fd, OCR_READ_PARA, &rpara) < 0) { return 0; }
}
OCR_read_regions += len;
return 1;
}
}
/*
* Clear Read Parameters
*/
static int ocr_proc_clr_rpara() {
if (OCR_fd < 0 || ioctl(OCR_fd, OCR_READ_CLR) < 0) {
return 0;
} else {
return 1;
}
}
/*
* Read
*/
static int ocr_proc_read() {
if (OCR_fd < 0 || ioctl(OCR_fd, OCR_READ) < 0) {
return 0;
} else {
return 1;
}
}
/*
* Upload and transfer image data. Data transfer is done in such way that is
* compatible with ocr_bulk_read in 'ocr.c'.
*/
static void ocr_proc_img_upload(struct ocr_image_info *iminfop, pid_t ppid)
{
register int len, resid, firsttime = 1;
int cnt;
char rbuf[65536], pkt[PKTLEN];
register char *ptr;
struct bd_header hd;
resid = OCR_image_size;
while (resid > 0) {
len = MIN(resid, sizeof(rbuf));
cnt = read(OCR_fd, rbuf, len);
if (cnt < 0) {
pkt[0] = 0;
write(OCR_sv, pkt, sizeof(pkt));
return;
}
resid -= cnt;
hd.len = (u_int)cnt;
hd.cont = (resid > 0) ? BD_CONT : BD_LAST;
if (firsttime) {
pkt[0] = 1;
write(OCR_sv, pkt, sizeof(pkt));
write(OCR_sv, (char *)iminfop, sizeof(struct ocr_image_info));
write(OCR_sv, &hd, sizeof(struct bd_header));
notify_ready(ppid);
firsttime = 0;
} else {
write(OCR_sv, &hd, sizeof(struct bd_header));
}
for (ptr = rbuf; cnt > 0; cnt -= len, ptr += len) { len = write(OCR_sv, ptr, cnt); }
}
return;
}
/*
* Get the read result from the device driver. The format of the data
* is converted to make it easy Lisp to use it. After converting the data,
* transfer data. Data transfer is done in such way that is
* compatible with ocr_bulk_read in 'ocr.c'.
*/
static void ocr_proc_post_read(pid_t ppid)
{
static u_char rbuf[65536];
static u_char fbuf[65536];
register u_char *ptr;
struct ocr_stat st;
register int cnt, len;
int amt, firsttime = 1;
struct bd_header hd;
if (OCR_fd < 0) goto fail;
if (ioctl(OCR_fd, OCR_STAT, &st) < 0 || st.state != STATE_RDING) goto fail;
while (st.state == STATE_RDING) {
if (sizeof(rbuf) - 2048 > st.data.rd_resid) {
/*
* 2048 is a margin to reformat the data.
*/
amt = len = st.data.rd_resid;
} else {
amt = len = sizeof(rbuf) - 2048;
}
ptr = rbuf;
do {
cnt = read(OCR_fd, ptr, len);
if (cnt < 0) {
goto fail;
} else {
len -= cnt;
ptr += cnt;
}
} while (len > 0);
if (ioctl(OCR_fd, OCR_STAT, &st) < 0) goto fail;
len = ocr_conv_read_data(rbuf, fbuf, amt);
if (len < 0) {
goto fail;
} else if (firsttime) {
u_char pkt[PKTLEN];
pkt[0] = 1;
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
firsttime = 0;
}
hd.len = (u_int)len;
hd.cont = (st.state == STATE_RDING) ? BD_CONT : BD_LAST;
write(OCR_sv, &hd, sizeof(struct bd_header));
for (ptr = fbuf; len > 0; len -= cnt, ptr += cnt) { cnt = write(OCR_sv, ptr, len); }
}
return;
fail : {
u_char pkt[PKTLEN];
pkt[0] = 0;
write(OCR_sv, pkt, sizeof(pkt));
notify_ready(ppid);
return;
}
}
/*
* Reformat the read data to make a life of Lisp tremendously easy
*/
static int ocr_conv_read_data(register u_char *sp, u_char *dp, register int len)
{
bcopy(sp, dp, len);
return (len);
}
/****************************************************
****************************************************
#define INC_SP(pos) {\
if (--len == 0) {\
statep->jmp = (pos);\
return(amt);\
} else {\
sp++;\
}\
}
#define CONV_CODE_BLOCK {
static int pos, hi, lo;
pos = 0;
if (*sp == 0xEB) {
INC_SP(POS16);
pos16:
if (*sp == 0xA0) {
if (*sp == 0x9F) {
/+ Lower certencity +/
*dp++ = REJECT;
INC_SP(POS17);
pos17:
pos += 2;
hi = *sp;
INC_SP
static int
ocr_conv_read_data(u_char *sp, u_char *dp, int len, struct parse_state *statep)
{
/+
* for now...
+/
bcopy(sp, dp, len);
return(len);
switch (statep->jmp) {
case POS1: goto pos1;
}
amt = 0;
while (1) {
if (*sp == '0') {
INC_SP(POS1);
pos1:
if (*sp == '0') {
/+ Region start +/
*dp++ = REG_START_CODE;
/+ Skip region number +/
INC_SP(POS2);
pos2:
INC_SP(POS3);
pos3:
INC_SP(POS4);
pos4:
if (*sp == 0xFC) {
INC_SP(POS5);
pos5:
if (*sp == 0xFA) {
/+ Blank region +/
*dp++ = REG_END_CODE;
continue;
}
}
/+ Skip a region header +/
INC_SP(POS6);
pos6:
INC_SP(POS7);
pos7:
INC_SP(POS8);
pos8:
INC_SP(POS9);
pos9:
INC_SP(POS10);
pos10:
INC_SP(POS11);
pos11:
INC_SP(POS12);
pos12:
while (1) {
if (*sp == 0xFC) {
INC_SP(POS13);
pos13:
if (*sp == 0xFA) {
/+ Region end +/
*dp++ = REG_END_CODE;
break;
}
}
/+ Skip a line number +/
INC_SP(POS14);
pos14:
/+ Process a line +/
while (1) {
if (*sp == 0xFC) {
INC_SP(POS15);
pos15:
if (*sp == 0xFB) {
/+ EOL +/
break;
}
}
/+ Some code exists +/
CONV_CODE_BLOCK;
}
if (statep.cr_line) *dp++ = EOL_CODE;
}
}
}
/+ Page end +/
return(1)
}
}
if (*sp == '0' && *(sp + 1) == '0') {
/+ Region start +/
*dp++ = REG_START_CODE;
/+ Skip region number +/
sp += 4;
if (*sp == 0xFC && *(sp + 1) == 0xFA) {
/+ Blank region +/
*dp++ = REG_END_CODE;
continue;
} else {
/+ Skip a region header +/
sp += 8;
}
while (1) {
if (*sp == 0xFC && *(sp + 1) == 0xFA) {
/+ Region end +/
*dp++ = REG_END_CODE;
break;
} else {
/+ Skip a line number +/
sp += 2;
/+ Process one line +/
while (*sp != 0xFC || *(sp + 1) != 0xFB) {
/+ Some codes exists +/
CONV_CODE_BLOCK(sp, bp);
}
if (statep.cr_line) *dp++ = EOL_CODE;
}
}
} else {
/+ Page end +/
}
}
}
*********************************************
*********************************************/
#endif /* OCR */