home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / fed0217s.zip / source / line.cpp < prev    next >
C/C++ Source or Header  |  2001-06-05  |  8KB  |  432 lines

  1. /*
  2. ** Module   :LINE.CPP
  3. ** Abstract :Editor Line methods
  4. **
  5. ** Copyright (C) Sergey I. Yevtushenko
  6. **
  7. ** Log: Wed  05/03/1997       Updated to V0.5
  8. **      Sun  09/11/1997       Updated to V0.9
  9. */
  10.  
  11. #include <string.h>
  12.  
  13. #include <line.h>
  14. #include <version.h>
  15.  
  16. Line::Line():hl_state(ST_INITIAL),known_len(0), str(""), buf_len(0)
  17. {
  18. }
  19.  
  20. Line::Line(PLine master):hl_state(ST_INITIAL), buf_len(0)
  21. {
  22.     if(master->buf_len)
  23.     {
  24.         str = new char[master->buf_len];
  25.  
  26.         memcpy(str, master->str, master->buf_len);
  27.  
  28.         buf_len = master->buf_len;
  29.     }
  30.     else
  31.         str = master->str;
  32.  
  33.     known_len  = master->known_len;
  34. }
  35.  
  36. Line::Line(PLine master, int start, int width):
  37.     hl_state(ST_INITIAL), buf_len(0), known_len(0),
  38.     str("")
  39. {
  40.     if(width <= 0)
  41.         return;
  42.  
  43.     expand_by(width + 1);
  44.     master->get_print(start, str, width);
  45. }
  46.  
  47. Line::Line(char *new_str): hl_state(ST_INITIAL), known_len(0), buf_len(0)
  48. {
  49.     str = new_str;
  50. }
  51.  
  52. Line::~Line()
  53. {
  54.     if(str && buf_len)
  55.         delete str;
  56. }
  57.  
  58. void Line::expand_by(int len)
  59. {
  60.     len = (len / CHUNK_SIZE + 1) * CHUNK_SIZE;
  61.  
  62.     char* tmp = new char [buf_len + len];
  63.  
  64.     memset(&tmp[buf_len], ' ', len);
  65.  
  66.     if(str)
  67.     {
  68.         memcpy(tmp, str, buf_len);
  69.  
  70.         if(buf_len)
  71.             delete str;
  72.     }
  73.  
  74.     buf_len += len;
  75.     str = tmp;
  76.     known_len = 0;
  77. }
  78.  
  79. void Line::set(char* str_new)
  80. {
  81.     int len = strlen(str_new)+1;
  82.  
  83.     check_size(len + 1);
  84.  
  85.     memcpy(str, str_new, len + 1);
  86.  
  87.     known_len = 0;
  88. }
  89.  
  90. char* Line::get_print(int start, char *buff, int width)
  91. {
  92.     char *str2 = str;
  93.     int pos = 0;
  94.     int end = start + width;
  95.  
  96.     for(pos = 0; *str2; str2++)
  97.     {
  98.         if(*str2 == '\t')
  99.         {
  100.             int fill = pos;
  101.             pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
  102.  
  103.             while(fill < pos)
  104.             {
  105.                 if(fill >= start && fill < end)
  106.                     buff[fill - start] = ' ';
  107.  
  108.                 fill++;
  109.             }
  110.         }
  111.         else
  112.         {
  113.             if(pos >= start && pos < end)
  114.                 buff[pos - start] = *str2;
  115.             pos++;
  116.         }
  117.  
  118.         if(pos >= end)
  119.             break;
  120.     }
  121.  
  122.     if(pos < start) // Oops, string too short
  123.         pos = start;
  124.  
  125.     while(pos < end)
  126.         buff[pos++ - start] = ' ';
  127.  
  128.     buff[pos - start] = 0;
  129.  
  130.     return buff;
  131. }
  132.  
  133. void Line::touch()
  134. {
  135.     int slen;
  136.     char *tmp;
  137.  
  138.     if(!buf_len)
  139.     {
  140.         slen = len();
  141.         slen = (slen / CHUNK_SIZE + 1) * CHUNK_SIZE;
  142.         tmp = new char[slen];
  143.         buf_len = slen;
  144.         strcpy(tmp, str);
  145.         str = tmp;
  146.     }
  147.  
  148.     tmp = strchr(str, '\t');
  149.  
  150.     if(tmp)
  151.     {
  152.         int i = 1;
  153.         while(tmp)
  154.         {
  155.             tmp = strchr(tmp + 1, '\t');
  156.             i++;
  157.         }
  158.  
  159.         expand_by(i * TAB_WIDTH);
  160.  
  161.         tmp = new char [buf_len];
  162.  
  163.         build_print(tmp);
  164.  
  165.         delete str;
  166.  
  167.         str = tmp;
  168.     }
  169. }
  170.  
  171. int Line::ins_char(int chr, int ins_pos)
  172. {
  173.     int slen;
  174.     if(ins_pos < 0)
  175.         return 1;
  176.  
  177.     touch();
  178.  
  179.     slen = /* strlen(str)*/ len();
  180.  
  181.     check_size(slen + 1);
  182.  
  183.     if(ins_pos > slen)
  184.     {
  185.         expand_by(ins_pos - slen);
  186.         memset(&str[slen], ' ', ins_pos - slen);
  187.         str[ins_pos] = 0;
  188.         slen = ins_pos;
  189.     }
  190.     memmove(&str[ins_pos + 1], &str[ins_pos], slen - ins_pos + 1);
  191.     str[ins_pos] = (char)chr;
  192.     known_len = 0;
  193.  
  194.     return (chr == '\t') ? ((ins_pos / TAB_WIDTH + 1) * TAB_WIDTH - ins_pos) : 1;
  195. }
  196.  
  197. int Line::ins_char(int pos, PLine src)
  198. {
  199.     if(!src->len())
  200.         return 0;
  201.  
  202.     touch();
  203.     src->touch();
  204.  
  205.     int slen = len();
  206.  
  207.     check_size(((slen < pos) ? pos:slen) + src->len());
  208.  
  209.     if(pos >= slen)
  210.     {
  211.         memset(&str[slen], ' ', pos - slen);
  212.         str[pos + src->len()] = 0;
  213.     }
  214.     else
  215.         memmove(&str[pos + src->len()], &str[pos], slen - pos + 1);
  216.  
  217.     memcpy(&str[pos], src->str, src->len());
  218.  
  219.     known_len = 0;
  220.  
  221.     return 1;
  222. }
  223.  
  224. int Line::del_char(int del_pos, int num)
  225. {
  226.     int slen;
  227.     int chr = 0;
  228.  
  229.     if(del_pos < 0 || !len() || num <= 0)
  230.         return 0;
  231.  
  232.     touch();
  233.  
  234.     slen = len();
  235.  
  236.     if(del_pos >= slen)
  237.         return 0;
  238.  
  239.     chr = str[del_pos];
  240.  
  241.     if(num > (slen - del_pos))
  242.     {
  243.         chr = 0;
  244.         num = slen - del_pos;
  245.     }
  246.  
  247.     memmove(&str[del_pos], &str[del_pos + num], slen - del_pos - num + 1);
  248.     known_len = 0;
  249.  
  250.     return chr;
  251. }
  252.  
  253. int Line::len()
  254. {
  255.     if(known_len)
  256.         return known_len;
  257.  
  258.     int pos = 0;
  259.     char *str2 = str;
  260.  
  261.     if(str2) /* Buffer is not empty */
  262.     {
  263.         for(pos = 0; *str2; str2++)
  264.         {
  265.             if(*str2 == '\t')
  266.                 pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
  267.             else
  268.                 pos++;
  269.         }
  270.     }
  271.  
  272.     return (known_len = pos);
  273. }
  274.  
  275. int Line::char_at(int from_pos)
  276. {
  277.     if(from_pos >= len())
  278.         return 0;
  279.  
  280.     char *str2 = str;
  281.     int pos = 0;
  282.  
  283.     if(str2)
  284.     {
  285.         for(pos = 0; *str2; str2++)
  286.         {
  287.             if(*str2 == '\t')
  288.             {
  289.                 int fill = pos;
  290.                 pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
  291.  
  292.                 if(fill <= from_pos && pos > from_pos)
  293.                     return ' ';
  294.             }
  295.             else
  296.             {
  297.                 if(pos == from_pos)
  298.                     return *str2;
  299.  
  300.                 pos++;
  301.             }
  302.         }
  303.     }
  304.  
  305.     return 0;
  306. }
  307.  
  308. void Line::build_print(char *buff)
  309. {
  310.     char *str2 = str;
  311.     int pos = 0;
  312.  
  313.     if(str2)
  314.     {
  315.         for(pos = 0; *str2; str2++)
  316.         {
  317.             if(*str2 == '\t')
  318.             {
  319.                 int fill = pos;
  320.                 pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
  321.  
  322.                 while(fill++ < pos)
  323.                     *buff++ = ' ';
  324.             }
  325.             else
  326.             {
  327.                 *buff++ = *str2;
  328.                 pos++;
  329.             }
  330.         }
  331.     }
  332.     *buff = 0;
  333. }
  334.  
  335. void Line::xlat(char *cvt_tbl)
  336. {
  337.     int slen;
  338.  
  339.     touch();
  340.  
  341.     slen = /* strlen(str)*/ len();
  342.  
  343.     for(int x = 0; x < slen; x++)
  344.         str[x] = cvt_tbl[str[x]];
  345. }
  346.  
  347. void Line::set_hiliting(Parser* parser, int& initial_state)
  348. {
  349.     hl_state = initial_state;
  350.  
  351.     parser->reset(str, hl_state);
  352.     //bc.reset();
  353.  
  354.     while(*parser->tok)
  355.     {
  356.         int iSz = parser->next_token();
  357.  
  358.         //bc.encode(parser->color, iSz);
  359.  
  360.         parser->tok += iSz;
  361.     }
  362.  
  363.     initial_state = parser->state;
  364. }
  365.  
  366. //-----------------------------------------
  367. // ByteCache - hiliting cache buffer
  368. //-----------------------------------------
  369.  
  370. #if 0   /* not used yet */
  371.  
  372. void ByteCache::encode(int color, int enc_len)
  373. {
  374.     if(enc_len <= 0)
  375.         return;
  376.  
  377.     last_pos += enc_len;
  378.  
  379.     while(enc_len)
  380.     {
  381.         int chunk = (enc_len < 16) ? enc_len:16;
  382.  
  383.         enc_len -= chunk;
  384.  
  385.         chunk -= 1; //Do not encode 0-len
  386.  
  387.         char code = ((color & 0x0F) << 4) | (chunk & 0x0F);
  388.  
  389.         if(enc >= len)
  390.             expand_buffer();
  391.  
  392.         buf[enc] = code;
  393.         enc++;
  394.     }
  395. }
  396.  
  397. void ByteCache::expand_buffer()
  398. {
  399.     char* new_buf = new char[len + BC_STEP];
  400.  
  401.     if(len)
  402.     {
  403.         memcpy(new_buf, buf, len);
  404.         memset(new_buf+len, 0x0F, BC_STEP);
  405.     }
  406.  
  407.     delete buf;
  408.     buf = new_buf;
  409.     len += BC_STEP;
  410. }
  411.  
  412. int ByteCache::unwind(int qry)
  413. {
  414.     //Check if there are anything in buffer
  415.  
  416.     if(!len || !buf || !enc || !last_pos)
  417.         return 0;
  418.  
  419.     if(qry > last_pos)
  420.         return 0;
  421.  
  422.     for(pos = bpos = 0; qry >= (pos + q_len(bpos));)
  423.     {
  424.         pos += q_len(bpos);
  425.         bpos++;
  426.     }
  427.  
  428.     return buf[bpos];
  429. }
  430.  
  431. #endif
  432.