COMPUTER INPUT SYSTEM
Field of the Invention The present invention relates to pen and brush input for electronic tablets or displays and software for controlling and speeding up input through pen, brush and keyboard text input systems, user identification and point of sale/teller systems.
Background of the Invention The computer industry has developed a number of writing tablets and light pens to allow a user to interact with a computer in a rough approximation of putting pen to paper. Such devices generally give a line of fixed width in response to user input. Some newer devices include a pressure sensitivity, but no system has been developed that emulates a pen or brush in a natural way. No one has found a natural way to increase input speed for either pens or keyboard input. In addition, the user must be identified in order to operate most stroke recognition, point of sale and automatic teller systems.
Summary Of The Invention
The invention consists of hardware embodiments for determining the position of a drawing tool in relation to a display incorporated in a writing tablet. The invention includes software components for identifying the pen user including kernal information for complete or partial stroke recognition and communication, particularly useful for completion of point of sale or debit transactions. A preferred drawing tool takes the form of a pen or brush and herein generally will be referred to as a pen. The present invention provides a pen-based computer input system comprising a pen and tablet. The writing tablet includes a writing surface with a pixel array connected to a host processor, which may be incorporated in the writing tablet. The pen includes an optical input connected through an optical sensor to a pen controller. The pen controller, in turn, is connected to an output device which can be directly or capacitively coupled to a remote receiver. The tablet may include or be connected to a receiver designed to receive information from the pen or brush. One form of receiver is a transparent, resistive sheet essentially covering the pixel array. The host processor can control the pixel display to illuminate pixels near the pen, thereby communicating with the pen, and the pen can communicate with the host processor through the output device and remote receiver. When the user brings the pen to the writing surface, the host can display pixels under the pen, leaving a trail of electronic ink and giving the user the feel of actually writing. By displaying a wider path of pixels when the user presses the pen more firmly, the effect can approximate writing with a fine fountain pen. The process of stroke processing is illustrated in the flowchart of Figure 1.
Optical means in the pen or brush provide information about drawing tool angle and pressure and brush bristle flex and spread. Logic and or microprocessors in the pen or brush body act alone or in conjunction with software in a host computer to provide stroke processing and estimate or refine the position of the pen nib or brush bristles on the tablet surface.
Software in the host also acts to increase input speed by providing a method for abbreviating common or frequently used words, phrases or text sections from either keyboard or pen sources and to suggest new abbreviations by evolving strokes from often used words as distinct from the overall stroke history and letter abbreviations from the overall word and phrase history. The expansion process is illustrated by the flowchart of Figure 2.
One object of the invention is to provide a set of stroke parameters peculiar to the user and an associated personal identification which can be stored in the pen to allow optimal stroke recognition in a host system, including a new host when the user first uses it.
Another object of the invention is to provide a system in which, pen position hardware cost is nύnimized in the tablet and host and an electronic pen cartridge is created suitable for inclusion in a wide variety of pen body styles, diameters and weights by many different suppliers.
Another object of the invention is to provide a dual function device which may contain a drawing tool of this invention plus a traditional writing device such as a fountain pen or ball point pen, a graphite pencil or eraser or a second drawing tool of this invention.
Brief Description Of The Drawings
Figure 1 is a overview flow chart of the pen and input accelerator system. Figure 2 is a detailed flow chart of the accelerator input software subsystem. Figure 3 is a side view of the pen and tablet. Figure 4 is a top view of the tablet and display.
Figure 5 is a detailed view of the tablet and writing surface.
Figure 6 is a detailed sectional view of a pen nib and of a brush and its active elements.
Figure 7 is a view of the pen body and an enlarged view of the nib and its electronic elements, Figure 8 is a block diagram showing the interaction of a host computer, tablet and writing tip.
Detailed Description Of The Invention The present invention consists of two major components - stroke entry and character handling. Stroke entry involves detecting the presence of a writing instrument near a writing tablet and selectively turning on pixels in the tablet to reflect the user's actions, effectively applying "electronic ink." Once a character is complete, that character is analyzed to detect special encoding and to speed information entry. The present invention preferably utilizes the tablet illustrated Figures 4 and 5. Tablet 50 includes a raster display of individually addressable pixels 100 arranged in rows and columns. The pixels can be of most any type of conventional manufacture, including LCD, ferroelectric liquid crystal, phosphor or other type known in the industry. The tablet writing surface 51 is covered by a relatively transparent, resistive sheet 53, which can be a metal such as gold or a metal oxide such as indium tin oxide. The resistive sheet may be the topmost layer of the display or it may be covered with a protective layer 54, illustrated in Figure 5. The conductive sheet is connected to conductive sensors 52A, 52B at opposite ends of the writing surface. The conductive sensors 52A,
52B are connected in turn to circuitry which calculates the relative strength of a signal generated by the pen as picked up by the two conductive sensors and then connected to the host computer (not shown). This allows the ratiometric determination of the approximate position of the pen along one dimension of the writing surface. This signal also carries information from the pen. Referring to Figures 7A and 7B, pen 30 includes writing tip 31, which can be manufactured as an interchangeable insert adapted to pen barrels of many manufacturers. Writing tip 31 consists primarily of support 40 which carries conductive nib 36 and light guides 35A, 35B which are optically coupled to photodetectors 34A, 34B which are connected in turn via leads 42 to controller 33. Nib 36 is a conductive or semi-conductive material such as pen brass terminated by tip 39, constructed of a material which provides a pleasing feel on the "writing" surface of tablet 50. Either or both photodetectors 34A and 34B independently detect light, each carrying an external signal to controller 33 in a manner well known in the art. For example, some methods used in photo-optical isolation devices can be utilized in the present invention. Battery 32 provides power for all components of writing tip 31. Controller 33, preferably an ASIC chip, controls and receives information from photodetectors 34A, 34B and transmits information to nib 36 through lead 43 and coupling pin 37. Controller 33 can send information to a host computer through a direct cable connection (not shown) but preferably broadcasts a signal through nib 36. If nib 36 is sufficiently close to resistive sheet 53, a signal generated by controller 33 is transmitted through nib 36 using direct or capacitive coupling through resistive sheet 53 and conductive sensors 52A, 52B to appropriate circuitry and thence to the host computer.
Referring to Figure 6, an alternative input device consists of electronic brush 29. Brush 29 includes "bristles" in the form of a fiber optic bundle of fibers 26 constrained by collar 27 and coupled to photodetector array 28. Each fiber 26 is coated with a conductive film or alternately (not shown) interspersed with conductive flexible wires. Brush collar 27 constrains the fiber and blocks extraneous light. Photodetector array 28 may be a linear or area array, with elements connected to a controller 33 (not shown) which in turn can transmit electronic signals through conductive fibers 26 in a manner closely analogous to the actions of writing tip 31. The system and method of this invention will be generally described using writing tip 31 as an example, but one skilled in the art will understand how to apply brush 29 in a similar manner. Referring to Figure 8, the host can communicate with controller 33 by cycling the on-off state of pixels 100 in tablet 50. The host can selectively activate pixels 100 and compare timing of pixel illumination versus return signals from controller 33, through nib 36 and resistive sheet 53, to determine where the pen is located, using techniques well known for interacting with prior art light pens. Since the pen contains photo-detectors 34A and 34B, each photodetector can pickup signals from separate illuminated pixels which can provide information about the angle of nib 36 on tablet 50. In addition, combinations of controlled pixel illumination and detection schemes in writing tip 31 can provide information about the proximity of writing tip 31 to tablet 50. This information can be used to vary the width of a stroke to be illuminated by pixels according to the pressure applied by the user. A brush, as illustrated in figure 6, can receive signals through multiple sensors, providing information about the location of each bristle. For any drawing tool, any pixel which is sufficiently close to the tool can be maintained in the "on" state. The net result
is the application of "electronic ink" which reflects the angle and pressure of the user's writing actions.
The input system can detect the location of the drawing tool in relation to the writing tablet including which pixels are closest to any component of the pen and which pixels near the pen may be weakly interacting with the pen. This allows calculation of the timing, pressure and angle of each stroke as it is applied. This information can be used to derive stroke kernal information which can be compared with recorded stroke kernal information or other information to identify the user. This may be used for identification of an individual, to select a certain stroke recognition sequence, or otherwise used to facilitate interaction of a user with a stroke recognition system. Recorded stroke information may be stored in a central host, for example a computer tied to a series of ATM or point of sale systems, in a host controller in the tablet, or in the local controller in the pen. There may be multiple stored patterns for a single user, or there may be multiple stored patterns for a series of users, who might for example share a single pen. Alternately the controller can transfer user signature identification information to the host. The controller may act to confirm a transaction from the host and contain stored information about the user's credit limit or debit account which is updated by the host with each transaction.
In using brush 29, fibers 26 are in optical contact with the pixels as they are changed which is detected by photodetector array 28. Thus brush 29 has the ability to sense individual "bristle" contact and contact angle to provide the same qualities of use as a normal paintbrush. A writing implement of this invention can be personalized to contain user identification information as well as information about user preferences and writing habits. This information can be stored in memory, e.g. EPROM, connected to controller 33 so that pen 30 or brush 29 can be used with multiple tablets 50 effectively interchangeably.
Referring to Figure 6, pixels 100 are cycled at times known to the host computer. Pen nib 36 with light guides 35A and 35B under the tip (not shown in Figure 6) "see" a series of pixel elements. As the pixels are cycled the position of the nib and its angle with the paper is determined by coordinating the pixel change with the sensed light through the pen. In addition as the nib pressure increases the light guides make greater contact with more pixels which provides pressure information to the pen system. When writing tip 31 is activated, for example by being held by the user, it repeatedly transmits stored user identification and key parameters. When writing tip 31 is held sufficiently close to tablet 50, the host "wakes up" and begins processing input. The host can read and store the user identification and key parameters. The host can activate pixels 100 on tablet 50. The signal from writing tip 31 is picked up through resistive sheet 53 by conductive sensors 52 A and 52B producing two signal amplitudes according to distances 20 and 21 between pen 30 and conductive sensors 52A and 52B. The ratio of these signal amplitudes provides a precise location of pen 30 along the tablet surface. The host uses this information to flick on pixels sequentially across the tablet surface while collecting the detected changes as described above. Once position, nib angle and pressure are determined, the information is passed to subroutines which update the display to show the proper flow of electronic "ink. " Stroke recognition is used to identify and convert the character input by the user. Conventional character recognition programs can perform
basic character conversion but the stroke information regarding angle, pressure and other information provided by the new pen input system can facilitate character recognition.
One means for ratiometric positioning in one dimension has been described in detail above. Other ratiometric means include determining a resistance, a capacitance, or an appropriate electromagnetic value in the X dimension, the Y dimension, or both dimensions, preferably simultaneously or nearly so. A sonic position evaluation system may be used, as may an active optical position evaluation method.
In an alternate embodiment in conjunction with an adequately fast display (such as ferroelectric liquid crystals, gas plasma, etc.) pen or brush position may be entirely determined by sequentially flicking (turning on and off or XOR'ing) pixels only while monitoring the response of the pen (brush). In this embodiment, transparent resistive film 18 (Figure 4) is not required, but it may still serve as the primary communications channel of the system.
The system allows rapid determination of a drawing tool's location by first performing a coarse search, then refining the search until a specific pixel or group of pixels in the immediate vicinity of the drawing tool can be identified.
Traditional means of identifying the position of a light pen or similar pointing device is to activate all pixels in a display sequentially, usually by a regular raster scan, then signalling a host computer when the pointing device has detected an activated pixel. This timing information can be coordinated with information about the raster driver to derive the position of the pointing device. Traditional pointing devices are crude equivalents of the drawing tool of the present invention but the principles for locating the precise location of an older pointing device or the new drawing tool are similar. The coarse search of this invention improves this old method by locating the approximate position of the drawing tool and only pixels near the drawing tool need be tested in order to locate the precise location of the drawing tool. A new means of approximating the location of the drawing tool is a pattern search.
Selected regions of the writing tablet can be activated selectively and the drawing tool can be monitored for a response. Where a response is detected, the corresponding region can be subdivided into smaller patterns which can be tested again, then subdivided as much as necessary until the precise location of the drawing tool is determined. One potential set of patterns is a traditional binary tree search where half the display is activated, then the other half. The half in which the drawing tool is located is then subdivided into two portions, and the process is repeated until the position is sufficiently determinate. This pattern matching does not rely on raster scanning and is best performed with a device that can randomly address pixels, either singly or in groups. This method of coarse positioning is also useful with existing precision positioning devices such as digitizing tablets. Current devices can be modified to utilize and benefit from coarse positioning through minimal modification of the hardware or software drivers.
Once the approximate location of the drawing tool has been determined, specific pixels in the approximate area can be activated while responses from the drawing tool are monitored. The system can continue to test pixels in that approximate area while the drawing tool is in contact or approximate contact with the writing tablet, enabling the system to follow which pixels are near the drawing tool at times in the future. If the drawing tool is moved away from the writing surface,
as between words or between some strokes, the system can continue to monitor the general area of the last stroke. It is convenient to think of the approximate location of the drawing tool as a "bubble" which expands or contacts depending on the state of the system. The system should test pixels within the bubble with sufficient frequency to track changing states of the drawing tool in relation to the writing surface.
One skilled in the art can readily set a frequency of pixel testing and a range of pixel locations to test during various operating states, including: no drawing tool near the writing tablet, a drawing tool in contact with the writing tablet, a slowly or rapidly moving drawing tool, a drawing tool recently in contact with the writing tablet, and other states of interest. For example, when the drawing tool is moving slowly, then the bubble can be rather small and the sampling frequency can be relatively low. If the drawing tool is moved away from the writing tablet, the bubble can be checked periodically within an expanding bubble, the expectation being that there is a high initial probability that the drawing tool will be returned in the vicinity of the previous stroke, but the probability of returning to that specific or general location decreases with time. At some point, the system resumes the general pattern testing to identify when the drawing tool does return and then to locate the position of the drawing tool.
Once a character has been input, it is processed according to the following steps. Each character is placed in a character buffer. The Fasthand software then takes this character (whether from pen, brush or keyboard source) to perform the input acceleration and shorthand functions illustrated in Figure 2. An input character is first tested to see if it is a special character of some sort including an ideograph or evolved stroke set. If not, the character is placed in a word buffer and the next character is accepted. If the input character is a normal word terminator, such as space, comma, period (followed by space) or other punctuation, the text contents of the word buffer are examined. The word terminator is combined with the text and the text is tested to see if it matches any of a list of abbreviations, stored, for example, in a look up table. If any matches are found, the corresponding expanded text is substituted for the abbreviated text and output and processing continues with the next character in the input stream.
If there are no exact matches for the text and the known abbreviations, then the text is examined for prefix or suffix abbreviations. The first two or three letters are tested against a table of known prefix abbreviations and if a prefix abbreviation is found, the corresponding expanded prefix is substituted in the text. In a similar fashion, the last letters of the text are tested against either a suffix algorithm or a user updatable table of suffix abbreviations or both and any corresponding suffixes are substituted in the text regardless of whether the first portion of the word has been abbreviated. In a preferred embodiment, the last letter of a word or entry may be capitalized using the conventional shift key or caps lock, signalling to the controller that the user desires a suffix expansion using an available algorithm or table entry. The text is then output and processing continues with the next character in the input stream.
One or more special characters can be interpreted as commands. In the preferred implementation, the equals sign is used to enter new abbreviations in the abbreviation table. Any text, generally a series of characters, followed by an equals sign, with no intervening space, is treated as a new abbreviation and any text following the equals sign, including spaces or other punctuation, up to the next equals sign following a non-space character, is treated as the
corresponding expanded text. The new abbreviation and corresponding expansion are stored with other known abbreviations for subsequent interpretation.
Another useful command causes the processor to cease interpreting the subsequent word or series of words. One could develop an elaborate language of special symbols to implement various control and interpretation functions. Each of these command schemes are encompassed within the claims of the present invention.
Another useful command uses an up arrow (*) as an alternative way to set "caps lock" on, causing any text following it to be capitalized. This may also be accomplished by setting the caps lock directly. Words which are not expanded, in other words, which have no abbreviation, either in whole or in part, are examined for potential abbreviation. Each non-abbreviated word is entered in a history table, setting a frequency flag for that word or incrementing a counter associated with that word. If the count is high enough then a proposed abbreviation is shown via pop-up to the user. Alternately for stroke based characters the stroke collection making up the letters and/or ideographs in the word are sorted and reduced to a unique related subset which is presented to the user as a suggested new efficient form. A fully spelled out word elicits a pop-up window with the abbreviation from the table as a teaching tool and as a reminder.
A batch program periodically analyzes the history table creates a frequency table and suggests abbreviations for text from other sources, or from abbreviations previously created by the user.
Source code for one implementation of this process is included as Example 1. This source code carries out the novel features of the software but does not include all of the code for basic functions or unrelated prior art software which is used in the actual device and method.
A general description of a device and method of using the present invention as well as a preferred embodiment of the present invention has been set forth above. One skilled in the art will recognize and be able to practice additional variations in the methods described and variations on the device described which fall within the teachings of this invention.
Example 1:
#include <stdio.h> #include <stdlib.h> #include <string.h>
#include "pcstuff.h" #include "ab.h" #include "Iϊst.h" /***Copyright 1992 Electronic Ink, Inc ********************************/ int PrefixCount = 0; intDefCount = 0; int SuffixCount = 0; int ShortCount = 0;
PTR Abbreviations| AX DEFS];
PTR Words[MAX_DEFSr; char *ShortWords[MAX_SHORTS];
PTR Prefixes[MAX PREFIXES]; PTR PreAbbrevs[MAX_PREFlXES];
PTR Suffixes[MAX SUFFDiES]; PTR SufAbbrevs[MAX_SUFFlXES];
This program uses two independently sorted arrays of pointers to nodes. One array is sorted by Abbreviations, and the other list is sorted by Words. This allows us to use a binary search on both Words and Abbreviations.
/*****************≠****Li},j]37D LIST OPERATIONS *************************/ /*
MakeNodeO mallocs space for and returns a pointer to a list node, initiallizin the fields to the specified character string parameters */ PTR MakeNode( char * Word, char * Abbrev, int objtype )
NODE * nodeptr ; /* Points to allocated node - returned to caller */ int TextSize; char TextPtr;
/* Make the node */ if ( ( nodeptr = (PTR) HeapAllocate ( sizeof (NODE) ) ) = = NULL ) return (NULL); }
TextSize = strlen (Word) + strlen (Abbrev) + 2; TextPtr = (char *)HeapAllocate (TextSize); if (NULL == TextPtr) {
HeapFree (nodeptr); return (NULL);
} nodeptr->word — TextPtr; strcpy (nodeptr->word, Word);
nodeptr- > abbrev = nodeptr- > word + strlen (Word) + 1; strcpy (nodeptr- > abbrev, Abbrev);
/* Initialize type and lengths */ nodeptr- > type = objtype ; nodeptr- >WordLength = strlen (Word); nodeptr- > AbbrevLength = strlen (Abbrev); nodeptr- >UseCount = nodeptr- >WarnCount = 0; nodeptr- >TempFlag = 0; return( nodeptr ) ;
/* MakeShortNodeO mallocs space for and returns a pointer to a list node, initiallizing the fields to the specified character string parameters
*/ char * MakeShortNode( char * Word ) { char * nodeptr ; /* Points to allocated node - returned to caller */
/* Make the node */ if ( ( nodeptr = (char *) HeapAllocate ( strlen (Word) + 1) ) = = NULL ) { return (NULL);
strcpy (nodeptr, Word); return( nodeptr ) ;
/* InitListO initializes the arrays of pointers */ void InitList (void) int i; for (i = 0; i < MAX 3EFS; i++)
Wordsp] = Abbreviations!!] = NULL; for (i = 0; i < MAX_PREFIXES; i+ +)
Prefixesp] = PreAbbrevsp] = NULL; for (i = 0; i < MAX SUFFIXES; i++)
Suffixes[i] = SufAb"brevs[i] = NULL;
InitHeap 0;
int WordSortFunction ( const void *a, const void *b)
PTR APtr, BPtr;
void ResortPreSuffixes (void) /*** Sort prefix lists ***/ qsort ( (void *) Prefixes, PrefixCount, sizeof (Prefixes[0]), WordSortFunction); qsort ( (void *) PreAbbrevs, PrefixCount, sizeof (TreAbbrevs[0]), AbbrevSortFunction);
/*** Sort suffix lists ***/ qsort ( (void *) Suffixes, SuffixCount, sizeof (Suffixes[0]), WordSortFunction); qsort ( (void *) SufAbbrevs, SuffixCount, sizeof (SufAbbrevs[0]), AbbrevSortFunction); *********************************4:*******
PTR AddNode (char *Word, char *Abbrev, PTR *WordList, PTR *AbbrevϊationList, int *ItemCount, int Type)
PTR Node;
char * AddShortNode (char *Word, char **WordList, int *ItemCount) char *Node;
PTR AddWord (char *Word, char *Abbrev, int Type, int ResortFlag)
PTR Result; Result = AddNode (Word, Abbrev, Words, Abbreviations, &DefCount, Type); if (ResortFlag)
ResortWordLists 0; return (Result);
void BuUdList ( FILE *wordfile ) int type; char buffer[ MAXWORDSIZE ] ; char word[ MAXWORDSIZE ] ; char abbrev[ MAXWORDSIZE ] ; char *ChrPtr;
InitList 0 ;
MaxSuffixLength = 0; while( fgets( buffer, MAXWORDSIZE, wordfile ) )
ChrPtr = &buffer[strlen(buffer)-l]; while (isspace (*ChrPtr)) /*** Skip past trailing spaces ***/
ChrPtr-;
/*** Skip to start of number ***/ while ( (isdigit (*ChrPtr)) && (ChrPtr > buffer) ) ChrPtr-; type = atoi (ChrPtr); *ChrPtr = '\0'; ChrPtr—; /*** Points to last char of abbrev ***/ while (isspace (*ChrPtr)) ChrPtr—; /*** Points to last non-space of abbrev ***/
*(ChrPtr+ 1) = '\0'; /*** Terminate abbrev ***/ while (! isspace (*ChrPtr)) ChrPtr-; /**** pomts to first non-space of abbrev ***/ strcpy (abbrev, ChrPtr+ 1); while (isspace (*ChrPtr)) ChrPtr-; /*** Points to last non-space of expansion ***/ *(ChrPtr+l) = '\0'; strcpy (word, buffer); if ( (KWORD == type) && (abbrev[0] != '9') ) AddNode (word, abbrev, Words, Abbreviations, &DefCount, type); else if (PREFK = = type)
AddNode (word, abbrev, Prefixes, PreAbbrevs, &PrefixCount, type); else if (SUFFK == type)
AddNode (word, abbrev, Suffixes, SufAbbrevs, &SuffixCount, type); else AddShortNode (word, ShortWords, &ShortCount);
ResortWordLists 0; ResortPreSuffixes 0;
int ReadWordList (char *FileName) {
FTLE *FPtr; if ( NULL == (FPtr = fopen (FileName, "r")) ) return (0); BuildList(FPtr ) ; fcIose (FPtr ) ; return (1);
int WordFindFunction ( char *a, PTR b) if (PREFIX == b-> type) return (stmicmp (a, b->word, b->WordLength) ); else /***** if (KWORD == b->type) *****/ return (stricmp (a, b->word));
int AbbrevFindFunction ( char *a, PTR b) if (PREFIX == b->type) return (stmicmp (a, b-> abbrev, b->AbbrevLength)); else /***** if (KWORD == b->type) *****/ return (stricmp (a, b-> abbrev) );
it SuffixWordFindFunction(char *Key, PTR Node)
int SuffixAbbrevFindFunction(char *Key, PTR Node) return (stricmp (Key, Node~> abbrev)); ***********************4:***************
PTR BinarySearch (char *Key, PTR *List, int Count, int CompareO) int Low, High, Mid, Comp;
else
PTR Find ( char *word, int Type )
/*** Search list for word as a word, prefix, or suffix, and set Type to the appropriate type as found. ***/ PTR NodePtr; inti, Start;
NodePtr = NULL;
/*** Search words ***/
NodePtr = BinarySearch ( word, Words, DefCount, WordFindFunction ); if (NodePtr)
Type = KWORD; return (NodePtr);
/*** Search for abbreviations ***/
NodePtr = BinarySearch (word, Abbreviations, DefCount, AbbrevFindFunction); if (NodePtr) Type = ABBREV; return (NodePtr);
/*** Search Prefixes ***/ NodePtr = BinarySearch ( word, Prefixes, PrefixCount, WordFindFunction ); if (NodePtr)
Type = KWORD; return (NodePtr); }
/*** Search for abbreviations ***/ PrefixCount, AbbrevFindFunction );
/*** Search for suffixes ***/ for (i = min (MaxSuffixLength, strlen (word) ); i > 0; i— )
Start = strlen (word) - i;
NodePtr = BinarySearch (&word[Start], Suffixes, SuffixCount, WordFindFunction); if (NodePtr)
Type = KWORD; return (NodePtr); NodePtr = BinarySearch (&word[Start], SufAbbrevs, SuffixCount, AbbrevFindFunction); if (NodePtr)
Type = ABBREV; return (NodePtr); }
return (NULL);
char *FindShort (char *Short) int i; char *Result;
Result = NULL; for (i = 0; ( (i < ShortCount) && (NULL = = Result) ); i+ +)
if (0 = = stricmp (Short, ShortWords[i]) ) /*** If a match ***/ Result = ShortWords[i]; return (Result); } int DeleteNode (PTR Node)
{ int i, Wordlndex, Abbrevlndex; if (NULL == Node) return (0);
Wordlndex = Abbrevlndex = -1; for (ϊ = 0; (i < DefCount) && ((Wordlndex < 0) 1 1 (Abbrevlndex < 0)); i+ +) if (Words[i] == Node)
Wordlndex = ϊ; if (Abbreviations!!] == Node) Abbrevlndex = i; if ( (Wordlndex < 0) | [ (Abbrevlndex < 0) ) return (0); Words[WordIndex] = Words[DefCount-l]; AbbreviationsfAbbrevIndex] = Abbreviations[DefCount-l]; DefCount-; HeapFree (Node); ResortWordLists 0; /***** DEBUG - Update MaxSuffixLengfli - DEBUG *****/ return (1);
void FormNodeString (PTR Node, char *Msg) char MaxWord[80], MaxAbbrev[80]; strncpy (MaxWord, Node->word, 22); MaxWord[18] = '\0'; stmcpy (MaxAbbrev, Node-> abbrev, 6); MaxAbbrev[6] = '\0'; sprintf (Msg, "%-22s %-6s %4d", MaxWord, MaxAbbrev, Node->UseCount);
#if 0 switch (Node->type) case KWORD: strcat (Msg, "WORD"); break ; case PREFIX: strcat (Msg, "PREFIX"); break ; case SUFFK: strcat (Msg, "SUFFIX"); break ;
#endif
/4:*:4:***:4:4:4:***4t**4:*4:4:****4t4:*:*4:4:**4:*:***^
PTR FormSuggestion (char *Word, char *Suggestion) { char NoVowels[80], *SrcPtr, *DstPtr; int i, Type, Unique; PTR Test; DstPtr = NoVowels; SrcPtr = Word;
*(DstPtr+ +) = *(SrcPtr+ +); /*** Always first character ***/ while (*SrcPtr) if ( (Istrchr ("aeiouAEIOU", *SrcPtr) ) && (ϋspunct (*SrcPtr)) )
*(bstPtr+ +) = *SrcPtr; SrcPtr+ + ;
*DstPtr = '\0';
Unique = 0; i = 2; while ( (lUnique) && (i < = strlen (NoVowels) ) ) strncpy (Suggestion, NoVowels, i);
Suggestionp] = '\0'; i+ +;
Test = Find (Suggestion, &Type); if ( (NULL = = Test) && (NULL = = FindShort (Suggestion)) )
Unique = TRUE; if (Unique) return (NULL); else return (Test);
/****: 4: : 4: : 4:*4: 4: 4: 4: 4:4:4:4:4: *:*****: 4: 4:*************^ void ExpandString (char *Str) { char *CharPtr;
PTR *WordList; int WordCount; print at (Top+1, Left+1, "Display Words", NORMAL);
;
switch ( Key ) case 'W': WordList = Words;
WordCount = DefCount; break ; case 'P': WordList = Prefixes;
WordCount = PrefixCount; break ; case 'S': WordList = Suffixes;
WordCount = SuffixCount; break ; default: WordCount = 0; break ;
ClearPopUp 0; for (i = 0; i < WordCount; i++)
FormNodeString(WordList[i], LineBuffer);
/* Pause every 22 lines of output */ print at (Top + 1 + Count, Left+ 1, LineBuffer, NORMAL); if( !(++Count%(Bottom-Top-3))) print_at (Bottom - 1, Left+l, prompt2, NORMAL ) ; bioskey (0); ClearPopUp 0;
Count = 0;
} /* end while */
Li i W dC )
{ . mt 1; char Str[80];
int SaveWordList (void) {
FILE *fPtr; /*** Delete back up file ***/ /*** Save old file ***/
#include <string.h>
#include "cscreen.h" #include "ab.h" #include "list.h" #include "history .h"
#define WORD_PROCESSOR "WP.EXE" /* Function declarations */ void syserrO ; voidHelpO ; void WriteToFileO ; /**Copyright 1992 Electronic Ink, Inc.***GLOBAL VARIABLES *************/ char *ProgramName = "Abbreviate"; char Word[ MAXWORDSIZE ]; char SearchWord [MAXWORDSIZE]; char *WordPtr = Word; int FlashDuration = 500; /** Duration of flash in milliseconds **/ int Active = TRUE; int MaxSuffixLength = 0; int DelϊmitFIag = 0; intKillFlash = 0; intKillThreshold = 2; int HistoryThreshold = 6; int RemindStart = 3; intRemindEnd = 7; int Expanding = 0; int PrevϊousKey = 0; int InPopupFIag = 0; int CRExpandFlag = TRUE; unsigned long int Keystrokes = 0; unsigned long int NonSpaces = 0; unsigned long int NetKeystrokes = 0; unsigned long int WordsTyped = 0; unsigned long int WordsWarned = 0; unsigned long int WordsExpanded = 0; unsigned long int PotentialNetKeystrokes = 0; **************************'TPD Related Variables ***********************7 unsigned ProgramSize = 5500; /*** Number of paragraphs ***/ unsigned ScanCode = 52; /*** '.' ***/ unsigned KeyMask = 8; /*** ALT ***/
void UnbufferWord (char *Word) { char *Ptr;
voidBufferWord (char *Word) char *Ptr; for (Ptr = Word; *Ptr; Ptr++)
BufferKey (*Ptr);
void ShowAbbreviation (char *Word, PTR Node, char Key) 4:*4: Remmd user mat abbreviation exists for Word ***/ char FirstChar, TempStr[MAXWORDSIZE]; if ( isupper (Word[0]) ) FirstChar = toupper( Node->abbrev[0] ) ; else FirstChar = Node->abbrev[0] ;
)
void ExpandAbbreviation (char *Abbreviation, PTR Node, char Key) char FirstChar, *CharPtr; char NewWord[MAXWORDSIZE]; strcpy (NewWord, Node- > word); ExpandString (NewWord); if ( isupper(Word[0]) )
FirstChar = toupper( NewWord[0] ) ; else
FirstChar = NewWord[0] ; if (KWORD = = Node- > type) /*** Backspace over abbreviation ***/
UnbufferWord (Abbreviation);
/*** Insert word into buffer ***/ BufferKey (FirstChar); BufferWord (&NewWord[l]); if (strlen (Abbreviation) > Node->AbbrevLength)
BufferWord (&Abbreviation[Node-> AbbrevLength]); else if ( SUFFK = = Node-> typ ) CharPtr = strstr (Abbreviation, Node-> abbrev); if (CharPtr = = Abbreviation) /*** If word begins with abbreviation ***/ return; if (CharPtr) UnbufferWord (CharPtr); /** Unbuffer suffix **/ BufferWord (NewWord); /** Expanded suffix **/ if (strlen (CharPtr) > Node- > AbbrevLength) BufferWord (&CharPtr[Node-> AbbrevLength]);
Node- > UseCount+ + ; /*** Increment use counter ***/
Expanding = TRUE;
WordsExpanded + + ;
NetKeystrokes += (Node->WordLength- Node- > AbbrevLength);
/*** Display new character ***/ BufferKey ( Key ) ;
void ExtractSearchWord (char *Word, char *SearchWord) int i; strcpy (SearchWord, Word); i = strlen (SearchWord) - 1; while ( (i > 0) && (ispunct(SearchWord[i]) ) ) SearchWordp-] = '\0';
/*******4:**************4:*************************** void ShowReminder (char *Word) char Suggestion[80], Reminder[80] ; PTR Node;
)
sprintf (Reminder, "Suggestion: Create an abbreviation for '%s'.", Word); FlashWord (Reminder, FlashDuration);
int ProcessKey (WORD Key, WORD ShiftMask)
PTR nodeptr; char *cptr ; int type; int MaskedKey; char Msg[80];
MaskedKey = Key & Oxff; if ( (Expanding) && (isprint (MaskedKey)) && (IlnPopupFlag)
return (Prev ousKey = ey ;
*WordPtr = EOW; /*** Terminate abbreviation ***/ if (Word = = WordPtr) return (PreviousKey = Key); #ifdef TEST
PopUp (ASSIGN POPUP);
BufferKey (BACK_SCAN); /*** Back over ASSIGN_KEY ***/
UnbufferWord (Word); /*** Back over abbreviation ***/
WordPtr = Word; /*** Clear word buffer ***/ *WordPtr = EOW;
BufferKey (BACK_SCAN); /*** Back over ASSIGNJ EY ***/ UnbufferWord (Word); /*** Back over abbreviation ***/ SeiPopFlag (ASSIGN_POPUP); /*** Enable popup for assignment ***/ #endif else if ( (' ' = = MaskedKey) | |
( ('\r' == MaskedKey) && (CRExpandFlag) ) ) { /* Delimits word */ if ({Expanding) WordsTyped++; if (DelimitFlag)
*WordPtr++ = MaskedKey; /* Add char to word: */ return (PreviousKey = Key);
*WordPtr = EOW ; /* Terminate word */
WordPtr = Word ; /* Reset wordptr */
ExtractSearchWord (Word, SearchWord); nodeptr = Find ( SearchWord, &typ ) ; /* Find word or Abbreviation */ if ( (NULL = = nodeptr) && (strlen (SearchWord) > = HistoryThreshold) )
{ /**** Word not abbrev or word - add to history ****/ int Count; char Msg[80];
Count = mcHistory (SearchWord); if ( (Count == RemindStart) && ('Expanding) ) ShowReminder (SearchWord);
WordPtr = Word; *WordPtr = EOW; return (PreviousKey = Key); else if (NULL == nodeptr) return (PreviousKey = Key);
/* Function to print error messages */ void syserr( msg ) char* ms ; extern int errno, sys nerr ; extern char *sys_errlist[] ; fprintf( stderr, "ERROR: %s (%d", msg, errno ) ; if ( errno > 0 && errno < sys_nerr )
fprintf( stderr, "; %s) \n", sys_errlist[eιτno] ) ; el e fprintf( stderr, ")\n" ) ; exit( 1 ) ;
7************************************************************************/ int Initialize (void) { initdisplay 0; /*** Initialize display routines ***/
InitHistory 0; if (IReadWordList (WORD^FILE)) syserr ("Error: Word list not found.");
nt esu t;
Result = spawnvp (P_WAIT, WordProcessor, ArgList); if (Result) { /*** Error ***/ char Msg [80]; sprintf (Msg, "Unable to run %s.", WordProcessor); perror (Msg); } return (0 = = Result);
7************************************************************************/ void main (int argc, char **argv) { int iVect; char c, *Ptr; printf ("\n%s, Copyright 1992, Electronic Ink\n", ProgramName); Initialize 0;
InitResident 0; /*** Doesn't return ***/
ExecuteWordProcessor (WORD_PROCESSOR, &argv[l]);
Terminate 0;
} /* end of mainO */
/** addhist.c **/
/******Copyright 1992 Electronic Ink, inC.*********************************/ fflSTORYJPTR AddHistory (char *Word)
HISTORY_PTR NewHist, HistPtr;
int CompResult, Done;
/*** Allocate space for node ***/ NewHist = HeapAllocate (sizeof (HISTORY_NODE) ); if (NULL == NewHist) return (NULL);
/*** Allocate space for word ***/
NewHist->Word = HeapAllocate (strlen (Word) + 1); if (NULL == NewHist->Word)
HeapFree ((void *)NewHist); return (NULL); } strcpy (NewHist->Word, Word); " N"ew HHiϊsstt--:> ~UseC ~ount = 0; NewHist->Left = NULL; NewHist-> Right = NULL;
/**** Add node to tree ****/ if (NULL = = HistoryRoot)
{
HistoryRoot = NewHist; return (NewHist);
HistPtr = HistoryRoot; Done = 0; while ('Done)
CompResult = stricmp (Word, HistPtr->Word); if (CompResult > 0) if (HistPtr-> Right)
HistPtr = HistPtr-> Right; else
HistPtr-> Right = NewHist; Done = 1; /*** Exit loop ***/
} } else if (CompResult < 0) if (HistPtr->Left)
HistPtr = HistPtr->Left; else
HistPtr- > Left = NewHist; Done = 1;
, } else /*** Matching Node was found ***/ HeapFree (NewHist- > Word);
HeapFree ((void *)NewHϊst); NewHist = NULL; Done = 1; } return (NewHist);