00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <errno.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include "htdebug.h"
00026 #include "textfile.h"
00027 #include "tools.h"
00028
00029 #define TEXTFILE_READSIZE 256
00030 #define TEXTFILE_MAX_LINELEN 512
00031
00032 #define TEXTFILE_MAX_LINEENDLEN 2
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 void ht_layer_textfile::init(ht_textfile *textfile, bool own_textfile)
00045 {
00046 ht_textfile::init(textfile, own_textfile);
00047 }
00048
00049 bool ht_layer_textfile::convert_ofs2line(FILEOFS o, UINT *line, UINT *pofs)
00050 {
00051 return ((ht_textfile*)streamfile)->convert_ofs2line(o, line, pofs);
00052 }
00053
00054 bool ht_layer_textfile::convert_line2ofs(UINT line, UINT pofs, FILEOFS *o)
00055 {
00056 return ((ht_textfile*)streamfile)->convert_line2ofs(line, pofs, o);
00057 }
00058
00059 void ht_layer_textfile::delete_lines(UINT line, UINT count)
00060 {
00061 ((ht_textfile*)streamfile)->delete_lines(line, count);
00062 }
00063
00064 void ht_layer_textfile::delete_chars(UINT line, UINT ofs, UINT count)
00065 {
00066 ((ht_textfile*)streamfile)->delete_chars(line, ofs, count);
00067 }
00068
00069 bool ht_layer_textfile::get_char(UINT line, char *ch, UINT pos)
00070 {
00071 return ((ht_textfile*)streamfile)->get_char(line, ch, pos);
00072 }
00073
00074 bool ht_layer_textfile::getline(UINT line, UINT pofs, void *buf, UINT buflen, UINT *retlen, lexer_state *state)
00075 {
00076 return ((ht_textfile*)streamfile)->getline(line, pofs, buf, buflen, retlen, state);
00077 }
00078
00079 UINT ht_layer_textfile::getlinelength(UINT line)
00080 {
00081 return ((ht_textfile*)streamfile)->getlinelength(line);
00082 }
00083
00084 void ht_layer_textfile::insert_lines(UINT before, UINT count, void **line_ends, int *line_end_lens)
00085 {
00086 ((ht_textfile*)streamfile)->insert_lines(before, count, line_ends, line_end_lens);
00087 }
00088
00089 void ht_layer_textfile::insert_chars(UINT line, UINT ofs, void *chars, UINT len)
00090 {
00091 ((ht_textfile*)streamfile)->insert_chars(line, ofs, chars, len);
00092 }
00093
00094 bool ht_layer_textfile::has_line(UINT line)
00095 {
00096 return ((ht_textfile*)streamfile)->has_line(line);
00097 }
00098
00099 UINT ht_layer_textfile::linecount()
00100 {
00101 return ((ht_textfile*)streamfile)->linecount();
00102 }
00103
00104 void ht_layer_textfile::set_layered_assume(ht_streamfile *s, bool changes_applied)
00105 {
00106
00107 ((ht_textfile*)streamfile)->set_layered_assume(s, changes_applied);
00108
00109
00110 }
00111
00112 void ht_layer_textfile::set_lexer(ht_syntax_lexer *lexer)
00113 {
00114 ((ht_textfile*)streamfile)->set_lexer(lexer);
00115 }
00116
00117
00118
00119
00120
00121 ht_ltextfile_line::~ht_ltextfile_line()
00122 {
00123 if (is_in_memory) free(in_memory.data);
00124 }
00125
00126
00127
00128
00129
00130 void ht_ltextfile::init(ht_streamfile *streamfile, bool own_streamfile, ht_syntax_lexer *l)
00131 {
00132 ht_textfile::init(streamfile, own_streamfile);
00133 int e = get_error();
00134 if (get_error()) return;
00135 lexer = l;
00136 lines = new ht_clist();
00137 lines->init();
00138 orig_lines = new ht_clist();
00139 orig_lines->init();
00140 reread();
00141 first_parse_dirty_line = linecount();
00142 first_nofs_dirty_line = linecount();
00143 dirty = false;
00144 ofs = 0;
00145 }
00146
00147 void ht_ltextfile::done()
00148 {
00149 lines->destroy();
00150 delete lines;
00151 orig_lines->destroy();
00152 delete orig_lines;
00153 ht_textfile::done();
00154 }
00155
00156 void ht_ltextfile::cache_invd()
00157 {
00158 lines->empty();
00159 UINT c=orig_lines->count();
00160 for (UINT i=0; i<c; i++) {
00161 ht_ltextfile_line *l = new ht_ltextfile_line();
00162 *l = *((ht_ltextfile_line*)orig_lines->get(i));
00163 lines->append(l);
00164 }
00165 dirty_parse(0);
00166
00167 dirty = false;
00168 }
00169
00170 void ht_ltextfile::cache_flush()
00171 {
00172 }
00173
00174 bool ht_ltextfile::convert_line2ofs(UINT line, UINT pofs, FILEOFS *o)
00175 {
00176 ht_ltextfile_line *x;
00177 x=fetch_line_nofs_ok(line);
00178 if (x) {
00179 UINT m=getlinelength_i(x);
00180 if (pofs<m) {
00181 *o=x->nofs+pofs;
00182 } else {
00183 *o=x->nofs+m;
00184 }
00185 return true;
00186 }
00187 return false;
00188 }
00189
00190 bool ht_ltextfile::convert_ofs2line(FILEOFS o, UINT *line, UINT *pofs)
00191 {
00192 UINT l=0, r=linecount();
00193 if (!r) return 0; else r--;
00194 UINT m=0;
00195 ht_ltextfile_line *x, *y;
00196 while (l<=r) {
00197 m=(l+r) / 2;
00198 x=fetch_line_nofs_ok(m);
00199 y=fetch_line_nofs_ok(m+1);
00200 if ((x->nofs < o) && ((y && (y->nofs <= o)) || !y)) l=m+1; else
00201 if (x->nofs > o) r=m-1; else break;
00202 }
00203
00204
00205 x=fetch_line_nofs_ok(m);
00206 if (x) assert(o>=x->nofs);
00207 x=fetch_line_nofs_ok(m+1);
00208 if (x) assert(o<x->nofs);
00209
00210
00211 x=fetch_line_nofs_ok(m);
00212
00213 *line=m;
00214 *pofs=o - x->nofs;
00215 return true;
00216 }
00217
00218 void ht_ltextfile::copy_to(ht_stream *stream)
00219 {
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 #define STREAM_COPYBUF_SIZE (64*1024)
00232 const UINT bufsize=STREAM_COPYBUF_SIZE;
00233 byte *buf=(byte*)malloc(bufsize);
00234 UINT r;
00235 do {
00236 r=read(buf, bufsize);
00237 stream->write(buf, r);
00238 } while (r);
00239 free(buf);
00240 }
00241
00242 void ht_ltextfile::delete_chars(UINT line, UINT ofs, UINT count)
00243 {
00244 ht_ltextfile_line *e=fetch_line_into_memory(line);
00245 if (e) {
00246 char *ostr=e->in_memory.data;
00247 UINT olen=e->in_memory.len;
00248
00249 if (ofs<olen) {
00250 if (ofs+count>olen) count=olen-ofs;
00251 char *nstr=(char*)malloc(olen-count);
00252 memcpy(nstr, ostr, ofs);
00253 memcpy(nstr+ofs, ostr+ofs+count, olen-ofs-count);
00254 free(ostr);
00255 e->in_memory.data=nstr;
00256 e->in_memory.len=olen-count;
00257 dirty_parse(line+1);
00258 dirty_nofs(line+1);
00259 dirty=true;
00260 }
00261 }
00262 }
00263
00264 void ht_ltextfile::delete_lines(UINT line, UINT count)
00265 {
00266 lines->del_multiple(line, count);
00267 dirty_parse(line);
00268 dirty_nofs(line);
00269 dirty=true;
00270 }
00271
00272 void ht_ltextfile::dirty_parse(UINT line)
00273 {
00274 if (line<first_parse_dirty_line) first_parse_dirty_line=line;
00275 }
00276
00277 void ht_ltextfile::dirty_nofs(UINT line)
00278 {
00279 if (line<first_nofs_dirty_line) first_nofs_dirty_line=line;
00280 }
00281
00282 int ht_ltextfile::extend(UINT newsize)
00283 {
00284
00285 return ENOSYS;
00286 }
00287
00288 ht_ltextfile_line *ht_ltextfile::fetch_line(UINT line)
00289 {
00290 return (ht_ltextfile_line*)lines->get(line);
00291 }
00292
00293 ht_ltextfile_line *ht_ltextfile::fetch_line_nofs_ok(UINT line)
00294 {
00295 if (is_dirty_nofs(line)) update_nofs(line);
00296 return fetch_line(line);
00297 }
00298
00299 UINT ht_ltextfile::find_linelen_forwd(byte *buf, UINT maxbuflen, FILEOFS ofs, int *le_len)
00300 {
00301 UINT readlen=(maxbuflen>TEXTFILE_READSIZE) ? TEXTFILE_READSIZE : maxbuflen;
00302 byte *bufp;
00303 UINT s;
00304 UINT len = 0;
00305
00306 if (le_len) *le_len = 0;
00307 do {
00308 streamfile->seek(ofs);
00309 s = streamfile->read(buf, readlen);
00310 int l;
00311 bufp = match_lineend_forwd(buf, s, &l);
00312 if (bufp) {
00313 len += bufp-buf+l;
00314 if (le_len) *le_len = l;
00315 break;
00316 }
00317 if (s != readlen) {
00318 len += s;
00319 break;
00320 }
00321
00322
00323 if (s > (TEXTFILE_MAX_LINEENDLEN-1)) {
00324 len += s-(TEXTFILE_MAX_LINEENDLEN-1);
00325 }
00326 ofs += s-(TEXTFILE_MAX_LINEENDLEN-1);
00327 } while (s == readlen);
00328 if (len > TEXTFILE_MAX_LINELEN) {
00329 len = TEXTFILE_MAX_LINELEN;
00330 if (le_len) *le_len = 0;
00331 }
00332 return len;
00333 }
00334
00335 ht_ltextfile_line *ht_ltextfile::fetch_line_into_memory(UINT line)
00336 {
00337 ht_ltextfile_line *e=fetch_line(line);
00338 if (e) {
00339 if (!e->is_in_memory) {
00340 char *data=(char*)malloc(e->on_disk.len);
00341 streamfile->seek(e->on_disk.ofs);
00342 UINT x=streamfile->read(data, e->on_disk.len);
00343
00344 e->is_in_memory=true;
00345 e->in_memory.data=data;
00346 e->in_memory.len=x;
00347 }
00348 }
00349 return e;
00350 }
00351
00352 UINT ht_ltextfile::get_size()
00353 {
00354 int line = linecount()-1;
00355 FILEOFS o = 0;
00356 convert_line2ofs(line, getlinelength(line), &o);
00357 return o;
00358 }
00359
00360 bool ht_ltextfile::get_char(UINT line, char *ch, UINT pos)
00361 {
00362 ht_ltextfile_line *e=fetch_line(line);
00363 if (e) {
00364 if (e->is_in_memory) {
00365 if (pos<e->in_memory.len) {
00366 *ch=e->in_memory.data[pos];
00367 return true;
00368 }
00369 } else {
00370 if (pos<e->on_disk.len) {
00371 streamfile->seek(e->on_disk.ofs);
00372 streamfile->read(ch, 1);
00373 return true;
00374 }
00375 }
00376 }
00377 return false;
00378 }
00379
00380
00381 bool ht_ltextfile::getline(UINT line, UINT pofs, void *buf, UINT buflen, UINT *retlen, lexer_state *state)
00382 {
00383
00384
00385
00386
00387
00388
00389
00390
00391 ht_ltextfile_line *e=fetch_line(line);
00392
00393 if (e) {
00394 if (is_dirty_parse(line)) update_parse(line);
00395 if (is_dirty_nofs(line)) update_nofs(line);
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 UINT ret;
00406 if (e->is_in_memory) {
00407 UINT l=e->in_memory.len;
00408 if (l>buflen-1) l=buflen-1;
00409 if (pofs>l) l=0; else l-=pofs;
00410 memmove(buf, e->in_memory.data+pofs, l);
00411 ret=l;
00412 } else {
00413 UINT l=e->on_disk.len;
00414 if (l>buflen-1) l=buflen-1;
00415 if (pofs>l) l=0; else l-=pofs;
00416 streamfile->seek(e->on_disk.ofs+pofs);
00417 streamfile->read(buf, l);
00418 ret=l;
00419 }
00420 if (state) *state=e->instate;
00421 *retlen=ret;
00422 return true;
00423 }
00424 return false;
00425 }
00426
00427 UINT ht_ltextfile::getlinelength(UINT line)
00428 {
00429 ht_ltextfile_line *e=fetch_line(line);
00430 return getlinelength_i(e);
00431 }
00432
00433 UINT ht_ltextfile::getlinelength_i(ht_ltextfile_line *e)
00434 {
00435 if (e) {
00436 if (e->is_in_memory) {
00437 return e->in_memory.len;
00438 } else {
00439 return e->on_disk.len;
00440 }
00441 }
00442 return 0;
00443 }
00444
00445 void ht_ltextfile::insert_lines(UINT before, UINT count, void **line_ends, int *line_end_lens)
00446 {
00447 ht_ltextfile_line *e = fetch_line(before);
00448 int instate = e->instate;
00449 while (count--) {
00450 e = new ht_ltextfile_line();
00451 e->is_in_memory = true;
00452 e->instate = instate;
00453 e->on_disk.ofs = 0xffffffff;
00454 e->on_disk.len = 0;
00455 e->in_memory.data = (char*)malloc(1);
00456 e->in_memory.len = 0;
00457 e->nofs = 0;
00458 if (line_ends && line_end_lens) {
00459 e->lineendlen = *line_end_lens++;
00460 memmove(e->lineend, *line_ends++, e->lineendlen);
00461 } else {
00462 e->lineendlen = 1;
00463 e->lineend[0] = '\n';
00464 }
00465 lines->insert_before(e, before);
00466 }
00467 dirty_parse(before);
00468 dirty_nofs(before);
00469 dirty = true;
00470 }
00471
00472 void ht_ltextfile::insert_chars(UINT line, UINT ofs, void *chars, UINT len)
00473 {
00474 ht_ltextfile_line *e=fetch_line(line);
00475 if (e) {
00476 UINT olen=e->is_in_memory ? e->in_memory.len : e->on_disk.len;
00477 if (ofs<=olen) {
00478 e=fetch_line_into_memory(line);
00479 char *ostr=e->in_memory.data;
00480
00481 char *nstr;
00482 UINT nlen=olen;
00483
00484 UINT clen=len;
00485
00486 if (ofs>nlen) nlen=ofs;
00487 nlen+=clen;
00488 nstr=(char*)malloc(nlen);
00489
00490 memcpy(nstr, ostr, ofs);
00491 memcpy(nstr+ofs, chars, clen);
00492 memcpy(nstr+ofs+clen, ostr+ofs, olen-ofs);
00493
00494 e->in_memory.data=nstr;
00495 e->in_memory.len=nlen;
00496 dirty_parse(line+1);
00497 dirty_nofs(line+1);
00498 dirty=true;
00499 free(ostr);
00500 }
00501 }
00502 }
00503
00504 bool ht_ltextfile::has_line(UINT line)
00505 {
00506 return (fetch_line(line)!=NULL);
00507 }
00508
00509 bool ht_ltextfile::is_dirty_nofs(UINT line)
00510 {
00511 return (line>=first_nofs_dirty_line);
00512 }
00513
00514 bool ht_ltextfile::is_dirty_parse(UINT line)
00515 {
00516 return (line>=first_parse_dirty_line);
00517 }
00518
00519 UINT ht_ltextfile::linecount()
00520 {
00521 return lines->count();
00522 }
00523
00524 byte *ht_ltextfile::match_lineend_forwd(byte *buf, UINT buflen, int *le_len)
00525 {
00526 byte *result=NULL;
00527
00528 byte *n=(byte*)memchr(buf, '\n', buflen);
00529 if (n) {
00530 if ((n>buf) && (n[-1] == '\r')) {
00531 *le_len=2;
00532 result=n-1;
00533 } else {
00534 *le_len=1;
00535 result=n;
00536 }
00537 }
00538 return result;
00539 }
00540
00541 lexer_state ht_ltextfile::next_instate(UINT line)
00542 {
00543 byte buf[TEXTFILE_MAX_LINELEN+1];
00544 lexer_state state = 0;
00545
00546 UINT buflen;
00547 if (!getline(line, 0, buf, TEXTFILE_MAX_LINELEN, &buflen, &state)) return state;
00548 buf[buflen] = 0;
00549
00550 if (lexer) {
00551 text_pos p;
00552 char *bufp = (char*)buf;
00553 UINT toklen;
00554 bool start_of_line = true;
00555 p.line = line;
00556 p.pofs = 0;
00557 int bufplen = buflen;
00558 int prev_bufplen = -1;
00559 while ((lexer->gettoken(bufp, bufplen, p, start_of_line, &state, &toklen))) {
00560 bufp += toklen;
00561 p.pofs += toklen;
00562 bufplen -= toklen;
00563 start_of_line = false;
00564 if (!bufplen && !prev_bufplen) break;
00565 prev_bufplen = bufplen;
00566 }
00567 }
00568 return state;
00569 }
00570
00571 FILEOFS ht_ltextfile::next_nofs(ht_ltextfile_line *l)
00572 {
00573 if (l) {
00574 if (l->is_in_memory) return l->nofs+l->in_memory.len+l->lineendlen; else
00575 return l->nofs+l->on_disk.len+l->lineendlen;
00576 }
00577 return 0;
00578 }
00579
00580 void ht_ltextfile::pstat(pstat_t *s)
00581 {
00582 streamfile->pstat(s);
00583 s->size=get_size();
00584 s->size_high=0;
00585 }
00586
00587 UINT ht_ltextfile::read(void *buf, UINT size)
00588 {
00589 FILEOFS o=tell();
00590 UINT line;
00591 UINT pofs;
00592 UINT c=0;
00593 byte *b=(byte*)buf;
00594
00595 if (convert_ofs2line(o, &line, &pofs)) while (size) {
00596 ht_ltextfile_line *l=fetch_line(line);
00597 if (!l)
00598 break;
00599 UINT q;
00600 if (l->is_in_memory) {
00601 q=l->in_memory.len;
00602 UINT s=q;
00603 if (s>pofs) {
00604 s-=pofs;
00605 s=MIN(size, s);
00606 memcpy(b+c, l->in_memory.data+pofs, s);
00607 size-=s;
00608 c+=s;
00609 pofs+=s;
00610 }
00611 } else {
00612 q=l->on_disk.len;
00613 UINT r;
00614 UINT s=q;
00615 if (s>pofs) {
00616 s-=pofs;
00617 s=MIN(size, s);
00618 streamfile->seek(l->on_disk.ofs+pofs);
00619 r=streamfile->read(b+c, s);
00620 if (r!=s) break;
00621 size-=s;
00622 c+=s;
00623 pofs+=s;
00624 }
00625 }
00626 UINT s=l->lineendlen;
00627 if ((q+s>pofs) && (pofs >= q)) {
00628 s-=pofs-q;
00629 s=MIN(size, s);
00630 memcpy(b+c, l->lineend+(pofs-q), s);
00631 size-=s;
00632 c+=s;
00633 }
00634 line++;
00635 pofs=0;
00636 }
00637 ofs += c;
00638 return c;
00639 }
00640
00641 void ht_ltextfile::reread()
00642 {
00643 lines->empty();
00644 orig_lines->empty();
00645 dirty=false;
00646 FILEOFS ofs=0;
00647 int ll, pll=-1, ln=0;
00648 bool firstline=true;
00649 byte buf[TEXTFILE_MAX_LINELEN+1];
00650
00651 lexer_state state=0;
00652 ht_ltextfile_line *e, *ce;
00653
00654 if (lexer) state=lexer->getinitstate();
00655
00656 UINT l=0;
00657 while ((l=find_linelen_forwd(buf, sizeof buf, ofs, &ll))) {
00658 if (streamfile->seek(ofs) != 0) break;
00659 UINT x=streamfile->read(buf, l-ll);
00660 buf[x]=0;
00661
00662 e=new ht_ltextfile_line();
00663 e->is_in_memory=false;
00664 e->instate=state;
00665 e->on_disk.ofs=ofs;
00666 e->on_disk.len=l-ll;
00667 e->nofs=ofs;
00668 e->lineendlen=ll;
00669 assert( (UINT)ll <= sizeof e->lineend);
00670 streamfile->read(e->lineend, ll);
00671 lines->append(e);
00672 ce=new ht_ltextfile_line();
00673 *ce = *e;
00674 orig_lines->append(ce);
00675
00676 if (lexer) {
00677 text_pos p;
00678 char *bufp=(char*)buf;
00679 UINT toklen;
00680 bool start_of_line=true;
00681 p.line=ln;
00682 p.pofs=0;
00683 while (lexer->gettoken(bufp, l-ll-(bufp-(char*)buf), p, start_of_line, &state, &toklen)) {
00684 bufp+=toklen;
00685 p.pofs+=toklen;
00686 start_of_line=false;
00687 }
00688 }
00689
00690 ofs+=l;
00691 pll=ll;
00692 firstline=false;
00693 ln++;
00694 }
00695
00696 if (pll || firstline) {
00697 ll=0;
00698 e=new ht_ltextfile_line();
00699 e->is_in_memory=false;
00700 e->instate=state;
00701 e->on_disk.ofs=ofs;
00702 e->on_disk.len=l-ll;
00703 e->nofs=ofs;
00704 e->lineendlen=ll;
00705 lines->append(e);
00706 ce=new ht_ltextfile_line();
00707 *ce = *e;
00708 orig_lines->append(ce);
00709 }
00710 }
00711
00712 void ht_ltextfile::split_line(UINT a, UINT pos, void *line_end, int line_end_len)
00713 {
00714 if (pos == 0) {
00715 insert_lines(a, 1, &line_end, &line_end_len);
00716 } else {
00717 UINT l=getlinelength(a);
00718 if (pos>l) pos=l;
00719 char *aline=(char*)malloc(pos+1);
00720 UINT alinelen;
00721 getline(a, 0, aline, pos+1, &alinelen, NULL);
00722
00723 insert_lines(a, 1, &line_end, &line_end_len);
00724 insert_chars(a, 0, aline, alinelen);
00725
00726 delete_chars(a+1, 0, pos);
00727 free(aline);
00728 }
00729 }
00730
00731 int ht_ltextfile::seek(FILEOFS offset)
00732 {
00733 ofs = offset;
00734 return 0;
00735 }
00736
00737 void ht_ltextfile::set_layered(ht_streamfile *streamfile)
00738 {
00739 ht_layer_streamfile::set_layered(streamfile);
00740 reread();
00741 }
00742
00743 void ht_ltextfile::set_layered_assume(ht_streamfile *streamfile, bool changes_applied)
00744 {
00745 if (changes_applied) {
00746 orig_lines->empty();
00747 UINT c = lines->count();
00748 for (UINT i=0; i<c; i++) {
00749 ht_ltextfile_line *l = fetch_line_nofs_ok(i);
00750 ht_ltextfile_line *m = new ht_ltextfile_line();
00751 l->on_disk.ofs = l->nofs;
00752 if (l->is_in_memory) {
00753 l->on_disk.len = l->in_memory.len;
00754 free(l->in_memory.data);
00755 l->is_in_memory = false;
00756 }
00757 *m = *l;
00758 orig_lines->append(m);
00759 }
00760 cache_invd();
00761 }
00762 ht_layer_streamfile::set_layered(streamfile);
00763 }
00764
00765 void ht_ltextfile::set_lexer(ht_syntax_lexer *l)
00766 {
00767 if (lexer != l) {
00768 lexer = l;
00769 dirty_parse(0);
00770 }
00771 }
00772
00773 FILEOFS ht_ltextfile::tell()
00774 {
00775 return ofs;
00776 }
00777
00778 int ht_ltextfile::truncate(UINT newsize)
00779 {
00780
00781 return ENOSYS;
00782 }
00783
00784 void ht_ltextfile::update_parse(UINT target)
00785 {
00786 ht_ltextfile_line *e;
00787 UINT line = first_parse_dirty_line;
00788
00789 lexer_state instate=0;
00790 if (line) {
00791 instate = next_instate(line-1);
00792
00793
00794
00795 } else {
00796 if (lexer) instate = lexer->getinitstate();
00797 }
00798
00799 while (line<=target) {
00800 e = fetch_line(line);
00801 if (!e) break;
00802
00803 e->instate = instate;
00804 first_parse_dirty_line = line+1;
00805 instate = next_instate(line);
00806 line++;
00807 }
00808 e = fetch_line(line);
00809 if (e) e->instate = instate;
00810 }
00811
00812 void ht_ltextfile::update_nofs(UINT target)
00813 {
00814 ht_ltextfile_line *e;
00815 UINT line=first_nofs_dirty_line;
00816
00817 FILEOFS nofs;
00818 if (line) {
00819 e=fetch_line(line-1);
00820 nofs=next_nofs(e);
00821 } else {
00822 nofs=0;
00823 }
00824
00825 while (line<=target) {
00826 e=fetch_line(line);
00827 if (!e) break;
00828 e->nofs=nofs;
00829 first_nofs_dirty_line=line+1;
00830 nofs=next_nofs(e);
00831 line++;
00832 }
00833 }
00834
00835 int ht_ltextfile::vcntl(UINT cmd, va_list vargs)
00836 {
00837 switch (cmd) {
00838 case FCNTL_MODS_INVD:
00839 cache_invd();
00840 return 0;
00841 case FCNTL_MODS_FLUSH:
00842 cache_flush();
00843 return 0;
00844 case FCNTL_MODS_IS_DIRTY: {
00845 FILEOFS o=va_arg(vargs, FILEOFS);
00846 UINT s=va_arg(vargs, UINT);
00847 bool *b=va_arg(vargs, bool*);
00848 *b = dirty;
00849 o = 0;
00850 s = 0;
00851 return 0;
00852 }
00853 case FCNTL_MODS_CLEAR_DIRTY: {
00854 dirty = false;
00855 return 0;
00856 }
00857 }
00858 return ht_textfile::vcntl(cmd, vargs);
00859 }
00860
00861 UINT ht_ltextfile::write(const void *buf, UINT size)
00862 {
00863 FILEOFS o = tell();
00864 UINT line;
00865 UINT pofs;
00866 byte *b = (byte*)buf;
00867 UINT r = 0;
00868 if (convert_ofs2line(o, &line, &pofs)) {
00869 r = size;
00870 while (size) {
00871 int lelen;
00872 UINT s;
00873 byte *c = match_lineend_forwd(b, size, &lelen);
00874 if (c) {
00875 s = c-b;
00876 split_line(line, pofs, c, lelen);
00877 } else {
00878 s = size;
00879 lelen = 0;
00880 }
00881 insert_chars(line, pofs, b, s);
00882 s += lelen;
00883 b += s;
00884 size -= s;
00885 line++;
00886 pofs = 0;
00887 }
00888 }
00889 ofs += r;
00890 return r;
00891 }