1 // This file is part of The New Aspell
2 // Copyright (C) 2002,2011 by Kevin Atkinson under the GNU LGPL license
3 // version 2.0 or 2.1. You should have received a copy of the LGPL
4 // license along with this library if you did not you can find
5 // it at http://www.gnu.org/.
9 #include "checker_string.hpp"
10 #include "speller.hpp"
11 #include "document_checker.hpp"
12 #include "asc_ctype.hpp"
13 #include "convert.hpp"
18 static int get_line(FILE * in, CheckerString::Line & d)
22 while ((i = getc(in)), i != EOF)
24 d.real.push_back(static_cast<char>(i));
28 dconv.conv->convert(d.real.str(), d.real.size(), d.buf, dconv.buf0);
29 d.disp.str = d.buf.str();
30 d.disp.size = d.buf.size();
32 d.disp.str = d.real.str();
33 d.disp.size = d.real.size();
38 CheckerString::CheckerString(AspellSpeller * speller,
39 FILE * in, FILE * out,
41 : in_(in), out_(out), speller_(speller)
43 lines_.reserve(num_lines + 1);
44 for (; num_lines > 0; --num_lines)
46 lines_.resize(lines_.size() + 1);
47 int s = get_line(in_, lines_.back());
50 if (lines_.back().real.size() != 0)
51 lines_.resize(lines_.size() + 1);
53 end_ = lines_.end() - 1;
54 cur_line_ = lines_.begin();
58 checker_.reset(new_document_checker(reinterpret_cast<Speller *>(speller)));
59 checker_->process(cur_line_->real.data(), cur_line_->real.size());
62 void CheckerString::abort() {
71 CheckerString::~CheckerString()
76 for (cur_line_ = first_line(); !off_end(cur_line_); next_line(cur_line_))
78 fwrite(cur_line_->real.data(), cur_line_->real.size(), 1, out_);
83 if (out_ && out_ != stdout && out_ != stdout)
87 bool CheckerString::read_next_line()
89 if (feof(in_)) return false;
90 Lines::iterator next = end_;
92 if (next == cur_line_) return false;
93 int s = get_line(in_, *end_);
94 if (s == 0) return false;
96 if (out_ && end_->real.size() > 0)
97 fwrite(end_->real.data(), end_->real.size(), 1, out_);
102 bool CheckerString::next_misspelling()
104 if (off_end(cur_line_)) return false;
108 bool correct = false;
109 // FIXME: This is a hack to avoid trying to check a word with a space
110 // in it. The correct action is to reparse to string and
111 // check each word individually. However doing so involves
112 // an API enhancement in Checker.
113 for (int i = 0; i != real_word_size_; ++i) {
114 if (asc_isspace(*(real_word_begin_ + i)))
118 correct = aspell_speller_check(speller_, &*real_word_begin_, real_word_size_);
119 diff_ += real_word_size_ - tok_.len;
120 tok_.len = real_word_size_;
124 while ((tok_ = checker_->next_misspelling()).len == 0) {
125 next_line(cur_line_);
127 if (off_end(cur_line_)) return false;
128 checker_->process(cur_line_->real.data(), cur_line_->real.size());
130 real_word_begin_ = cur_line_->real.begin() + tok_.offset + diff_;
131 real_word_size_ = tok_.len;
136 void CheckerString::replace(ParmString repl)
138 assert(real_word_size_ > 0);
139 int offset = real_word_begin_ - cur_line_->real.begin();
140 aspell_speller_store_replacement(speller_, &*real_word_begin_, real_word_size_,
141 repl.str(), repl.size());
142 cur_line_->real.replace(real_word_begin_, real_word_begin_ + real_word_size_,
143 repl.str(), repl.str() + repl.size());
144 real_word_begin_ = cur_line_->real.begin() + offset;
145 real_word_size_ = repl.size();
150 void CheckerString::fix_display_str()
153 cur_line_->buf.clear();
154 int s = real_word_begin_ - cur_line_->real.begin();
155 if (s > 0) dconv.conv->convert(cur_line_->real.data(), s,
156 cur_line_->buf, dconv.buf0);
157 int off = cur_line_->buf.size();
158 dconv.conv->convert(real_word_begin_, real_word_size_,
159 cur_line_->buf, dconv.buf0);
160 disp_word_size_ = cur_line_->buf.size() - off;
161 s = cur_line_->real.end() - (real_word_begin_ + real_word_size_);
162 if (s > 0) dconv.conv->convert(cur_line_->real.data() + (cur_line_->real.size() - s),
163 s, cur_line_->buf, dconv.buf0);
164 cur_line_->disp.str = cur_line_->buf.str();
165 cur_line_->disp.size = cur_line_->buf.size();
166 disp_word_begin_ = cur_line_->buf.data() + off;
168 cur_line_->disp.str = cur_line_->real.str();
169 cur_line_->disp.size = cur_line_->real.size();
170 disp_word_size_ = real_word_size_;
171 disp_word_begin_ = real_word_begin_;