home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / tpictu / tpicture.cpp next >
Encoding:
C/C++ Source or Header  |  1991-11-17  |  9.6 KB  |  352 lines

  1. //  **********************************************************************
  2. //     Please read explanations and comments present in file TPicture.h
  3. //     Written by Gonzalo Isaza.  Compuserve member no. 73257,2655.
  4. //     This object can be freely used, modified and distributed.  It 
  5. //     cannot be sold or distributed in such way that such distribution
  6. //     generates a revenue to any of the parties involved in such 
  7. //     distribution.
  8. //  ************************************************************************
  9.  
  10.  
  11. #include  <string.h>
  12. #include  <iostream.h>
  13. #include  <ctype.h>
  14.  
  15. #define  Uses_TStreamableClass
  16. #define  Uses_TInputLine
  17. #define  Uses_TEvent
  18. #define  Uses_TKeys
  19. #include <tv.h>
  20.  
  21. #include "TPicture.h"
  22.  
  23. __link(RPicture);
  24.  
  25. #define   beep()   cout << (char) 7
  26.  
  27. const char * const TPicture::name="TPicture";
  28.  
  29. // more sophisticated "toupper" that handles vowels with accent.
  30.  
  31. static char capitalize(char c)
  32. {
  33.   c=toupper(c);
  34.   if (c=='á') c='A';
  35.   if (c=='é') c='E';
  36.   if (c=='í') c='I';
  37.   if (c=='ó') c='O';
  38.   if (c=='ú' || c=='ü') c='U';
  39.   if (c=='ñ') c++;
  40.   return c;
  41. }
  42.  
  43. void TPicture::write(opstream& os)
  44. {
  45.   TInputLine::write(os);
  46.   os.writeString(mask);
  47. }
  48.  
  49. void  *TPicture::read(ipstream& is)
  50. {
  51.   TInputLine::read(is);
  52.   is.readString(mask,maxLen+1);
  53.   return this;
  54. }
  55.  
  56. TStreamable *TPicture::build()
  57. {
  58.   return new TPicture(streamableInit);
  59. }
  60.  
  61. inline ipstream& operator >> (ipstream& is,TPicture&  cl)
  62.        { return is >> (TStreamable&) cl;}
  63. inline ipstream& operator >> (ipstream& is,TPicture*& cl)
  64.        { return is >> (void*&) cl;}
  65.  
  66. inline opstream& operator << (opstream& os,TPicture&  cl)
  67.        {return os << (TStreamable&) cl;}
  68. inline opstream& operator << (opstream& os,TPicture* cl)
  69.        {return os << (TStreamable*) cl;}
  70.  
  71. TPicture::TPicture(const TRect& bounds,char *maskstring) :
  72.                 TInputLine(bounds,strlen(maskstring))
  73. {
  74.   mask=new char[strlen(maskstring)+1];
  75.   strcpy(mask,maskstring);
  76.   curPos=NextPos(-1);  // cursor on first position of Picture field
  77.   firstPos=0;
  78. }
  79.  
  80. TPicture :: ~TPicture()
  81. {
  82.   delete  mask;
  83. }
  84.  
  85. void  TPicture :: handleEvent(TEvent& event)
  86. {
  87.   Boolean  Success;
  88.   int      oldCurPos,j;
  89.  
  90.   Success=True;
  91.   if (event.what & evMouse)     // mouse event
  92.   {
  93.     TInputLine :: handleEvent(event);   // let base class handle the mouse
  94.     if (!strchr(STRINGMASK,mask[curPos]))
  95.     {
  96.       curPos=(NextPos(curPos)==curPos)? NextPos(curPos,-1) : NextPos(curPos);
  97.       if (curPos<firstPos)
  98.         firstPos=curPos;
  99.       if (curPos>firstPos+size.x-2)
  100.         firstPos=(curPos-size.x+3<0)? 0 : curPos-size.x+3;
  101.       TInputLine::drawView();
  102.     }
  103.   }
  104.   if (event.what & evKeyDown)
  105.   {
  106.     switch (event.keyDown.keyCode)
  107.     {
  108.       case kbIns:           // Toggle insert mode
  109.       case kbTab:           // go to next field
  110.       case kbEnter:
  111.       case kbEsc:
  112.         TInputLine::handleEvent(event);   // let base class handle it
  113.         return;
  114.       case kbRight:
  115.         if (NextPos(curPos)==curPos && curPos<strlen(mask) &&
  116.                    firstPos<strlen(mask)-size.x+2)
  117.           firstPos++;
  118.         if ((curPos=selStart=selEnd=NextPos(curPos))>firstPos+size.x-3)
  119.           firstPos=curPos-size.x+3;
  120.         break;
  121.       case kbDel:
  122.         if (selStart!=selEnd)
  123.         {
  124.           if (!DelBlock())
  125.           {
  126.             selEnd=curPos=selStart;
  127.             beep();
  128.           }
  129.           if (curPos>=firstPos+size.x-2)
  130.             firstPos=curPos-size.x+2;
  131.         }
  132.         else
  133.           if (!RemChar())
  134.             beep();
  135.         break;
  136.       case kbBack:
  137.         selStart=selEnd=curPos;
  138.         if (NextPos(curPos,-1)==curPos)
  139.           break;
  140.         curPos=NextPos(curPos,-1);
  141.         if (!RemChar())
  142.           beep();
  143.         if (curPos<firstPos)
  144.           firstPos=curPos;
  145.         break;
  146.       case kbLeft:
  147.         selStart=selEnd=curPos;
  148.         if (curPos==NextPos(curPos,-1) && firstPos)
  149.           firstPos--;
  150.         if ((curPos=NextPos(curPos,-1))<firstPos)
  151.           firstPos=curPos;
  152.         break;
  153.       case kbHome:
  154.         HomePos();   // move cursor to first position in Picture;
  155.         firstPos=(curPos-size.x+2<0)? 0 : curPos-size.x+2;
  156.         break;
  157.       case kbEnd:
  158.         LastPos();   // move cursor to last position in field
  159.         firstPos=(strlen(mask)-size.x+3<0)? 0 : strlen(mask)-size.x+3;
  160.         break;
  161.       default:
  162.         Success=False;
  163.         if (!DelBlock())
  164.         {
  165.           beep();
  166.           return;
  167.         }
  168.         if (!validChar(event.keyDown.keyCode,mask[curPos]))
  169.           break;
  170.         event.keyDown.keyCode=ConvertChar(event.keyDown.keyCode,mask[curPos]);
  171.         if (!(state & sfCursorIns))  //  working in insert mode
  172.           if ((Success=Insert(event.keyDown.keyCode))==False)
  173.             break;
  174.         else
  175.           data[curPos]=event.keyDown.keyCode;
  176.         if ((curPos=NextPos(curPos))>=firstPos+size.x-2)
  177.           firstPos=(curPos-size.x+3<0)? 0 : curPos-size.x+3;
  178.         Success=True;
  179.     }
  180.     if (Success)        // character inserted successfully
  181.       TInputLine::drawView();
  182.     else
  183.       beep();       // let user know invalid entry detected
  184.     clearEvent(event);
  185.   }
  186. }
  187.  
  188. Boolean TPicture::DelBlock()
  189. {
  190.   char  *s;
  191.   int   j,source,destination;
  192.  
  193.   if (selStart==selEnd)
  194.     return True;
  195.   s=new char[strlen(mask)+1];
  196.   strcpy(s,data);              // save data for a while
  197.   if (state & sfCursorIns)     // insert mode is off
  198.   {
  199.     for (j=selStart;j<selEnd;j++)
  200.       data[j]=(strchr(STRINGMASK,mask[j]))? ' ' : mask[j];
  201.     selEnd=selStart;
  202.     return True;
  203.   }
  204.   source=selEnd;
  205.   destination=selStart;
  206.   if (mask[source] && !strchr(STRINGMASK,mask[source])) // set valid source
  207.     source=(NextPos(source)==source)? strlen(mask) : NextPos(source);
  208.   if (mask[destination] && !strchr(STRINGMASK,mask[destination]))
  209.     destination=(NextPos(destination)==destination)?
  210.                          strlen(mask) : NextPos(destination);
  211.   while (destination<strlen(mask))
  212.   {
  213.     data[destination]=(source==strlen(mask))? ' ' : data[source];
  214.     data[destination]=ConvertChar(data[destination],mask[destination]);
  215.     if (!validChar(data[destination],mask[destination]))
  216.     {
  217.       strcpy(data,s);
  218.       delete s;
  219.       return False;
  220.     }
  221.     source=(NextPos(source)==source)? strlen(mask) : NextPos(source);
  222.     destination=(NextPos(destination)==destination)?
  223.                                  strlen(mask) : NextPos(destination);
  224.   }
  225.   delete s;
  226.   selEnd=curPos=selStart;
  227.   return True;
  228. }
  229.  
  230. Boolean TPicture::Insert(char c)
  231. {
  232.   int      oldCurPos;         // used to remember initial cursor position
  233.   int      lastPos;           // stores last position of cursor
  234.   Boolean  fail;
  235.   char *s;
  236.  
  237.   if (!validChar(c,mask[curPos]))  // character does not fit current position
  238.     return False;
  239.   oldCurPos=curPos;
  240.   fail=False;
  241.   s=new char[strlen(mask)+1];  // get string for temporary storage
  242.   strcpy(s,data);
  243.   LastPos();
  244.   for (lastPos=curPos;curPos!=oldCurPos;lastPos=curPos)
  245.   {
  246.     curPos=NextPos(curPos,-1);     // get Previous position
  247.     if (!validChar(data[curPos],mask[lastPos]))
  248.     {
  249.       fail=True;
  250.       break;
  251.     }
  252.     data[lastPos]=data[curPos];
  253.   }
  254.   if (!fail)
  255.     data[curPos]=c;     // insert character
  256.   else
  257.     strcpy(data,s);    // restore initial contents of data
  258.   delete s;
  259.   curPos=oldCurPos;    // restore cursor Position
  260.   return True;
  261. }
  262.  
  263. Boolean TPicture::RemChar()
  264. {
  265.   char      *s;
  266.   int       lastPos,oldCurPos;
  267.   Boolean   fail;
  268.  
  269.   s=new char[strlen(mask)+1];
  270.   fail=False;
  271.   oldCurPos=curPos;
  272.   strcpy(s,data);        // keep copy of original data
  273.   for (lastPos=curPos;;lastPos=curPos)
  274.   {
  275.     curPos=(NextPos(curPos)==curPos)? strlen(mask) : NextPos(curPos);
  276.     if (curPos==strlen(mask))
  277.       break;
  278.     if (!validChar(data[curPos],mask[lastPos]))
  279.     {
  280.       fail=True;
  281.       break;
  282.     }
  283.     data[lastPos]=data[curPos];    // shift characters to the left
  284.   }
  285.   if (!fail)
  286.     data[NextPos(curPos,-1)]=' ';    // remove last character in picture
  287.   if (fail)
  288.     strcpy(data,s);    // restore initial contents of data
  289.   delete s;
  290.   curPos=oldCurPos;
  291.   return (fail==True)? False : True;
  292. }
  293.  
  294. int TPicture::NextPos(int place,int increment)
  295. {
  296.   int  oldPlace;
  297.  
  298.   oldPlace=place;
  299.   for (place+=increment;place>=0 && place<strlen(mask);place+=increment)
  300.     if (strchr(STRINGMASK,mask[place]))
  301.     {
  302.       break;
  303.     }
  304.   return (place<0 || place>=strlen(mask))? oldPlace : place;
  305. }
  306.  
  307. Boolean TPicture::validChar(char c,char cmask)
  308. {
  309.   if ((cmask=='#' && !(isdigit(c) || c==' '))  ||
  310.       ((cmask=='?' || cmask=='&') &&
  311.             !(isalpha(c) || c==' ' || (c>='á' && c<='Ñ') ||
  312.             c=='ü' || c=='é')) ||
  313.       ((cmask=='~' && !(isdigit(c) || c==' ' || c=='-' ||
  314.                 c=='.'))))      // is character invalid?
  315.     return False;
  316.   return (!strchr(STRINGMASK,cmask) && cmask!=c)? False : True;
  317. }
  318.  
  319. Boolean TPicture::valid(ushort command)
  320. {
  321.   if (!command)
  322.     return True;
  323.   for (int i=0;i<=strlen(mask);i++)
  324.     if (!validChar(data[i],mask[i]))
  325.       return False;
  326.   return True;
  327. }
  328.  
  329. void TPicture :: setData(void *rec)
  330. {
  331.   TInputLine::setData(rec);
  332.   if (!valid(1))
  333.     for (int i=0;i<=strlen(mask);i++)
  334.       switch(mask[i])
  335.       {
  336.         case '#':
  337.         case '?':
  338.         case '&':
  339.         case '@':
  340.         case '!':
  341.         case '~':
  342.           data[i]=' ';
  343.           break;
  344.         default:
  345.           data[i]=mask[i];
  346.       }
  347. }
  348.  
  349. TStreamableClass RPicture(TPicture::name,TPicture::build,__DELTA(TPicture));
  350.  
  351. #undef beep()
  352.