home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / AVATAR.CPP < prev    next >
C/C++ Source or Header  |  1997-07-05  |  7KB  |  306 lines

  1. // +++Date last modified: 05-Jul-1997
  2.  
  3. // Implements Avatar display class
  4. // public domain
  5. // by David Nugent <davidn@unique.blaze.net.au>
  6. // 3:632/348@fidonet
  7.  
  8. #include <iostream.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11.  
  12. #include "avatar.hpp"
  13.  
  14. #define AVT_DEFAULT   3
  15. #define AVT_DLE       0x10
  16.  
  17.  
  18. avatar::avatar(video & v)
  19.   : scrinterp(v),
  20.     dispfunc(0),
  21.     counter(-1),
  22.     arg1(-1),
  23.     rptlen(-1)
  24. {}
  25.  
  26. void
  27. avatar::reset()
  28. {
  29.   dispfunc = 0;
  30.   counter = -1;
  31.   arg1 = -1;
  32.   insertmode = 0;
  33.   rptlen = -1;
  34.   scrinterp::reset();
  35. }
  36.  
  37.   // This is the top level dispatcher. It really only
  38.   // Looks for special control characters
  39.  
  40. #define ctrl(x)   (x-'@')
  41.  
  42. void
  43. avatar::putch(int ch)
  44. {
  45.   if (dispfunc)
  46.     (this->*dispfunc)(ch);
  47.   else
  48.   {
  49.     switch (ch)
  50.     {
  51.       case ctrl('L'):             // cls
  52.         flushbuf();
  53.         vs.gotoxy(0, 0);
  54.         vs.setattr(AVT_DEFAULT);
  55.         vs.cls();
  56.         insertmode = 0;
  57.         break;
  58.  
  59.       case ctrl('Y'):             // repeat chr
  60.         flushbuf();
  61.         dispfunc = &avatar::rptchar;
  62.         counter = -1;
  63.         break;
  64.  
  65.       case ctrl('V'):             // Video
  66.         flushbuf();
  67.         dispfunc = &avatar::setvideo;
  68.         break;
  69.  
  70.       default:
  71.         scrinterp::putch(ch);
  72.         break;
  73.     }
  74.   }
  75. }
  76.  
  77. void
  78. avatar::rptchar(int ch)
  79. {
  80.   if (counter == -1)
  81.     counter = ch;
  82.   else
  83.   {
  84.     dispfunc = 0;
  85.     int count = ch;
  86.     ch = counter;
  87.     counter = -1;
  88.     while (count-- > 0)
  89.       putch(ch);
  90.   }
  91. }
  92.  
  93. void
  94. avatar::setvideo(int ch)
  95. {
  96.   cell_t  x, y,
  97.           mx, my;
  98.   int     nx =0,
  99.           ny =0;
  100.  
  101.   switch (ch)
  102.   {
  103.     case ctrl('A'):
  104.       dispfunc = &avatar::setattr;
  105.       arg1 = -1;
  106.       break;
  107.     case ctrl('B'):       // Blink
  108.       vs.setbg(cell_t(vs.getbg() | 0x8));
  109.       dispfunc = 0;
  110.       break;
  111.     case ctrl('C'):       // Row up
  112.       ny = -1;
  113.       goto mvxy;
  114.     case ctrl('D'):       // Row down
  115.       ny = 1;
  116.       goto mvxy;
  117.     case ctrl('E'):       // Column to left (erase)
  118.       nx = -1;
  119.       goto mvxy;
  120.     case ctrl('F'):       // Column to right (forward)
  121.       nx = 1;
  122.     mvxy:
  123.       vs.wherexy(x, y);
  124.       x = cell_t(x + nx);
  125.       y = cell_t(y + ny);
  126.       vs.maxxy(mx, my);
  127.       if (x < mx && y < my)
  128.         vs.gotoxy(x, y);
  129.       dispfunc = 0;
  130.       break;
  131.     case ctrl('H'):       // Set cursor position
  132.       arg1 = -1;
  133.       dispfunc = &avatar::setpos;
  134.       break;
  135.     case ctrl('I'):       // Toggle insertmode on
  136.       insertmode = 1;
  137.       dispfunc = 0;
  138.       return;
  139.     case ctrl('J'):       // scroll area up
  140.     case ctrl('K'):       // scroll area down
  141.       dispfunc = &avatar::scroll;
  142.       arg1 = ch;          // Save type of scroll
  143.       counter = -1;       // Used as index to area coord
  144.       break;
  145.     case ctrl('L'):       // Clear area to attribute
  146.       dispfunc = &avatar::clrarea;
  147.       counter = -1;
  148.       break;
  149.     case ctrl('M'):
  150.       dispfunc = &avatar::setarea;
  151.       counter = -1;
  152.       break;
  153.     case ctrl('N'):
  154.       // unsupported
  155.       dispfunc = 0;
  156.       break;
  157.     case ctrl('G'):       // Clear to eol
  158.       vs.wherexy(x, y);
  159.       vs.maxxy(mx, my);
  160.       vs.repchr(' ', mx - x);
  161.       vs.gotoxy(x, y);
  162.       dispfunc = 0;
  163.       break;
  164.     case ctrl('Y'):       // Repeat sequence
  165.       dispfunc = &avatar::rptseq;
  166.       counter = rptlen = -1;
  167.       return;   // Don't reset insertmode
  168.   }
  169.   insertmode = 0;
  170. }
  171.  
  172. void
  173. avatar::resetattr(int ch)
  174. {
  175.   vs.setattr(cell_t(ch & 0x7f));
  176.   dispfunc = 0;
  177.   arg1 = -1;
  178. }
  179.  
  180. void
  181. avatar::setattr(int ch)
  182. {
  183.   if (arg1 == -1)         // No DLE
  184.   {
  185.     if (ch == AVT_DLE)    // Got a DLE
  186.     {
  187.       arg1 = 0;           // Call with next byte, and do ESC
  188.       return;
  189.     }
  190.     resetattr(ch);
  191.   }
  192.   else    // Previous char was DLE escaped
  193.   {
  194.     if (ch & 0x80)        // This has a hi-bit
  195.       resetattr(ch);      // So displaying is ok
  196.     else
  197.     {
  198.       resetattr(AVT_DLE); // Else use DLE as attribute
  199.       putch(ch);          // And redisplay this character
  200.     }
  201.   }
  202. }
  203.  
  204. void
  205. avatar::setpos(int ch)
  206. {
  207.   if (arg1 == -1)
  208.     arg1 = ch;
  209.   else
  210.   {
  211.     cell_t  x = cell_t(ch),
  212.             y = cell_t(arg1);
  213.     cell_t  mx, my;
  214.     vs.maxxy(mx, my);
  215.     --x; --y; // Avatar uses 1-based coords
  216.     if (x < mx && y < my)
  217.       vs.gotoxy(x, y);
  218.     counter = arg1 = -1;
  219.     dispfunc = 0;
  220.   }
  221. }
  222.  
  223. void
  224. avatar::rptseq(int ch)
  225. {
  226.   if (rptlen == -1)             // Counter
  227.   {
  228.     counter = (ch & 0xff);
  229.     ++rptlen;
  230.   }
  231.   else if (rptlen == counter)   // We've reached the end
  232.   {
  233.     int count = ch;             // Save these locally so we don't run into
  234.     int len = rptlen;           // reentrancy problems (but recusion problems, yes!)
  235.     rptlen = 0;                 // Reset everything to norm
  236.     dispfunc = 0;
  237.     arg1 = counter = -1;
  238.     if (len)                    // For zero count, we can ignore the lot
  239.     {
  240.       char tmp[256];            // Make local copy of repeated sequence too
  241.       memcpy(tmp, rptbuf, len); // Now, output the whole thing 'count' times
  242.       for (int times = 0; times < count; times++)
  243.         for (int idx = 0; idx < len; idx++)
  244.           putch(tmp[idx]);
  245.     }
  246.   }                             // Just storing repeated sequence
  247.   else rptbuf[rptlen++] = char(ch);
  248. }
  249.  
  250. void
  251. avatar::scroll(int ch)
  252. {
  253.   area[counter++] = cell_t(ch);   // Store data
  254.   if (counter == 5)
  255.   {
  256.     #define s_lines area[0]
  257.     #define s_upper area[1]
  258.     #define s_left  area[2]
  259.     #define s_lower area[3]
  260.     #define s_right area[4]
  261.     vs.scroll(--s_left, --s_upper, --s_right, --s_lower, s_lines, arg1 == ctrl('J'));
  262.     rptlen = arg1 = counter = -1;
  263.     dispfunc = 0;
  264.   }
  265. }
  266.  
  267. void
  268. avatar::clrarea(int ch)
  269. {
  270.   area[counter++] = cell_t(ch);     // Store data
  271.   if (counter == 3)
  272.   {
  273.     #define cl_attr  area[0]
  274.     #define cl_rows  area[1]
  275.     #define cl_cols  area[2]
  276.     vs.setattr(cl_attr);
  277.     cell_t x, y;
  278.     vs.wherexy(x, y);
  279.     vs.scroll(x, y, cell_t(x + cl_cols - 1), cell_t(y + cl_rows - 1), cl_rows, 1);
  280.     rptlen = arg1 = counter = -1;
  281.     dispfunc = 0;
  282.   }
  283. }
  284.  
  285. void
  286. avatar::setarea(int ch)
  287. {
  288.   area[counter++] = cell_t(ch);   // Store data
  289.   if (counter == 4)
  290.   {
  291.     #define sa_attr  area[0]
  292.     #define sa_char  area[1]
  293.     #define sa_rows  area[2]
  294.     #define sa_cols  area[3]
  295.     vs.setattr(sa_attr);
  296.     vs.setfill(sa_char);
  297.     cell_t x, y;
  298.     vs.wherexy(x, y);
  299.     vs.scroll(x, y, cell_t(x + sa_cols - 1), cell_t(y + sa_rows - 1), sa_rows, 1);
  300.     vs.setfill(' ');
  301.     rptlen = arg1 = counter = -1;
  302.     dispfunc = 0;
  303.   }
  304. }
  305.  
  306.