home *** CD-ROM | disk | FTP | other *** search
- // **********************************************************************
- // Please read explanations and comments present in file TPicture.h
- // Written by Gonzalo Isaza. Compuserve member no. 73257,2655.
- // This object can be freely used, modified and distributed. It
- // cannot be sold or distributed in such way that such distribution
- // generates a revenue to any of the parties involved in such
- // distribution.
- // ************************************************************************
-
-
- #include <string.h>
- #include <iostream.h>
- #include <ctype.h>
-
- #define Uses_TStreamableClass
- #define Uses_TInputLine
- #define Uses_TEvent
- #define Uses_TKeys
- #include <tv.h>
-
- #include "TPicture.h"
-
- __link(RPicture);
-
- #define beep() cout << (char) 7
-
- const char * const TPicture::name="TPicture";
-
- // more sophisticated "toupper" that handles vowels with accent.
-
- static char capitalize(char c)
- {
- c=toupper(c);
- if (c=='á') c='A';
- if (c=='é') c='E';
- if (c=='í') c='I';
- if (c=='ó') c='O';
- if (c=='ú' || c=='ü') c='U';
- if (c=='ñ') c++;
- return c;
- }
-
- void TPicture::write(opstream& os)
- {
- TInputLine::write(os);
- os.writeString(mask);
- }
-
- void *TPicture::read(ipstream& is)
- {
- TInputLine::read(is);
- is.readString(mask,maxLen+1);
- return this;
- }
-
- TStreamable *TPicture::build()
- {
- return new TPicture(streamableInit);
- }
-
- inline ipstream& operator >> (ipstream& is,TPicture& cl)
- { return is >> (TStreamable&) cl;}
- inline ipstream& operator >> (ipstream& is,TPicture*& cl)
- { return is >> (void*&) cl;}
-
- inline opstream& operator << (opstream& os,TPicture& cl)
- {return os << (TStreamable&) cl;}
- inline opstream& operator << (opstream& os,TPicture* cl)
- {return os << (TStreamable*) cl;}
-
- TPicture::TPicture(const TRect& bounds,char *maskstring) :
- TInputLine(bounds,strlen(maskstring))
- {
- mask=new char[strlen(maskstring)+1];
- strcpy(mask,maskstring);
- curPos=NextPos(-1); // cursor on first position of Picture field
- firstPos=0;
- }
-
- TPicture :: ~TPicture()
- {
- delete mask;
- }
-
- void TPicture :: handleEvent(TEvent& event)
- {
- Boolean Success;
- int oldCurPos,j;
-
- Success=True;
- if (event.what & evMouse) // mouse event
- {
- TInputLine :: handleEvent(event); // let base class handle the mouse
- if (!strchr(STRINGMASK,mask[curPos]))
- {
- curPos=(NextPos(curPos)==curPos)? NextPos(curPos,-1) : NextPos(curPos);
- if (curPos<firstPos)
- firstPos=curPos;
- if (curPos>firstPos+size.x-2)
- firstPos=(curPos-size.x+3<0)? 0 : curPos-size.x+3;
- TInputLine::drawView();
- }
- }
- if (event.what & evKeyDown)
- {
- switch (event.keyDown.keyCode)
- {
- case kbIns: // Toggle insert mode
- case kbTab: // go to next field
- case kbEnter:
- case kbEsc:
- TInputLine::handleEvent(event); // let base class handle it
- return;
- case kbRight:
- if (NextPos(curPos)==curPos && curPos<strlen(mask) &&
- firstPos<strlen(mask)-size.x+2)
- firstPos++;
- if ((curPos=selStart=selEnd=NextPos(curPos))>firstPos+size.x-3)
- firstPos=curPos-size.x+3;
- break;
- case kbDel:
- if (selStart!=selEnd)
- {
- if (!DelBlock())
- {
- selEnd=curPos=selStart;
- beep();
- }
- if (curPos>=firstPos+size.x-2)
- firstPos=curPos-size.x+2;
- }
- else
- if (!RemChar())
- beep();
- break;
- case kbBack:
- selStart=selEnd=curPos;
- if (NextPos(curPos,-1)==curPos)
- break;
- curPos=NextPos(curPos,-1);
- if (!RemChar())
- beep();
- if (curPos<firstPos)
- firstPos=curPos;
- break;
- case kbLeft:
- selStart=selEnd=curPos;
- if (curPos==NextPos(curPos,-1) && firstPos)
- firstPos--;
- if ((curPos=NextPos(curPos,-1))<firstPos)
- firstPos=curPos;
- break;
- case kbHome:
- HomePos(); // move cursor to first position in Picture;
- firstPos=(curPos-size.x+2<0)? 0 : curPos-size.x+2;
- break;
- case kbEnd:
- LastPos(); // move cursor to last position in field
- firstPos=(strlen(mask)-size.x+3<0)? 0 : strlen(mask)-size.x+3;
- break;
- default:
- Success=False;
- if (!DelBlock())
- {
- beep();
- return;
- }
- if (!validChar(event.keyDown.keyCode,mask[curPos]))
- break;
- event.keyDown.keyCode=ConvertChar(event.keyDown.keyCode,mask[curPos]);
- if (!(state & sfCursorIns)) // working in insert mode
- if ((Success=Insert(event.keyDown.keyCode))==False)
- break;
- else
- data[curPos]=event.keyDown.keyCode;
- if ((curPos=NextPos(curPos))>=firstPos+size.x-2)
- firstPos=(curPos-size.x+3<0)? 0 : curPos-size.x+3;
- Success=True;
- }
- if (Success) // character inserted successfully
- TInputLine::drawView();
- else
- beep(); // let user know invalid entry detected
- clearEvent(event);
- }
- }
-
- Boolean TPicture::DelBlock()
- {
- char *s;
- int j,source,destination;
-
- if (selStart==selEnd)
- return True;
- s=new char[strlen(mask)+1];
- strcpy(s,data); // save data for a while
- if (state & sfCursorIns) // insert mode is off
- {
- for (j=selStart;j<selEnd;j++)
- data[j]=(strchr(STRINGMASK,mask[j]))? ' ' : mask[j];
- selEnd=selStart;
- return True;
- }
- source=selEnd;
- destination=selStart;
- if (mask[source] && !strchr(STRINGMASK,mask[source])) // set valid source
- source=(NextPos(source)==source)? strlen(mask) : NextPos(source);
- if (mask[destination] && !strchr(STRINGMASK,mask[destination]))
- destination=(NextPos(destination)==destination)?
- strlen(mask) : NextPos(destination);
- while (destination<strlen(mask))
- {
- data[destination]=(source==strlen(mask))? ' ' : data[source];
- data[destination]=ConvertChar(data[destination],mask[destination]);
- if (!validChar(data[destination],mask[destination]))
- {
- strcpy(data,s);
- delete s;
- return False;
- }
- source=(NextPos(source)==source)? strlen(mask) : NextPos(source);
- destination=(NextPos(destination)==destination)?
- strlen(mask) : NextPos(destination);
- }
- delete s;
- selEnd=curPos=selStart;
- return True;
- }
-
- Boolean TPicture::Insert(char c)
- {
- int oldCurPos; // used to remember initial cursor position
- int lastPos; // stores last position of cursor
- Boolean fail;
- char *s;
-
- if (!validChar(c,mask[curPos])) // character does not fit current position
- return False;
- oldCurPos=curPos;
- fail=False;
- s=new char[strlen(mask)+1]; // get string for temporary storage
- strcpy(s,data);
- LastPos();
- for (lastPos=curPos;curPos!=oldCurPos;lastPos=curPos)
- {
- curPos=NextPos(curPos,-1); // get Previous position
- if (!validChar(data[curPos],mask[lastPos]))
- {
- fail=True;
- break;
- }
- data[lastPos]=data[curPos];
- }
- if (!fail)
- data[curPos]=c; // insert character
- else
- strcpy(data,s); // restore initial contents of data
- delete s;
- curPos=oldCurPos; // restore cursor Position
- return True;
- }
-
- Boolean TPicture::RemChar()
- {
- char *s;
- int lastPos,oldCurPos;
- Boolean fail;
-
- s=new char[strlen(mask)+1];
- fail=False;
- oldCurPos=curPos;
- strcpy(s,data); // keep copy of original data
- for (lastPos=curPos;;lastPos=curPos)
- {
- curPos=(NextPos(curPos)==curPos)? strlen(mask) : NextPos(curPos);
- if (curPos==strlen(mask))
- break;
- if (!validChar(data[curPos],mask[lastPos]))
- {
- fail=True;
- break;
- }
- data[lastPos]=data[curPos]; // shift characters to the left
- }
- if (!fail)
- data[NextPos(curPos,-1)]=' '; // remove last character in picture
- if (fail)
- strcpy(data,s); // restore initial contents of data
- delete s;
- curPos=oldCurPos;
- return (fail==True)? False : True;
- }
-
- int TPicture::NextPos(int place,int increment)
- {
- int oldPlace;
-
- oldPlace=place;
- for (place+=increment;place>=0 && place<strlen(mask);place+=increment)
- if (strchr(STRINGMASK,mask[place]))
- {
- break;
- }
- return (place<0 || place>=strlen(mask))? oldPlace : place;
- }
-
- Boolean TPicture::validChar(char c,char cmask)
- {
- if ((cmask=='#' && !(isdigit(c) || c==' ')) ||
- ((cmask=='?' || cmask=='&') &&
- !(isalpha(c) || c==' ' || (c>='á' && c<='Ñ') ||
- c=='ü' || c=='é')) ||
- ((cmask=='~' && !(isdigit(c) || c==' ' || c=='-' ||
- c=='.')))) // is character invalid?
- return False;
- return (!strchr(STRINGMASK,cmask) && cmask!=c)? False : True;
- }
-
- Boolean TPicture::valid(ushort command)
- {
- if (!command)
- return True;
- for (int i=0;i<=strlen(mask);i++)
- if (!validChar(data[i],mask[i]))
- return False;
- return True;
- }
-
- void TPicture :: setData(void *rec)
- {
- TInputLine::setData(rec);
- if (!valid(1))
- for (int i=0;i<=strlen(mask);i++)
- switch(mask[i])
- {
- case '#':
- case '?':
- case '&':
- case '@':
- case '!':
- case '~':
- data[i]=' ';
- break;
- default:
- data[i]=mask[i];
- }
- }
-
- TStreamableClass RPicture(TPicture::name,TPicture::build,__DELTA(TPicture));
-
- #undef beep()