Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* PDCurses */
  2.  
  3. #include "pdcsdl.h"
  4.  
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #ifdef PDC_WIDE
  9. # include "../common/acsgr.h"
  10. #else
  11. # include "../common/acs437.h"
  12. #endif
  13.  
  14. #define MAXRECT 200     /* maximum number of rects to queue up before
  15.                            an update is forced; the number was chosen
  16.                            arbitrarily */
  17.  
  18. static SDL_Rect uprect[MAXRECT];       /* table of rects to update */
  19. static chtype oldch = (chtype)(-1);    /* current attribute */
  20. static int rectcount = 0;              /* index into uprect */
  21. static short foregr = -2, backgr = -2; /* current foreground, background */
  22. static bool blinked_off = FALSE;
  23.  
  24. /* do the real updates on a delay */
  25.  
  26. void PDC_update_rects(void)
  27. {
  28.     if (rectcount)
  29.     {
  30.         /* if the maximum number of rects has been reached, we're
  31.            probably better off doing a full screen update */
  32.  
  33.         if (rectcount == MAXRECT)
  34.             SDL_Flip(pdc_screen);
  35.         else
  36.             SDL_UpdateRects(pdc_screen, rectcount, uprect);
  37.  
  38.         rectcount = 0;
  39.     }
  40. }
  41.  
  42. /* set the font colors to match the chtype's attribute */
  43.  
  44. static void _set_attr(chtype ch)
  45. {
  46.     attr_t sysattrs = SP->termattrs;
  47.  
  48. #ifdef PDC_WIDE
  49.     TTF_SetFontStyle(pdc_ttffont,
  50.         ( ((ch & A_BOLD) && (sysattrs & A_BOLD)) ?
  51.             TTF_STYLE_BOLD : 0) |
  52.         ( ((ch & A_ITALIC) && (sysattrs & A_ITALIC)) ?
  53.             TTF_STYLE_ITALIC : 0) );
  54. #endif
  55.  
  56.     ch &= (A_COLOR|A_BOLD|A_BLINK|A_REVERSE);
  57.  
  58.     if (oldch != ch)
  59.     {
  60.         short newfg, newbg;
  61.  
  62.         if (SP->mono)
  63.             return;
  64.  
  65.         pair_content(PAIR_NUMBER(ch), &newfg, &newbg);
  66.  
  67.         if ((ch & A_BOLD) && !(sysattrs & A_BOLD))
  68.             newfg |= 8;
  69.         if ((ch & A_BLINK) && !(sysattrs & A_BLINK))
  70.             newbg |= 8;
  71.  
  72.         if (ch & A_REVERSE)
  73.         {
  74.             short tmp = newfg;
  75.             newfg = newbg;
  76.             newbg = tmp;
  77.         }
  78.  
  79.         if (newfg != foregr)
  80.         {
  81. #ifndef PDC_WIDE
  82.             SDL_SetPalette(pdc_font, SDL_LOGPAL,
  83.                            pdc_color + newfg, pdc_flastc, 1);
  84. #endif
  85.             foregr = newfg;
  86.         }
  87.  
  88.         if (newbg != backgr)
  89.         {
  90. #ifndef PDC_WIDE
  91.             if (newbg == -1)
  92.                 SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
  93.             else
  94.             {
  95.                 if (backgr == -1)
  96.                     SDL_SetColorKey(pdc_font, 0, 0);
  97.  
  98.                 SDL_SetPalette(pdc_font, SDL_LOGPAL,
  99.                                pdc_color + newbg, 0, 1);
  100.             }
  101. #endif
  102.             backgr = newbg;
  103.         }
  104.  
  105.         oldch = ch;
  106.     }
  107. }
  108.  
  109. #ifdef PDC_WIDE
  110.  
  111. /* Draw some of the ACS_* "graphics" */
  112.  
  113. bool _grprint(chtype ch, SDL_Rect dest)
  114. {
  115.     Uint32 col = pdc_mapped[foregr];
  116.     int hmid = (pdc_fheight - pdc_fthick) >> 1;
  117.     int wmid = (pdc_fwidth - pdc_fthick) >> 1;
  118.  
  119.     switch (ch)
  120.     {
  121.     case ACS_ULCORNER:
  122.         dest.h = pdc_fheight - hmid;
  123.         dest.y += hmid;
  124.         dest.w = pdc_fthick;
  125.         dest.x += wmid;
  126.         SDL_FillRect(pdc_screen, &dest, col);
  127.         dest.w = pdc_fwidth - wmid;
  128.         goto S1;
  129.     case ACS_LLCORNER:
  130.         dest.h = hmid;
  131.         dest.w = pdc_fthick;
  132.         dest.x += wmid;
  133.         SDL_FillRect(pdc_screen, &dest, col);
  134.         dest.w = pdc_fwidth - wmid;
  135.         dest.y += hmid;
  136.         goto S1;
  137.     case ACS_URCORNER:
  138.         dest.h = pdc_fheight - hmid;
  139.         dest.w = pdc_fthick;
  140.         dest.y += hmid;
  141.         dest.x += wmid;
  142.         SDL_FillRect(pdc_screen, &dest, col);
  143.         dest.w = wmid;
  144.         dest.x -= wmid;
  145.         goto S1;
  146.     case ACS_LRCORNER:
  147.         dest.h = hmid + pdc_fthick;
  148.         dest.w = pdc_fthick;
  149.         dest.x += wmid;
  150.         SDL_FillRect(pdc_screen, &dest, col);
  151.         dest.w = wmid;
  152.         dest.x -= wmid;
  153.         dest.y += hmid;
  154.         goto S1;
  155.     case ACS_LTEE:
  156.         dest.h = pdc_fthick;
  157.         dest.w = pdc_fwidth - wmid;
  158.         dest.x += wmid;
  159.         dest.y += hmid;
  160.         SDL_FillRect(pdc_screen, &dest, col);
  161.         dest.w = pdc_fthick;
  162.         dest.x -= wmid;
  163.         goto VLINE;
  164.     case ACS_RTEE:
  165.         dest.w = wmid;
  166.     case ACS_PLUS:
  167.         dest.h = pdc_fthick;
  168.         dest.y += hmid;
  169.         SDL_FillRect(pdc_screen, &dest, col);
  170.     VLINE:
  171.         dest.h = pdc_fheight;
  172.         dest.y -= hmid;
  173.     case ACS_VLINE:
  174.         dest.w = pdc_fthick;
  175.         dest.x += wmid;
  176.         goto DRAW;
  177.     case ACS_TTEE:
  178.         dest.h = pdc_fheight - hmid;
  179.         dest.w = pdc_fthick;
  180.         dest.x += wmid;
  181.         dest.y += hmid;
  182.         SDL_FillRect(pdc_screen, &dest, col);
  183.         dest.w = pdc_fwidth;
  184.         dest.x -= wmid;
  185.         goto S1;
  186.     case ACS_BTEE:
  187.         dest.h = hmid;
  188.         dest.w = pdc_fthick;
  189.         dest.x += wmid;
  190.         SDL_FillRect(pdc_screen, &dest, col);
  191.         dest.w = pdc_fwidth;
  192.         dest.x -= wmid;
  193.     case ACS_HLINE:
  194.         dest.y += hmid;
  195.         goto S1;
  196.     case ACS_S3:
  197.         dest.y += hmid >> 1;
  198.         goto S1;
  199.     case ACS_S7:
  200.         dest.y += hmid + (hmid >> 1);
  201.         goto S1;
  202.     case ACS_S9:
  203.         dest.y += pdc_fheight - pdc_fthick;
  204.     case ACS_S1:
  205.     S1:
  206.         dest.h = pdc_fthick;
  207.     case ACS_BLOCK:
  208.     DRAW:
  209.         SDL_FillRect(pdc_screen, &dest, col);
  210.         return TRUE;
  211.     default: ;
  212.     }
  213.  
  214.     return FALSE;  /* didn't draw it -- fall back to acs_map */
  215. }
  216.  
  217. #endif
  218.  
  219. /* draw a cursor at (y, x) */
  220.  
  221. void PDC_gotoyx(int row, int col)
  222. {
  223.     SDL_Rect src, dest;
  224.     chtype ch;
  225.     int oldrow, oldcol;
  226. #ifdef PDC_WIDE
  227.     Uint16 chstr[2] = {0, 0};
  228. #endif
  229.  
  230.     PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n",
  231.              row, col, SP->cursrow, SP->curscol));
  232.  
  233.     oldrow = SP->cursrow;
  234.     oldcol = SP->curscol;
  235.  
  236.     /* clear the old cursor */
  237.  
  238.     PDC_transform_line(oldrow, oldcol, 1, curscr->_y[oldrow] + oldcol);
  239.  
  240.     if (!SP->visibility)
  241.         return;
  242.  
  243.     /* draw a new cursor by overprinting the existing character in
  244.        reverse, either the full cell (when visibility == 2) or the
  245.        lowest quarter of it (when visibility == 1) */
  246.  
  247.     ch = curscr->_y[row][col] ^ A_REVERSE;
  248.  
  249.     _set_attr(ch);
  250.  
  251.     src.h = (SP->visibility == 1) ? pdc_fheight >> 2 : pdc_fheight;
  252.     src.w = pdc_fwidth;
  253.  
  254.     dest.y = (row + 1) * pdc_fheight - src.h + pdc_yoffset;
  255.     dest.x = col * pdc_fwidth + pdc_xoffset;
  256.     dest.h = src.h;
  257.     dest.w = src.w;
  258.  
  259. #ifdef PDC_WIDE
  260.     SDL_FillRect(pdc_screen, &dest, pdc_mapped[backgr]);
  261.  
  262.     if (!(SP->visibility == 2 && (ch & A_ALTCHARSET && !(ch & 0xff80)) &&
  263.         _grprint(ch & (0x7f | A_ALTCHARSET), dest)))
  264.     {
  265.         if (ch & A_ALTCHARSET && !(ch & 0xff80))
  266.             ch = acs_map[ch & 0x7f];
  267.  
  268.         chstr[0] = ch & A_CHARTEXT;
  269.  
  270.         pdc_font = TTF_RenderUNICODE_Blended(pdc_ttffont, chstr,
  271.                                              pdc_color[foregr]);
  272.         if (pdc_font)
  273.         {
  274.             int center = pdc_fwidth > pdc_font->w ?
  275.                         (pdc_fwidth - pdc_font->w) >> 1 : 0;
  276.             src.x = 0;
  277.             src.y = pdc_fheight - src.h;
  278.             dest.x += center;
  279.             SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
  280.             dest.x -= center;
  281.             SDL_FreeSurface(pdc_font);
  282.             pdc_font = NULL;
  283.         }
  284.     }
  285. #else
  286.     if (ch & A_ALTCHARSET && !(ch & 0xff80))
  287.         ch = acs_map[ch & 0x7f];
  288.  
  289.     src.x = (ch & 0xff) % 32 * pdc_fwidth;
  290.     src.y = (ch & 0xff) / 32 * pdc_fheight + (pdc_fheight - src.h);
  291.  
  292.     SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
  293. #endif
  294.  
  295.     if (oldrow != row || oldcol != col)
  296.     {
  297.         if (rectcount == MAXRECT)
  298.             PDC_update_rects();
  299.  
  300.         uprect[rectcount++] = dest;
  301.     }
  302. }
  303.  
  304. void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp)
  305. {
  306.     SDL_Rect src, dest, lastrect;
  307.     int j;
  308. #ifdef PDC_WIDE
  309.     Uint16 chstr[2] = {0, 0};
  310. #endif
  311.     attr_t sysattrs = SP->termattrs;
  312.     short hcol = SP->line_color;
  313.     bool blink = blinked_off && (attr & A_BLINK) && (sysattrs & A_BLINK);
  314.  
  315.     if (rectcount == MAXRECT)
  316.         PDC_update_rects();
  317.  
  318. #ifdef PDC_WIDE
  319.     src.x = 0;
  320.     src.y = 0;
  321. #endif
  322.     src.h = pdc_fheight;
  323.     src.w = pdc_fwidth;
  324.  
  325.     dest.y = pdc_fheight * lineno + pdc_yoffset;
  326.     dest.x = pdc_fwidth * x + pdc_xoffset;
  327.     dest.h = pdc_fheight;
  328.     dest.w = pdc_fwidth * len;
  329.  
  330.     /* if the previous rect was just above this one, with the same width
  331.        and horizontal position, then merge the new one with it instead
  332.        of adding a new entry */
  333.  
  334.     if (rectcount)
  335.         lastrect = uprect[rectcount - 1];
  336.  
  337.     if (rectcount && lastrect.x == dest.x && lastrect.w == dest.w)
  338.     {
  339.         if (lastrect.y + lastrect.h == dest.y)
  340.             uprect[rectcount - 1].h = lastrect.h + pdc_fheight;
  341.         else
  342.             if (lastrect.y != dest.y)
  343.                 uprect[rectcount++] = dest;
  344.     }
  345.     else
  346.         uprect[rectcount++] = dest;
  347.  
  348.     _set_attr(attr);
  349.  
  350.     if (backgr == -1)
  351.         SDL_LowerBlit(pdc_tileback, &dest, pdc_screen, &dest);
  352. #ifdef PDC_WIDE
  353.     else
  354.         SDL_FillRect(pdc_screen, &dest, pdc_mapped[backgr]);
  355. #endif
  356.  
  357.     if (hcol == -1)
  358.         hcol = foregr;
  359.  
  360.     for (j = 0; j < len; j++)
  361.     {
  362.         chtype ch = srcp[j];
  363.  
  364.         if (blink)
  365.             ch = ' ';
  366.  
  367.         dest.w = pdc_fwidth;
  368.  
  369.         if (ch & A_ALTCHARSET && !(ch & 0xff80))
  370.         {
  371. #ifdef PDC_WIDE
  372.             if (_grprint(ch & (0x7f | A_ALTCHARSET), dest))
  373.             {
  374.                 dest.x += pdc_fwidth;
  375.                 continue;
  376.             }
  377. #endif
  378.             ch = acs_map[ch & 0x7f];
  379.         }
  380.  
  381. #ifdef PDC_WIDE
  382.         ch &= A_CHARTEXT;
  383.  
  384.         if (ch != ' ')
  385.         {
  386.             if (chstr[0] != ch)
  387.             {
  388.                 chstr[0] = ch;
  389.  
  390.                 if (pdc_font)
  391.                     SDL_FreeSurface(pdc_font);
  392.  
  393.                 pdc_font = TTF_RenderUNICODE_Blended(pdc_ttffont, chstr,
  394.                                                      pdc_color[foregr]);
  395.             }
  396.  
  397.             if (pdc_font)
  398.             {
  399.                 int center = pdc_fwidth > pdc_font->w ?
  400.                     (pdc_fwidth - pdc_font->w) >> 1 : 0;
  401.                 dest.x += center;
  402.                 SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
  403.                 dest.x -= center;
  404.             }
  405.         }
  406. #else
  407.         src.x = (ch & 0xff) % 32 * pdc_fwidth;
  408.         src.y = (ch & 0xff) / 32 * pdc_fheight;
  409.  
  410.         SDL_LowerBlit(pdc_font, &src, pdc_screen, &dest);
  411. #endif
  412.  
  413.         if (!blink && (attr & (A_LEFT | A_RIGHT)))
  414.         {
  415.             dest.w = pdc_fthick;
  416.  
  417.             if (attr & A_LEFT)
  418.                 SDL_FillRect(pdc_screen, &dest, pdc_mapped[hcol]);
  419.  
  420.             if (attr & A_RIGHT)
  421.             {
  422.                 dest.x += pdc_fwidth - pdc_fthick;
  423.                 SDL_FillRect(pdc_screen, &dest, pdc_mapped[hcol]);
  424.                 dest.x -= pdc_fwidth - pdc_fthick;
  425.             }
  426.         }
  427.  
  428.         dest.x += pdc_fwidth;
  429.     }
  430.  
  431. #ifdef PDC_WIDE
  432.     if (pdc_font)
  433.     {
  434.         SDL_FreeSurface(pdc_font);
  435.         pdc_font = NULL;
  436.     }
  437. #endif
  438.  
  439.     if (!blink && (attr & A_UNDERLINE))
  440.     {
  441.         dest.y += pdc_fheight - pdc_fthick;
  442.         dest.x = pdc_fwidth * x + pdc_xoffset;
  443.         dest.h = pdc_fthick;
  444.         dest.w = pdc_fwidth * len;
  445.  
  446.         SDL_FillRect(pdc_screen, &dest, pdc_mapped[hcol]);
  447.     }
  448. }
  449.  
  450. /* update the given physical line to look like the corresponding line in
  451.    curscr */
  452.  
  453. void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
  454. {
  455.     attr_t old_attr, attr;
  456.     int i, j;
  457.  
  458.     PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
  459.  
  460.     old_attr = *srcp & (A_ATTRIBUTES ^ A_ALTCHARSET);
  461.  
  462.     for (i = 1, j = 1; j < len; i++, j++)
  463.     {
  464.         attr = srcp[i] & (A_ATTRIBUTES ^ A_ALTCHARSET);
  465.  
  466.         if (attr != old_attr)
  467.         {
  468.             _new_packet(old_attr, lineno, x, i, srcp);
  469.             old_attr = attr;
  470.             srcp += i;
  471.             x += i;
  472.             i = 0;
  473.         }
  474.     }
  475.  
  476.     _new_packet(old_attr, lineno, x, i, srcp);
  477. }
  478.  
  479. static Uint32 _blink_timer(Uint32 interval, void *param)
  480. {
  481.     SDL_Event event;
  482.  
  483.     event.type = SDL_USEREVENT;
  484.     SDL_PushEvent(&event);
  485.     return(interval);
  486. }
  487.  
  488. void PDC_blink_text(void)
  489. {
  490.     static SDL_TimerID blinker_id = 0;
  491.     int i, j, k;
  492.  
  493.     oldch = (chtype)(-1);
  494.  
  495.     if (!(SP->termattrs & A_BLINK))
  496.     {
  497.         SDL_RemoveTimer(blinker_id);
  498.         blinker_id = 0;
  499.     }
  500.     else if (!blinker_id)
  501.     {
  502.         blinker_id = SDL_AddTimer(500, _blink_timer, NULL);
  503.         blinked_off = TRUE;
  504.     }
  505.  
  506.     blinked_off = !blinked_off;
  507.  
  508.     for (i = 0; i < SP->lines; i++)
  509.     {
  510.         const chtype *srcp = curscr->_y[i];
  511.  
  512.         for (j = 0; j < SP->cols; j++)
  513.             if (srcp[j] & A_BLINK)
  514.             {
  515.                 k = j;
  516.                 while (k < SP->cols && (srcp[k] & A_BLINK))
  517.                     k++;
  518.                 PDC_transform_line(i, j, k - j, srcp + j);
  519.                 j = k;
  520.             }
  521.     }
  522.  
  523.     oldch = (chtype)(-1);
  524. }
  525.  
  526. void PDC_doupdate(void)
  527. {
  528.     PDC_napms(1);
  529. }
  530.