• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

コンソールベースの ToDo ソフトウェアの私的改良版


Commit MetaInfo

修订版b91a9e95ed44c76b0331474cfabf5fe20b0073f0 (tree)
时间2013-02-04 22:59:46
作者Takeshi Hamasaki <hmatrjp@user...>
CommiterTakeshi Hamasaki

Log Message

added multi-width caracter support on editor.cc, editor.h, screen.cc

更改概述

差异

--- a/src/editor.cc
+++ b/src/editor.cc
@@ -116,13 +116,13 @@ void Editor::tab() {}
116116 void Editor::other() {}
117117
118118 void Editor::esc()
119-{
119+{
120120 exit = true;
121121 result = NOT_SAVED;
122122 }
123123
124124 void Editor::enter()
125-{
125+{
126126 exit = true;
127127 }
128128
@@ -143,7 +143,7 @@ void LineEditor::updateText()
143143
144144 window->_move(y, x);
145145 window->_addstr(text.substr(offset, cols));
146- for (unsigned int i = text.length()-offset; i < cols; i++)
146+ for (unsigned int i = text.length()-offset; i < cols; i++)
147147 window->_addch(' ');
148148 window->_move(y, x+cursor-offset);
149149 window->_refresh();
@@ -202,32 +202,51 @@ void LineEditor::other()
202202 */
203203 void TitleEditor::initialize()
204204 {
205- textLines = ((int)text.length()-1) / (int)cols;
205+ if (MB_CUR_MAX == 1) { // only single-width char
206+ textLines = ((int)text.length()-1) / (int)cols;
206207
207- for (int i = 0; i <= textLines; i++)
208- {
209- wstring line(text.substr(i*cols, cols));
210- window->_move(y+i, x);
211- window->_addstr(line);
208+ for (int i = 0; i <= textLines; i++)
209+ {
210+ wstring line(text.substr(i*cols, cols));
211+ window->_move(y+i, x);
212+ window->_addstr(line);
213+ }
214+
215+ } else { // wide char may appear.
216+ textLines = displaySplitLines();
212217 }
218+
213219 window->_move(y+cursorLine(), x+cursorCol());
214220 window->_refresh();
215221 }
216222
217223 void TitleEditor::updateText()
218224 {
219- if (textLines != ((int)(text.length()-1) / (int)cols))
220- {
221- exit = true;
222- result = REDRAW;
223- return;
224- }
225+ if (MB_CUR_MAX == 1) {
226+ if (textLines != ((int)(text.length()-1) / (int)cols))
227+ {
228+ exit = true;
229+ result = REDRAW;
230+ return;
231+ }
225232
226- for (int i = 0; i <= textLines; i++)
227- {
228- wstring line(text.substr(i*cols, cols));
229- window->_move(y+i, x);
230- window->_addstr(line);
233+ for (int i = 0; i <= textLines; i++)
234+ {
235+ wstring line(text.substr(i*cols, cols));
236+ window->_move(y+i, x);
237+ window->_addstr(line);
238+ }
239+
240+ } else { // wide char may appear.
241+ // try self first,
242+ int lineCt = displaySplitLines();
243+
244+ // request redraw if line count differs from initialize.
245+ if (textLines != lineCt) {
246+ exit = true;
247+ result = REDRAW;
248+ return;
249+ }
231250 }
232251
233252 for (unsigned int i = ((text.length()-1) % cols); i < cols-1; i++)
@@ -236,30 +255,203 @@ void TitleEditor::updateText()
236255 window->_refresh();
237256 }
238257
258+// returns counter of actual line(s) -1: 0 means one line.
259+int TitleEditor::displaySplitLines() {
260+// window->_move(y, x);
261+ int linect = 0; // to be used in move();
262+
263+ const wchar_t *widestr = text.c_str();
264+ int wch; // index for widestr[]
265+ char linebuf[cols * MB_CUR_MAX]; // to be used in wctomb() function
266+ char *plinebuf = linebuf;
267+
268+ unsigned int colCount = 0; // counter of filled line length
269+
270+ int wstrlen = wcslen(widestr);
271+ for ( wch=0; wch < wstrlen; wch++) {
272+ int convertedCharLen = wctomb(plinebuf ,widestr[wch]);
273+ if (convertedCharLen >= 1) { // TODO: not preventing overflow.
274+ plinebuf += convertedCharLen;
275+
276+ if ( convertedCharLen > 1) { // wide char
277+ colCount += 2;
278+ } else { // TODO: not processing possible conversion error,
279+ colCount ++;
280+ }
281+
282+ // reached line end?
283+ if (colCount < cols) { // not yet.
284+ ;
285+ } else if (colCount == cols) { // just end position
286+ *plinebuf = L'\0';
287+
288+ window->_move(y+ linect++,x);
289+ window->_addstr(linebuf);
290+
291+ colCount = 0;
292+ plinebuf = linebuf;
293+ } else { // colCount > cols, thus exceeded
294+ plinebuf -= convertedCharLen;
295+ char tmpChar[MB_CUR_MAX];
296+
297+ // temporary keep the last char
298+ for (int i=0; i < convertedCharLen; i++) {
299+ tmpChar[i] = *(plinebuf+i);
300+ }
301+
302+ *plinebuf = L'\0';
303+ window->_move(y+ linect++,x);
304+ window->_addstr(linebuf);
305+
306+ plinebuf = linebuf;
307+ // copy back from temporary buffer
308+ for (int i=0; i < convertedCharLen; i++) {
309+ *plinebuf++ = tmpChar[i];
310+ }
311+ colCount = 2;
312+ }
313+ }
314+ }
315+
316+ if (plinebuf != linebuf) { // the last line, if something remains
317+ *plinebuf = L'\0';
318+
319+ window->_move(y+ linect++,x);
320+ window->_addstr(linebuf);
321+ }
322+
323+ return --linect;
324+}
325+
239326 void TitleEditor::up()
240327 {
241- if (cursorLine() > 0)
242- cursor -= cols;
328+ if (cursorLine() > 0) {
329+ if (MB_CUR_MAX == 1) {
330+ cursor -= cols;
331+ } else { // wide char may appear.
332+ unsigned int colCount = 0;
333+ int bytesLen;
334+ int colWidth;
335+ char dummyBuf[MB_CUR_MAX];
336+ while(cursor > 0) {
337+ bytesLen = wctomb( dummyBuf, text.at(--cursor) );
338+ if (bytesLen > 1) {
339+ colWidth = 2;
340+ } else {
341+ colWidth = 1;
342+ }
343+ if (colCount + colWidth < cols) {
344+ colCount += colWidth;
345+ } else {
346+ break;
347+ }
348+ }
349+ cursor++;
350+ }
351+ }
243352 }
244353
245354 void TitleEditor::down()
246355 {
247356 if ((int)cursorLine() < textLines)
248357 {
249- cursor += cols;
250- if (cursor > (int)text.length())
251- cursor = text.length();
358+ if (MB_CUR_MAX == 1) {
359+ cursor += cols;
360+ if (cursor > (int)text.length())
361+ cursor = text.length();
362+ } else { // wide char may appear.
363+ unsigned int colCount = 0;
364+ int bytesLen;
365+ int colWidth;
366+ char dummyBuf[MB_CUR_MAX];
367+ while(cursor < text.length()) {
368+ bytesLen = wctomb( dummyBuf, text.at(cursor) );
369+ if (bytesLen > 1) {
370+ colWidth = 2;
371+ } else {
372+ colWidth = 1;
373+ }
374+ if (colCount + colWidth < cols) {
375+ colCount += colWidth;
376+ cursor++;
377+ } else {
378+ break;
379+ }
380+ }
381+ }
252382 }
253383 }
254384
255385 unsigned int TitleEditor::cursorLine()
256386 {
257- return cursor / cols;
387+ unsigned int retLine = 0;
388+
389+ if (MB_CUR_MAX == 1) {
390+
391+ retLine = cursor / cols;
392+
393+ } else { // wide char may appear.
394+
395+ const wchar_t *widestr = text.c_str();
396+ unsigned int colCount = 0;
397+ int bytesLen;
398+ char dummyBuf[MB_CUR_MAX];
399+ for (int i =0; i < cursor; i++) {
400+ bytesLen = wctomb(dummyBuf , widestr[i]);
401+ if ( bytesLen > 1) {
402+ colCount += 2;
403+ } else { // TODO: may be conversion error,
404+ colCount ++;
405+ }
406+
407+ // reached line end?
408+ if (colCount < cols) { // not yet.
409+ ;
410+ } else if (colCount == cols) { // just end position
411+ retLine++;
412+ colCount = 0;
413+ } else { // colCount > cols, thus exceeded
414+ retLine++;
415+ colCount = 2;
416+ }
417+ }
418+ }
419+
420+ return retLine;
258421 }
259422
260423 unsigned int TitleEditor::cursorCol()
261424 {
262- return cursor % cols;
425+ unsigned int retCol = 0;
426+
427+ if (MB_CUR_MAX == 1) {
428+ retCol = cursor % cols;
429+
430+ } else { // wide char may appear.
431+
432+ const wchar_t *widestr = text.c_str();
433+ int bytesLen;
434+ char dummyBuf[MB_CUR_MAX];
435+ for (int i =0; i < cursor; i++) {
436+ bytesLen = wctomb(dummyBuf , widestr[i]);
437+ if ( bytesLen > 1) {
438+ retCol += 2;
439+ } else { // TODO: may be conversion error,
440+ retCol ++;
441+ }
442+
443+ // reached line end?
444+ if (retCol < cols) { // not yet.
445+ ;
446+ } else if (retCol == cols) { // just end position
447+ retCol = 0;
448+ } else { // retCol > cols, thus exceeded
449+ retCol = 2;
450+ }
451+ }
452+ }
453+
454+ return retCol;
263455 }
264456
265457
@@ -298,7 +490,7 @@ void CategoryEditor::tab() /* do completion */
298490 (cat == *search))
299491 {
300492 search++;
301- if ((search != categories.end()) &&
493+ if ((search != categories.end()) &&
302494 (!cmp(i, *search)))
303495 {
304496 text = pre + *search + pos;
@@ -315,11 +507,11 @@ void CategoryEditor::tab() /* do completion */
315507 else
316508 {
317509 length = j-i;
318- for (search = categories.begin();
319- (search != categories.end()) &&
320- (cmp(i, *search));
510+ for (search = categories.begin();
511+ (search != categories.end()) &&
512+ (cmp(i, *search));
321513 search++);
322- if ((search != categories.end()) &&
514+ if ((search != categories.end()) &&
323515 (!cmp(i, *search)))
324516 {
325517 text = pre + *search + pos;
@@ -383,7 +575,7 @@ void HistoryEditor::backspace()
383575 */
384576 void CmdEditor::initialize()
385577 {
386- /* initialize if is new command,
578+ /* initialize if is new command,
387579 * in other case we expect it to be already initialized */
388580 if (text == L"")
389581 {
@@ -412,7 +604,7 @@ void CmdEditor::tab() /* do completion */
412604 {
413605 params.push_back(text.substr(begin, end-begin));
414606 }
415- if (wstring::npos != end)
607+ if (wstring::npos != end)
416608 {
417609 params.push_back(text.substr(begin, end-begin));
418610 rest_params = text.substr(end+1);
@@ -456,7 +648,7 @@ void CmdEditor::command_completion(wstring& com)
456648 (com == com_search->first))
457649 {
458650 com_search++;
459- if ((com_search != commands.end()) &&
651+ if ((com_search != commands.end()) &&
460652 (!cmp(com_search->first)))
461653 {
462654 com = com_search->first;
@@ -474,11 +666,11 @@ void CmdEditor::command_completion(wstring& com)
474666 {
475667 length = com.length();
476668 //TODO: try upper_bound
477- for (com_search = commands.begin();
478- (com_search != commands.end()) &&
479- (cmp(com_search->first));
669+ for (com_search = commands.begin();
670+ (com_search != commands.end()) &&
671+ (cmp(com_search->first));
480672 com_search++);
481- if ((com_search != commands.end()) &&
673+ if ((com_search != commands.end()) &&
482674 (!cmp(com_search->first)))
483675 {
484676 com = com_search->first;
@@ -498,7 +690,7 @@ void CmdEditor::category_completion(wstring& cat, int num_param)
498690 (cat == *search))
499691 {
500692 search++;
501- if ((search != categories.end()) &&
693+ if ((search != categories.end()) &&
502694 (!param_cmp(*search)))
503695 {
504696 cat = *search;
@@ -513,11 +705,11 @@ void CmdEditor::category_completion(wstring& cat, int num_param)
513705 else
514706 {
515707 length = cat.length();
516- for (search = categories.begin();
517- (search != categories.end()) &&
518- (param_cmp(*search));
708+ for (search = categories.begin();
709+ (search != categories.end()) &&
710+ (param_cmp(*search));
519711 search++);
520- if ((search != categories.end()) &&
712+ if ((search != categories.end()) &&
521713 (!param_cmp(*search)))
522714 {
523715 cat = *search;
--- a/src/editor.h
+++ b/src/editor.h
@@ -89,6 +89,7 @@ protected:
8989 int textLines;
9090
9191 void initialize();
92+ int displaySplitLines();
9293 void updateText();
9394 void up();
9495 void down();
--- a/src/screen.cc
+++ b/src/screen.cc
@@ -343,13 +343,81 @@ void Screen::drawTitle(int line, int depth, wstring& title, int startLine)
343343 {
344344 int lines, cols;
345345 wtree->_getmaxyx(lines, cols);
346+ unsigned int lenTitleLine = cols-startTitle(depth);
346347
347- for (unsigned int i = startLine; i <= (title.length() / (cols-startTitle(depth))); i++)
348- {
349- if ((int)(line + i) >= lines) break;
350- unsigned int lenTitleLine = cols-startTitle(depth);
351- wstring titleLine = title.substr(i*lenTitleLine,lenTitleLine);
352- wtree->_addstr(line + i, startTitle(depth), titleLine);
348+ if (MB_CUR_MAX == 1) {
349+ for (unsigned int i = startLine; i <= (title.length() / lenTitleLine); i++)
350+ {
351+ if ((int)(line + i) >= lines) break;
352+ wstring titleLine = title.substr(i*lenTitleLine,lenTitleLine);
353+ wtree->_addstr(line + i, startTitle(depth), titleLine);
354+ }
355+
356+ } else { // wide char may appear.
357+
358+ // for passed title string
359+ const wchar_t *titleStr = title.c_str();
360+ int wstrlen = wcslen(titleStr);
361+ int titleIndex=0;
362+
363+ // for a line to be composed
364+ char linebuf[lenTitleLine * MB_CUR_MAX];
365+ char *plinebuf = linebuf;
366+
367+ unsigned int colCount = 0; // counter of filled line length
368+ int linect = 0; // to be used in move();
369+
370+ for (titleIndex = 0; titleIndex < wstrlen; titleIndex++) {
371+ if ((int)(line + linect) >= lines) break;
372+
373+ int convertedCharLen = wctomb(plinebuf ,titleStr[titleIndex]);
374+ if (convertedCharLen >= 1) { // TODO: not processing conversion error.
375+ plinebuf += convertedCharLen;
376+
377+ if ( convertedCharLen > 1) { // wide char
378+ colCount += 2;
379+ } else { // TODO: not processing possible conversion error,
380+ colCount ++;
381+ }
382+
383+ // reached line end?
384+ if (colCount < lenTitleLine) { // not yet.
385+ ;
386+ } else if (colCount == lenTitleLine) { // just end position
387+ *plinebuf = L'\0';
388+ wtree->_addstr(line + linect, startTitle(depth), linebuf);
389+ plinebuf = linebuf;
390+ linect++;
391+ colCount = 0;
392+ } else { // colCount > colToBeUsed, thus exceeded
393+ plinebuf -= convertedCharLen;
394+ char tmpChar[MB_CUR_MAX];
395+
396+ // temporary keep the last char
397+ for (int i=0; i < convertedCharLen; i++) {
398+ tmpChar[i] = *(plinebuf+i);
399+ }
400+
401+ *plinebuf = L'\0';
402+ wtree->_addstr(line + linect, startTitle(depth), linebuf);
403+
404+ plinebuf = linebuf;
405+ linect++;
406+
407+ // copy back from temporary buffer
408+ for (int i=0; i < convertedCharLen; i++) {
409+ *plinebuf++ = tmpChar[i];
410+ }
411+ colCount = 2;
412+ }
413+
414+ }
415+ }
416+ if (plinebuf != linebuf) { // the last line, if something remains
417+ *plinebuf = L'\0';
418+
419+ wtree->_addstr(line + linect, startTitle(depth), linebuf);
420+ }
353421 }
354422 }
355423
@@ -760,10 +828,61 @@ int Screen::treeLines()
760828 int Screen::taskLines(int depth, ToDo &t)
761829 {
762830 int titleLength = t.getTitle().length();
763- int titleLines = (titleLength / (coor.coor[WTREE].cols-startTitle(depth))) + 1;
831+ unsigned int colToBeUsed = coor.coor[WTREE].cols-startTitle(depth);
832+ int titleLines;
833+
834+ if (MB_CUR_MAX == 1) {
835+ titleLines = (titleLength / colToBeUsed) + 1;
836+
837+ if (titleLength && !(titleLength % colToBeUsed))
838+ titleLines -= 1;
839+
840+ } else { // wide char may appear.
841+
842+ // for passed title string
843+ const wchar_t *titleStr = t.getTitle().c_str();
844+ int wstrlen = wcslen(titleStr);
845+ int titleIndex=0;
846+
847+ // for a line to be composed
848+ char linebuf[colToBeUsed * MB_CUR_MAX];
849+ char *plinebuf = linebuf;
850+
851+ unsigned int colCount = 0; // counter of filled line length
852+ titleLines = 1;
853+
854+ for (titleIndex = 0; titleIndex < wstrlen; titleIndex++) {
855+
856+ int convertedCharLen = wctomb(plinebuf ,titleStr[titleIndex]);
857+ if (convertedCharLen >= 1) { // TODO: not processing conversion error.
858+ plinebuf += convertedCharLen;
859+
860+ if ( convertedCharLen > 1) { // wide char
861+ colCount += 2;
862+ } else { // TODO: not processing possible conversion error,
863+ colCount ++;
864+ }
865+
866+ // reached line end?
867+ if (colCount < colToBeUsed) { // not yet.
868+ ;
869+ } else if (colCount == colToBeUsed) { // just end position
870+ titleLines++;
871+ colCount = 0;
872+ plinebuf = linebuf;
873+ } else { // colCount > colToBeUsed, thus exceeded
874+ titleLines++;
875+ colCount = 2;
876+ plinebuf = linebuf + convertedCharLen; // we don't need the actual content here.
877+ }
878+ }
879+ }
880+ if (titleLength && (plinebuf == linebuf)) { // at the last line, if nothing remains
881+ titleLines--; // when a child is just created, its titleLength is 0
882+ } // still it has occupy a line.
883+
884+ }
764885
765- if (titleLength && !(titleLength % (coor.coor[WTREE].cols-startTitle(depth))))
766- titleLines -= 1;
767886 return titleLines;
768887 }
769888