home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
fed0217s.zip
/
source
/
line.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-05
|
8KB
|
432 lines
/*
** Module :LINE.CPP
** Abstract :Editor Line methods
**
** Copyright (C) Sergey I. Yevtushenko
**
** Log: Wed 05/03/1997 Updated to V0.5
** Sun 09/11/1997 Updated to V0.9
*/
#include <string.h>
#include <line.h>
#include <version.h>
Line::Line():hl_state(ST_INITIAL),known_len(0), str(""), buf_len(0)
{
}
Line::Line(PLine master):hl_state(ST_INITIAL), buf_len(0)
{
if(master->buf_len)
{
str = new char[master->buf_len];
memcpy(str, master->str, master->buf_len);
buf_len = master->buf_len;
}
else
str = master->str;
known_len = master->known_len;
}
Line::Line(PLine master, int start, int width):
hl_state(ST_INITIAL), buf_len(0), known_len(0),
str("")
{
if(width <= 0)
return;
expand_by(width + 1);
master->get_print(start, str, width);
}
Line::Line(char *new_str): hl_state(ST_INITIAL), known_len(0), buf_len(0)
{
str = new_str;
}
Line::~Line()
{
if(str && buf_len)
delete str;
}
void Line::expand_by(int len)
{
len = (len / CHUNK_SIZE + 1) * CHUNK_SIZE;
char* tmp = new char [buf_len + len];
memset(&tmp[buf_len], ' ', len);
if(str)
{
memcpy(tmp, str, buf_len);
if(buf_len)
delete str;
}
buf_len += len;
str = tmp;
known_len = 0;
}
void Line::set(char* str_new)
{
int len = strlen(str_new)+1;
check_size(len + 1);
memcpy(str, str_new, len + 1);
known_len = 0;
}
char* Line::get_print(int start, char *buff, int width)
{
char *str2 = str;
int pos = 0;
int end = start + width;
for(pos = 0; *str2; str2++)
{
if(*str2 == '\t')
{
int fill = pos;
pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
while(fill < pos)
{
if(fill >= start && fill < end)
buff[fill - start] = ' ';
fill++;
}
}
else
{
if(pos >= start && pos < end)
buff[pos - start] = *str2;
pos++;
}
if(pos >= end)
break;
}
if(pos < start) // Oops, string too short
pos = start;
while(pos < end)
buff[pos++ - start] = ' ';
buff[pos - start] = 0;
return buff;
}
void Line::touch()
{
int slen;
char *tmp;
if(!buf_len)
{
slen = len();
slen = (slen / CHUNK_SIZE + 1) * CHUNK_SIZE;
tmp = new char[slen];
buf_len = slen;
strcpy(tmp, str);
str = tmp;
}
tmp = strchr(str, '\t');
if(tmp)
{
int i = 1;
while(tmp)
{
tmp = strchr(tmp + 1, '\t');
i++;
}
expand_by(i * TAB_WIDTH);
tmp = new char [buf_len];
build_print(tmp);
delete str;
str = tmp;
}
}
int Line::ins_char(int chr, int ins_pos)
{
int slen;
if(ins_pos < 0)
return 1;
touch();
slen = /* strlen(str)*/ len();
check_size(slen + 1);
if(ins_pos > slen)
{
expand_by(ins_pos - slen);
memset(&str[slen], ' ', ins_pos - slen);
str[ins_pos] = 0;
slen = ins_pos;
}
memmove(&str[ins_pos + 1], &str[ins_pos], slen - ins_pos + 1);
str[ins_pos] = (char)chr;
known_len = 0;
return (chr == '\t') ? ((ins_pos / TAB_WIDTH + 1) * TAB_WIDTH - ins_pos) : 1;
}
int Line::ins_char(int pos, PLine src)
{
if(!src->len())
return 0;
touch();
src->touch();
int slen = len();
check_size(((slen < pos) ? pos:slen) + src->len());
if(pos >= slen)
{
memset(&str[slen], ' ', pos - slen);
str[pos + src->len()] = 0;
}
else
memmove(&str[pos + src->len()], &str[pos], slen - pos + 1);
memcpy(&str[pos], src->str, src->len());
known_len = 0;
return 1;
}
int Line::del_char(int del_pos, int num)
{
int slen;
int chr = 0;
if(del_pos < 0 || !len() || num <= 0)
return 0;
touch();
slen = len();
if(del_pos >= slen)
return 0;
chr = str[del_pos];
if(num > (slen - del_pos))
{
chr = 0;
num = slen - del_pos;
}
memmove(&str[del_pos], &str[del_pos + num], slen - del_pos - num + 1);
known_len = 0;
return chr;
}
int Line::len()
{
if(known_len)
return known_len;
int pos = 0;
char *str2 = str;
if(str2) /* Buffer is not empty */
{
for(pos = 0; *str2; str2++)
{
if(*str2 == '\t')
pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
else
pos++;
}
}
return (known_len = pos);
}
int Line::char_at(int from_pos)
{
if(from_pos >= len())
return 0;
char *str2 = str;
int pos = 0;
if(str2)
{
for(pos = 0; *str2; str2++)
{
if(*str2 == '\t')
{
int fill = pos;
pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
if(fill <= from_pos && pos > from_pos)
return ' ';
}
else
{
if(pos == from_pos)
return *str2;
pos++;
}
}
}
return 0;
}
void Line::build_print(char *buff)
{
char *str2 = str;
int pos = 0;
if(str2)
{
for(pos = 0; *str2; str2++)
{
if(*str2 == '\t')
{
int fill = pos;
pos = ((pos / TAB_WIDTH + 1) * TAB_WIDTH);
while(fill++ < pos)
*buff++ = ' ';
}
else
{
*buff++ = *str2;
pos++;
}
}
}
*buff = 0;
}
void Line::xlat(char *cvt_tbl)
{
int slen;
touch();
slen = /* strlen(str)*/ len();
for(int x = 0; x < slen; x++)
str[x] = cvt_tbl[str[x]];
}
void Line::set_hiliting(Parser* parser, int& initial_state)
{
hl_state = initial_state;
parser->reset(str, hl_state);
//bc.reset();
while(*parser->tok)
{
int iSz = parser->next_token();
//bc.encode(parser->color, iSz);
parser->tok += iSz;
}
initial_state = parser->state;
}
//-----------------------------------------
// ByteCache - hiliting cache buffer
//-----------------------------------------
#if 0 /* not used yet */
void ByteCache::encode(int color, int enc_len)
{
if(enc_len <= 0)
return;
last_pos += enc_len;
while(enc_len)
{
int chunk = (enc_len < 16) ? enc_len:16;
enc_len -= chunk;
chunk -= 1; //Do not encode 0-len
char code = ((color & 0x0F) << 4) | (chunk & 0x0F);
if(enc >= len)
expand_buffer();
buf[enc] = code;
enc++;
}
}
void ByteCache::expand_buffer()
{
char* new_buf = new char[len + BC_STEP];
if(len)
{
memcpy(new_buf, buf, len);
memset(new_buf+len, 0x0F, BC_STEP);
}
delete buf;
buf = new_buf;
len += BC_STEP;
}
int ByteCache::unwind(int qry)
{
//Check if there are anything in buffer
if(!len || !buf || !enc || !last_pos)
return 0;
if(qry > last_pos)
return 0;
for(pos = bpos = 0; qry >= (pos + q_len(bpos));)
{
pos += q_len(bpos);
bpos++;
}
return buf[bpos];
}
#endif