[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | BAGELS and other things of Jewish interest |
Notice: | 1.0 policy, 280.0 directory, 32.0 registration |
Moderator: | SMURF::FENSTER |
|
Created: | Mon Feb 03 1986 |
Last Modified: | Thu Jun 05 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 1524 |
Total number of notes: | 18709 |
452.0. "Print formatter for mixed Hebrew-English text" by BOLT::MINOW (Je suis marxiste, tendance Groucho) Thu Apr 14 1988 17:17
Last fall, when I was studying Yiddish, I decided to modify microEmacs
to handle mixed Hebrew-English text. I never got the code working
well enough (still on the back burner), but you might find the
enclosed useful. It takes mixed Hebrew and English text and prints
it on a Panasonic (or, I think, Epson) printer. The program is
written in C and should be straight-forward to get working and/or
adapt to your needs. It is not "product-quality", so don't even
bother extracting it if you're not interested in programming.
hebrew.h common definitions
hformat.c the formatter itself
hprint.c print on Epson printers
Martin.
/* Store this as hebrew.h */
/*
* These definitions are for testing only.
*/
#define LOAD_PRINTER 1
#define ATARI_ST 0
#define ASCII_UPCASE_HEBREW 1
#define DEBUG 1
/*
* Header file for Hebrew printer.
* Definitions:
* ISO_HEBREW Hebrew characters are as defined by
* ISO 8859-8 (ECMA 121)
* ASCII_7BIT_HEBREW Hebrew characters are in the ASCII
* 7-bit range (replacing 'a'-'z')
* ASCII_UPCASE_HEBREW Hebrew characters are in the ASCII
* 7-bit range (replacing 'A'-'Z')
* ATARI_HEBREW Hebrew characters are as defined by
* the Atari ST (in the range 0xC2..0xDC)
* Only one of the above should be defined. ASCII_UPCASE_HEBREW is
* intended for convenience in debugging.
*
* If ATARI_ST is defined and non-zero, output will be directed to
* the Atari printer port. This code will probably work for IBM
* (compatibles) without too much hacking.
* If ATARI_ST is zero, output will be piped to stdout.
*
* If LOAD_PRINTER is non-zero (default), the character set will be
* loaded into the printer.
*/
#include <ctype.h>
#ifndef ISO_HEBREW
#define ISO_HEBREW 0
#endif
#ifndef ASCII_7BIT_HEBREW
#define ASCII_7BIT_HEBREW 0
#endif
#ifndef ASCII_UPCASE_HEBREW
#define ASCII_UPCASE_HEBREW 0
#endif
#ifndef ATARI_HEBREW
#define ATARI_HEBREW 0
#endif
#if (ISO_HEBREW | ASCII_7BIT_HEBREW | ASCII_UPCASE_HEBREW | ATARI_HEBREW) == 0
#ifdef ST
#define ATARI_HEBREW 1
#else
#define ISO_HEBREW 1
#endif
#endif
#if (ISO_HEBREW + ASCII_7BIT_HEBREW + ASCII_UPCASE_HEBREW + ATARI_HEBREW) != 1
<< error, you must define a character set >>
#endif
#ifndef ATARI_ST
#ifdef ST
#define ATARI_ST 1
#else
#define ATARI_ST 0
#endif
#endif
#ifndef LOAD_PRINTER
#define LOAD_PRINTER 1
#endif
#ifndef DEBUG
#define DEBUG 0
#endif
#define TRUE 1
#define FALSE 0
#define EOS '\0'
#define DEF_WIDTH 80 /* Printer width */
#define MAX_COLUMNS 512 /* Maximum line width */
#define LEFT_TO_RIGHT 0 /* Must be zero */
#define RIGHT_TO_LEFT 1
#if ISO_HEBREW
#define FIRST_HEBREW 0xE0
#endif
#if ASCII_7BIT_HEBREW
#define FIRST_HEBREW 0x60
#endif
#if ASCII_UPCASE_HEBREW
#define FIRST_HEBREW '@'
#endif
#if ATARI_HEBREW
#define FIRST_HEBREW 0xC2
#endif
#if ATARI_HEBREW
#define MAXCHAR 27 /* Normal Hebrew character set */
#else
#define MAXCHAR 32 /* My Yiddish hacks */
#endif
#define ISHEBREW(c) (c >= first_hebrew && c <= last_hebrew)
extern int first_hebrew;
extern int last_hebrew;
/*
* Define some character testers. Note that the argument must not
* have side-effects.
*/
#define ISENGLISH(c) (!ISHEBREW(c) && isalpha(c))
#define ISPUNCT(c) (!ISHEBREW(c) && ispunct(c))
#define ISSPACE(c) isspace(c)
#define ISDIGIT(c) isdigit(c)
/*
* Definitions for the multi-directional Hebrew formatter. The data is
* stored in a doubly-linked list. The head of the list, h_listhead,
* identifies the start and end characters, while h_cursor identifies
* the current cursor position. Note that the structure doesn't care
* which direction the list is displayed. I.e., transversing the
* h_next pointer always moves from the natural start of the line
* towards the end of the line (right to left for Hebrew, left to
* right for English).
*
* Note: some of this is only interesting for a display editor.
*
* To extract data from the list (assume English):
* column = 0;
* hp = h_listhead.h_next;
* while (column < ncol && hp != &h_listhead) {
* line[column] = hp->h_char;
* hp = hp->h_next;
* ++column;
* }
*/
typedef struct hlist {
struct hlist *h_next; /* Start->end pointer */
struct hlist *h_prev; /* End->start pointer */
unsigned char h_char; /* Current character */
short h_offset; /* Dot offset in line */
} HLIST;
#ifndef vms
#define noshare
#endif
extern noshare HLIST h_listhead; /* List handle */
extern noshare HLIST *h_cursor; /* Current cursor */
extern noshare int h_is_interpolation; /* Funny cursor? */
extern noshare int debug;
#ifdef ST
#define strchr index /* Berkeley brain damage */
#endif
extern char *strchr();
#define streq(a, b) (strcmp(a, b) == 0)
/* Store this as hformat.c */
/*
* Generalized Hebrew formatter
* Author: Martin Minow
* minow%[email protected]
* Version: 30-Mar-1988
*
* Copyright 1987, 1988 by Martin Minow, Arlington MA 02134, USA.
* All rights reserved.
*
* Permission to copy without fee all or part of this material is granted
* provided that the copies are not made or distributed for direct
* commercial advantage, the copyright notice and title of the publication
* and its date appear, and notice is given that copying is by permission
* of Martin Minow. To copy otherwise, or to republish, requires a fee
* and/or specific permission.
*/
static char copyright[] =
"Copyright 1987, 1988 by Martin Minow, Arlington MA 02134, USA.\
All rights reserved,";
#include "hebrew.h"
#define NIL ((HLIST *) 0)
/*
* This is the list handle. It is known outside.
* h_char is set to EOS to stop loops in _shiftspace().
* h_offset will be set to the length of the line.
*/
noshare HLIST h_listhead = { NIL, NIL, EOS, 0 };
/*
* h_cursor is needed to properly display the cursor in mixed-text
* lines. It marks the position (in display space) of the last
* character entered.
*/
noshare HLIST *h_cursor; /* -> current cursor */
/*
* h_is_interpolation is TRUE if, when the line is formatted and the
* cursor put at the logical end of the line, the display cursor
* is not at the visual end of the line.
*/
noshare int h_is_interpolation;
/*
* The following are private to hformat.c
*/
noshare HLIST h_data[MAX_COLUMNS]; /* Formatted line here */
noshare int h_freepointer; /* Index into h_data[] */
/*
* Format a (mixed-language) line 'size' bytes (columns) long.
* The result is stored in a linked list in h_data[]. The start
* and end of the list are accessed via h_listhead, while the
* current dot is accessed through h_cursor.
* The output line may contain fewer than MAX_COLUMNS bytes of information.
*/
#define H_NORMAL 0 /* Hebrew... */
#define H_INTERPOLATION 1
#define E_NORMAL 2 /* English... */
#define E_INTERPOLATION 3
h_format(source, size, isright)
register char *source; /* Data start */
int size; /* Size of input */
int isright; /* Right->left if TRUE */
{
register HLIST *hp; /* -> current element */
register char *lp; /* -> current input */
char *lpend; /* -> end of input line */
register int state; /* Conversion state */
register int c; /* Current character */
/*
* To simplify the control flow, a lot of the actual byte-banging
* is done by subroutines. Thus, we globalize the input parameters
* so they're accessable to the data movers.
*/
h_freepointer = 0; /* Free all data */
h_listhead.h_prev = &h_listhead; /* Empty the display */
h_listhead.h_next = &h_listhead; /* list. */
h_listhead.h_offset = size; /* Remember line size */
h_cursor = &h_listhead; /* Initial cursor */
/*
* There are two independent algorithms: one for left->right
* text (English with a few Hebrew words scattered in) and
* one for right->left text (Hebrew with some English). The
* two are not symmetrical because of the way numbers work
* inside Hebrew strings in predominantly English text.
* The following is preliminary, and knowingly incomplete.
* In the commentary, Hebrew will be written in upper-case.
*
* For Hebrew text, stuff Hebrew letters and punctuation
* right-to-left until you hit an English letter or digit.
* Then, stuff the English text left to right. When you
* return to Hebrew, fixup any trailing punctuation and
* shift trailing spaces and continue with the Hebrew.
*
* For English text, stuff the English forwards on the line
* until you hit some Hebrew, then write the Hebrew backwards.
* Note: this algorithim doesn't handle numbers quite correctly:
* input: abc DEF 123 GHI jkl
* result: abc IHG 123 FED jkl -- correct
* actual: abc FED 123 IHG jkl -- incorrect.
*
* Remember that the list always runs "front to back" in the
* primary direction. I.e., for English, the first element
* in the list is displayed in column 0, but for Hebrew, the
* first element is displayed in column 79.
*/
lp = source; /* -> current line pos. */
lpend = lp + size; /* -> end of line */
state = (isright) ? H_NORMAL : E_NORMAL;
while (lp < lpend) {
c = *lp & 0xFF;
#if DEBUG
if (debug) {
printf("state %d: %02x '%c' %s\n",
state,
c,
isprint(c) ? c : '?',
ISHEBREW(c) ? "Hebrew"
: ISENGLISH(c) ? "English"
: ISPUNCT(c) ? "Punct"
: ISSPACE(c) ? "Space"
: "Other"
);
}
#endif
/*
* Get a new list element. Note: the semantic line may be
* longer than the display line. However, because text goes
* in "both" directions, stuff at the semantic end of the line
* may still be visible. This is handled (as it were) by
* stealing the last element.
*/
if (h_freepointer < MAX_COLUMNS)
hp = &h_data[h_freepointer++];
else {
hp = h_listhead.h_prev; /* Last element */
h_listhead.h_prev = hp->h_prev; /* Unlink it */
}
hp->h_char = c;
hp->h_offset = (int) (lp - source);
switch (state) {
case H_NORMAL:
h_normal(hp);
if (ISENGLISH(c)) /* Interpolation coming */
state = H_INTERPOLATION;
break; /* Get next character */
case H_INTERPOLATION:
if (ISENGLISH(c) /* Alphabet or digit */
|| ISPUNCT(c) /* or punctuation */
|| ISSPACE(c)) { /* or whitespace */
h_abnormal(hp);
}
else { /* Back to Hebrew */
h_shiftspaces();
h_normal(hp);
state = H_NORMAL;
}
break;
case E_NORMAL: /* Normal English */
h_normal(hp);
if (ISHEBREW(c)) /* Start of Hebrew */
state = E_INTERPOLATION;
break;
case E_INTERPOLATION:
if (ISHEBREW(c) /* More Hebrew */
|| ISPUNCT(c) /* or punctuation */
|| ISSPACE(c)) { /* or whitespace */
h_abnormal(hp);
}
else { /* Now back to English */
h_shiftspaces();
h_normal(hp);
state = E_NORMAL;
}
break;
} /* State machine exit */
++lp;
}
if (state == H_INTERPOLATION
|| state == E_INTERPOLATION)
h_is_interpolation = h_shiftspaces();
else {
h_is_interpolation = FALSE;
}
}
/*
* Normal output (for Hebrew in a Hebrew line or English in an English line).
*/
h_normal(hp)
register HLIST *hp;
{
hp->h_next = &h_listhead; /* New -> end marker */
hp->h_prev = h_listhead.h_prev; /* New -> old end elem. */
(h_listhead.h_prev)->h_next = hp; /* Old end -> new */
h_cursor = h_listhead.h_prev = hp; /* End -> new elem. */
}
/*
* Abnormal (interpolation): right-to-left for Hebrew text in an English
* line or left-to-right for English text in a Hebrew line.
*/
h_abnormal(hp)
register HLIST *hp;
{
hp->h_next = h_cursor; /* Insert at cursor */
hp->h_prev = h_cursor->h_prev; /* What's before cursor */
(h_cursor->h_prev)->h_next = hp; /* Earlier->new */
h_cursor->h_prev = hp; /* Old cursor->new */
h_cursor = hp; /* New cursor is here */
}
/*
* This routine is called at the transition between an interpolation
* and the main text. It shifts spaces and trailing punctuation from
* the end of the interpolation to the edge of the line (between the
* interpolation and subsequent text). For example, letting '_' represent
* blanks and assuming a Hebrew line with interpolated English text:
* Semantics: ABC_123_DEF
* Display: FED_123_CDA
* Note that, when the 'D' was seen (the first Hebrew letter after the
* interpolation, the string looks like:
* 123__CDA
* ^----- move this to left of '1'
* Note: the code cannot loop forever as there must be a non-blank
* between h_cursor and the end of the line.
*
* h_shiftspaces() returns (TRUE) if it didn't move any spaces.
* This is needed if the display formatting ended in an interpolation.
* TRUE means that the line is still inside an interpolation.
*/
int
h_shiftspaces()
{
register HLIST *start;
register HLIST *end;
register HLIST *next;
/*
* Note: we can't get here unless there is a normal letter
* towards the end of the display line. Thus, the following
* cannot loop forever.
*/
start = end = h_cursor;
while (ISSPACE(start->h_char))
start = start->h_next;
while (ISPUNCT(start->h_char))
start = start->h_next;
/*
* Start points to the last character in the interpolation.
*/
if (start == end)
return (TRUE); /* Still interpolating */
/*
* Now, start points at the first non-space:
*
* abc .FED
* ^ ^
* | +-- start
* +---- end
* First, unlink the piece we want to mess around with.
*/
(end->h_prev)->h_next = start;
next = start->h_prev;
start->h_prev = end->h_prev;
/*
* Now: the line looks like "abc FED"
* Finally, reinsert the interpolation spaces backwards (i.e.
* in it's normal display order.
*/
do {
start = next;
next = next->h_prev;
h_normal(start);
} while (start != end);
/*
* As if by magic, the line now looks like "abc FED. "
*/
return (FALSE); /* Cursor is normal */
}
/* Store this as hprint.c */
/*
* Hebrew print formatter
* Author: Martin Minow
* minow%[email protected]
* Version: 30-Mar-1988
*
*
* Copyright 1987, 1988 by Martin Minow, Arlington MA 02134, USA.
* All rights reserved.
*
* Permission to copy without fee all or part of this material is granted
* provided that the copies are not made or distributed for direct
* commercial advantage, the copyright notice and title of the publication
* and its date appear, and notice is given that copying is by permission
* of Martin Minow. To copy otherwise, or to republish, requires a fee
* and/or specific permission.
*/
static char copyright[] =
"Copyright 1987, 1988 by Martin Minow, Arlington MA 02134, USA.\
All rights reserved,";
/*
* Download the Hebrew font into the (Panasonic KX-P1080i) printer.
* One would hope that this would work for Epson and compatibles.
* Then print from the argument list or stdin.
*
* The Panasonic printer doesn't like using control-character positions
* (including DEL 7/15) for font replacement.
*
* Hprint [-options] [files]
*
* Options:
* -d Debug (conditionally compiled)
* -n Use "near letter quality mode"
* -h Set initial direction of file to Hebrew (right->left)
* -e Set initial direction of file to English (left->right)
* -w<width> Printer line width (default = 80)
* -s<value> First Hebrew letter (default set by compilation)
*
* Input text is entered in "chronological" (i.e. speaking) order. The
* program, (assuming it is correct) handles all text reversals.
*
* You can specify the direction of a text segment by adding a line
* containing (exactly)
* *h
* or *e
* to set the direction to "Hebrew" or "English" respectively.
*
* Note: Printer Switch 8 on the Panasonic must be OFF. This may
* be a bug in the printer.
*/
#ifdef _STDC_
#if _STDC_ != 0
#include <stddef.h>
#endif
#endif
#include <stdio.h>
#ifdef ST
#include <osbind.h>
#include <bios.h>
#endif
#include "hebrew.h"
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif
int nlq_mode = FALSE; /* TRUE if Near Letter Quality */
int nhebrew; /* How many to download */
int first_hebrew = FIRST_HEBREW; /* First right-to-left */
int last_hebrew; /* Last right_to_left char. */
int line_width = DEF_WIDTH; /* Printer line width */
int default_direction = RIGHT_TO_LEFT;
char input[MAX_COLUMNS + 1]; /* Text read here */
char output[MAX_COLUMNS + 1]; /* Printer line built here */
#if DEBUG
int debug = FALSE;
#endif
/*
* The "ISO" values are for ECMA-121 (8-bit Latin/Hebrew Alphabet)
* It is being submitted to ISO for standardization.
* Characters from FB to FF (15/11 to 15/15) are my Yiddish hacks.
* Note that I don't handle a couple of charcters needed for Yiddish.
* The Yiddish and Hebrew transliterations are slightly different.
* Those marked with an asterisk are handled.
*
* * Pasakh alef [a] Aleph with an underbar
* * Komets alef [o] Aleph with a Komets (small 't') diacritic
* Melpum vov [u] Dotted Vav
* Khirik Yud [i] Yud with a dot underneath
* * Pasakh tsvey yudn [ay] Two Yud with a joining underbar.
* * Beyz [b] Dotted Bet
* Kof [k] Dotted Koph
* * Pey [p] Dotted Fey
* Tof [t] Dotted Sof
*/
#if ISO_HEBREW || ASCII_7BIT_HEBREW || ASCII_UPCASE_HEBREW
char charset[MAXCHAR][9] = {
/* 0 1 2 3 4 5 6 7 8 ISO */
0x00, 0x4E, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x72, 0x00, /* Aleph E0 */
0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x02, /* Bet/Veyz E1 */
0x00, 0x00, 0x46, 0x08, 0x50, 0x00, 0x7E, 0x00, 0x00, /* Gimel E2 */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, 0x00, 0x40, /* Dalet E3 */
0x4E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* He E4 */
0x00, 0x00, 0x00, 0x40, 0x00, 0x7E, 0x00, 0x00, 0x00, /* Vav E5 */
0x00, 0x00, 0x00, 0x40, 0x30, 0x4E, 0x00, 0x00, 0x00, /* Zain E6 */
0x7E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* Het E7 */
0x7E, 0x00, 0x02, 0x00, 0x02, 0x30, 0x42, 0x00, 0x7E, /* Tet E8 */
0x00, 0x00, 0x00, 0x40, 0x00, 0x70, 0x00, 0x00, 0x00, /* Yod E9 */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7F, /* Term Koph EA */
0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Koph EB */
0x00, 0xC0, 0x00, 0x42, 0x00, 0x44, 0x08, 0x70, 0x00, /* Lamed EC */
0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Term Mem ED */
0x00, 0x66, 0x18, 0x20, 0x40, 0x00, 0x42, 0x00, 0x7E, /* Mem EE */
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7F, 0x00, 0x00, /* Term Nun EF */
0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x00, /* Nun F0 */
0x00, 0x7C, 0x02, 0x40, 0x02, 0x40, 0x02, 0x44, 0x38, /* Samech F1 */
0x02, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, /* Ayin F2 */
0x70, 0x00, 0x50, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7F, /* Term Pe F3 */
0x72, 0x00, 0x52, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Pe/Fey F4 */
0x00, 0x7F, 0x00, 0x08, 0x00, 0x10, 0x20, 0x40, 0x00, /* Term Sade F5 */
0x00, 0x62, 0x10, 0x0A, 0x00, 0x12, 0x28, 0x46, 0x00, /* Zade F6 */
0x00, 0x40, 0x1E, 0x40, 0x00, 0x44, 0x08, 0x70, 0x00, /* Koph F7 */
0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x3E, 0x00, /* Resh F8 */
0x7E, 0x00, 0x0A, 0x10, 0x62, 0x00, 0x02, 0x00, 0x7E, /* Shin F9 */
0x02, 0x00, 0x7E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* Taw FA */
0x00, 0x4E, 0x30, 0x01, 0x18, 0x01, 0x0C, 0x72, 0x00, /* Pasach Al FB */
0x00, 0x4E, 0x30, 0x02, 0x19, 0x02, 0x0C, 0x72, 0x00, /* Kometz Al FC */
0x42, 0x10, 0x42, 0x10, 0x42, 0x00, 0x7E, 0x00, 0x02, /* Beyz FD */
0x00, 0x40, 0x01, 0x70, 0x01, 0x00, 0x41, 0x00, 0x71, /* Pas 2 yud FE */
0x72, 0x00, 0x52, 0x08, 0x42, 0x08, 0x42, 0x00, 0x7E /* Pe FF */
/* 0 1 2 3 4 5 6 7 8 ISO */
};
#endif
#if ATARI_HEBREW
char charset[MAXCHAR][9] = {
/* 0 1 2 3 4 5 6 7 8 Atari */
0x00, 0x4E, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x72, 0x00, /* Aleph C2 */
0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x02, /* Bet/Veyz C3 */
0x00, 0x00, 0x46, 0x08, 0x50, 0x00, 0x7E, 0x00, 0x00, /* Gimel C4 */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, 0x00, 0x40, /* Dalet C5 */
0x4E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* He C6 */
0x00, 0x00, 0x00, 0x40, 0x00, 0x7E, 0x00, 0x00, 0x00, /* Vav C7 */
0x00, 0x00, 0x00, 0x40, 0x30, 0x4E, 0x00, 0x00, 0x00, /* Zain C8 */
0x7E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* Het C9 */
0x7E, 0x00, 0x02, 0x00, 0x02, 0x30, 0x42, 0x00, 0x7E, /* Tet CA */
0x00, 0x00, 0x00, 0x40, 0x00, 0x70, 0x00, 0x00, 0x00, /* Yod CB */
0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Koph CC */
0x00, 0xC0, 0x00, 0x42, 0x00, 0x44, 0x08, 0x70, 0x00, /* Lamed CD */
0x00, 0x66, 0x18, 0x20, 0x40, 0x00, 0x42, 0x00, 0x7E, /* Mem CE */
0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x00, /* Nun CF */
0x00, 0x7C, 0x02, 0x40, 0x02, 0x40, 0x02, 0x44, 0x38, /* Samech D0 */
0x02, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, /* Ayin D1 */
0x72, 0x00, 0x52, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Pe/Fey D2 */
0x00, 0x62, 0x10, 0x0A, 0x00, 0x12, 0x28, 0x46, 0x00, /* Zade D3 */
0x00, 0x40, 0x1E, 0x40, 0x00, 0x44, 0x08, 0x70, 0x00, /* Koph D4 */
0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x3E, 0x00, /* Resh D5 */
0x7E, 0x00, 0x0A, 0x10, 0x62, 0x00, 0x02, 0x00, 0x7E, /* Shin D6 */
0x02, 0x00, 0x7E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7E, /* Taw D7 */
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7F, 0x00, 0x00, /* Term Nun D8 */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7F, /* Term Koph D9 */
0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, /* Term Mem DA */
0x70, 0x00, 0x50, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7F, /* Term Pe DB */
0x00, 0x7F, 0x00, 0x08, 0x00, 0x10, 0x20, 0x40, 0x00, /* Term Sade DC */
/* 0 1 2 3 4 5 6 7 8 Atari */
};
#endif
char acute[1][9] = {
0x00, 0x00, 0x20, 0x40, 0xA0, 0x40, 0x80, 0x00, 0x00 /* Acute accent */
};
#if ATARI_ST
#define PUTPRN(c) Bconout(BC_PRT, (int) c) /* Output to printer */
#else
#define PUTPRN(c) putchar(c) /* Output to stdout */
#endif
#define DC1 0x11 /* Awaken printer */
#define ESC 0x1B
main(argc, argv)
int argc;
char *argv[];
{
get_number_of_characters();
argc = getoptions(argc, argv);
#if LOAD_PRINTER
setup_printer();
#endif
if (argc <= 1)
printfile(stdin);
else {
while (argc > 1) {
if (freopen(argv[1], "r", stdin) == NULL) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
else {
printfile(stdin);
}
--argc;
++argv;
}
}
#if LOAD_PRINTER
unsetup_printer();
#endif
exit(EXIT_SUCCESS);
}
/*
* Do the printing
*/
printfile(fp)
FILE *fp;
{
register char *tp;
int old_mode;
int primary_direction;
old_mode = letter_quality(nlq_mode);
primary_direction = default_direction;
while (fgets(input, sizeof input, fp) != NULL) {
if ((tp = strchr(input, '\n')) != NULL)
*tp = EOS; /* Erase newline */
if (streq(input, "*h"))
primary_direction = RIGHT_TO_LEFT;
else if (streq(input, "*e"))
primary_direction = LEFT_TO_RIGHT;
else {
printline(input, primary_direction);
}
}
letter_quality(old_mode);
}
printline(text, isright)
char *text; /* Remove the newline first */
int isright; /* Assumed line direction */
{
register char *op;
register HLIST *hp;
register int column;
h_format(text, strlen(text), isright);
/*
* Now, we have a formatted line. Walk the list and generate
* a character string (with leading blanks if it's right->left).
*/
hp = h_listhead.h_next;
column = 0;
if (isright) {
/*
* Working from the right end of the output line, copy characters
* from the formatted list. Then, fill the left end of the line
* with blanks. When done, op points to the left edge of the
* display line.
*/
op = output + sizeof output;
*--op = EOS;
while (op > output && hp != &h_listhead) {
*--op = hp->h_char;
hp = hp->h_next;
column++;
}
while (column < line_width && op > output) {
*--op = ' ';
column++;
}
}
else {
/*
* Working from the left edge of the output line, copy characters
* from the formatted list. Then, terminate the line. When
* done, op is set to point to the start of the display line.
*/
op = output;
while (op < &output[sizeof output] && hp != &h_listhead) {
*op++ = hp->h_char;
hp = hp->h_next;
column++;
}
*op = EOS;
op = output;
}
#if DEBUG
if (debug)
printf("line(%d)\n%s\n", strlen(op), op);
#endif
#if ATARI_ST
while (*op != EOS)
PUTPRN(*op++);
PUTPRN('\r');
PUTPRN('\n');
#else
puts(op);
#endif
}
int
getoptions(argc, argv)
int argc;
char *argv[];
{
register int i;
register int j;
register char *ap;
for (i = j = 1; i < argc; i++) {
ap = argv[i];
if (*ap == '-') {
switch (*++ap) {
#if DEBUG
case 'd':
++debug;
break;
#endif
case 'e':
default_direction = LEFT_TO_RIGHT;
break;
case 'h':
default_direction = RIGHT_TO_LEFT;
break;
case 'n':
nlq_mode = TRUE;
break;
case 'w':
line_width = atoi(++ap);
if (line_width <= 0
|| line_width >= sizeof (output)) {
fprintf(stderr, "Bad line width (%s) %d, %d used\n",
argv[i], line_width, DEF_WIDTH);
line_width = DEF_WIDTH;
}
break;
case 's':
first_hebrew = atoi(++ap);
if (first_hebrew < ' '
|| (first_hebrew + nhebrew) > 255) {
fprintf(stderr, "Bad Hebrew character range start %d,",
first_hebrew);
fprintf(stderr, ", using %d\n", FIRST_HEBREW);
first_hebrew = FIRST_HEBREW;
}
break;
default:
fprintf(stderr, "Ignoring unknown option \"%s\"\n",
argv[i]);
break;
}
continue;
}
else {
argv[j++] = ap;
}
}
argv[j] = NULL;
return (j);
}
get_number_of_characters()
{
register int i;
register char *info;
for (nhebrew = 0; nhebrew < MAXCHAR; nhebrew++) {
info = charset[nhebrew];
for (i = 0; i < 9; i++) {
if (*info++ != 0)
goto next_char;
}
break;
next_char: ;
}
last_hebrew = first_hebrew + nhebrew - 1; /* Last valid */
}
#if LOAD_PRINTER
setup_printer()
{
register int i;
reset_printer();
PUTPRN(ESC);
PUTPRN('m'); /* Select printer mode */
PUTPRN('3'); /* IBM Printer Mode II */
PUTPRN(ESC); /* Configure for 8-bit */
PUTPRN('#'); /* transparent mode. */
for (i = 0; i < nhebrew; i++)
load_printer(i + first_hebrew, charset[i]);
#if ATARI_HEBREW
load_printer(0xBA, ´[0][0]);
#endif
#if ISO_HEBREW
load_printer(0xB8, ´[0][0]);
#endif
}
load_printer(c, info)
int c;
register char *info;
{
register int i;
PUTPRN(ESC); /* Download character */
PUTPRN('y'); /* set it here */
PUTPRN(c); /* This character */
for (i = 0; i < 9; i++)
PUTPRN(*info++);
}
unsetup_printer()
{
register int i;
for (i = 0; i < nhebrew; i++) {
PUTPRN(ESC); /* Download character */
PUTPRN('z'); /* remove it here */
PUTPRN(i + first_hebrew);
}
PUTPRN(ESC);
PUTPRN('m'); /* Select Printer Mode */
PUTPRN('0'); /* Standard Mode */
reset_printer();
}
#endif
test()
{
register int i;
int old_mode;
old_mode = letter_quality(nlq_mode);
for (i = 0x20; i <= 0x7F; i++) {
if ((i % 32) == 0) {
PUTPRN('\r');
PUTPRN('\n');
}
PUTPRN(i);
}
PUTPRN('\r');
PUTPRN('\n');
letter_quality(old_mode);
}
int
letter_quality(new_mode)
int new_mode; /* TRUE for l.q. mode */
{
#if ATARI_ST
static int current_mode = FALSE; /* draft/nlq mode */
int previous_mode = current_mode;
PUTPRN(ESC);
if (new_mode)
PUTPRN('n'); /* NLQ mode */
else {
PUTPRN('P'); /* Draft mode */
}
current_mode = new_mode;
return (previous_mode);
#else
return (new_mode);
#endif
}
reset_printer()
{
PUTPRN(DC1); /* Awaken */
PUTPRN(ESC);
PUTPRN('@');
PUTPRN(DC1); /* Awaken again */
}
T.R | Title | User | Personal Name | Date | Lines |
---|
452.1 | | RAWFSH::MAHLER | Michael | Digital Telecommunications Engineering | Thu Apr 14 1988 17:29 | 6 |
|
You should have started before I was born....
|
452.2 | I have done the MicroEMACS procedure | MPGS::ORNSTEIN | Ian Ornstein | Thu Apr 14 1988 18:34 | 11 |
| I have written a �EMACS procedure to key Hebrew.
I'll try to post it later tonight. There is a small
problem...unless you look at it on a screen that substitutes
the Hebrew characters for the Greek ones, you will be quite
confused ;-) Also, my substitutions are the ones for the
I*M character set not the 7 bit compatable one that DEC uses.
- Ian -
|
452.3 | ivrit.rc | MPGS::ORNSTEIN | Ian Ornstein | Thu Apr 14 1988 22:34 | 149 |
| ;
39 store-macro
write-message "[Hebrew (�����) Mode Enabled]"
update-screen
set %ivrit TRUE
!while %ivrit TRUE
set %data >key
!if &EQual &asc %data 7
write-message "[English Mode Restored]"
set %ivrit FALSE
!return
!endif
!if &EQual &asc %data 13
end-of-line
newline
next-line
!endif
!if &EQual &asc %data 9
handle-tab
!endif
!if &SEQual %data " "
insert-string " "
!goto backup
!endif
!if &SEQual %data "a"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "b"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "c"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "d"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "e"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "f"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "g"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "h"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "i"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "j"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "k"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "l"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "m"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "n"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "o"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "p"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "q"
insert-string "/"
!goto backup
!endif
!if &SEQual %data "r"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "s"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "t"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "u"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "v"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "w"
insert-string "'"
!goto backup
!endif
!if &SEQual %data "x"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "y"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "z"
insert-string "�"
!goto backup
!endif
!if &SEQual %data "."
insert-string "�"
!goto backup
!endif
!if &SEQual %data ","
insert-string "�"
!goto backup
!endif
!if &SEQual %data "/"
insert-string "."
!goto backup
!endif
!if &SEQual %data ";"
insert-string "�"
!goto backup
!endif
*backup
backward-character
update-screen
!endwhile
!endm
|