Exemple #1
0
size_t split_line(SplitStringLine *result, unsigned wid, std::wstring_view str, size_t offset, unsigned options) {
	str.remove_prefix(offset);
	const wchar_t *s = str.data();
	size_t slen = str.length();

	size_t cur = 0;     // Current position
	unsigned curwid = 0;// Used screen width

	for (;;) {
		if (cur >= slen) {
			result->begin = offset;
			result->len = slen;
			result->wid = curwid;
			return (offset + slen);
		}
		if (!(options & SPLIT_NEWLINE_AS_SPACE) && s[cur] == L'\n') {
			result->begin = offset;
			result->len = cur;
			result->wid = curwid;
			return (offset + cur + 1); // Skip the newline character
		}
		unsigned w = ucs_width (s[cur]);
		if (curwid + w > wid) {
			break;
		}
		curwid += w;
		++cur;
	}
	// Not the whold string. Neither has a newline character been encountered
	// Now scan backward to find a proper line-breaking point
	unsigned extra_skip = 0;
	if (!(options & SPLIT_CUT_WORD)) {
		unsigned xcur = cur;
		for (;;) {
			if (xcur == 0) { // This means that a single word is longer than a line. We have to split it
				break;
			}
			if ((!ucs_isalnum (s[xcur-1]) || !ucs_isalnum (s[xcur])) &&
					allow_line_end (s[xcur-1]) &&
					allow_line_beginning (s[xcur])) {
				cur = xcur;
				break;
			}
			curwid -= ucs_width (s[--xcur]);
		}
		while (cur+extra_skip+1<slen && s[cur+extra_skip]==L' ') {
			++extra_skip;
		}
	}
	result->begin = offset;
	result->len = cur;
	result->wid = curwid;
	return (offset + cur + extra_skip);
}
Exemple #2
0
void append_richtext_line (std::wstring &text, RichTextLineList &lst,
		PaletteID id, const wchar_t *text_a, const std::wstring &text_b)
{
	size_t len_a = wcslen (text_a);
	RichTextLine tmp_line = {
		text.length (),
		len_a + text_b.length (),
		id,
		ucs_width (text_a, len_a) + ucs_width (text_b)
	};
	lst.push_back (tmp_line);
	text.append (text_a, len_a);
	text.append (text_b);
}
Exemple #3
0
void UIString::update ()
{
	unsigned lines = 0;
	unsigned max_width = 0;
	unsigned cur_line_width = 0;
	const wchar_t *cls = get_text ().c_str (); // Current line starting point
	const wchar_t *s;
	for (s = cls; *s; ++s) {
		if (*s == L'\n') {
			++lines;
			max_width = maxU (max_width, cur_line_width);
			cur_line_width = 0;
			cls = s + 1;
		}
		else {
			cur_line_width += ucs_width (*s);
		}
	}
	if (s != cls) {
		++lines;
		max_width = maxU (max_width, cur_line_width);
	}

	this->lines = lines;
	this->max_width = max_width;

	split_cache_wid = 0;
	split_cache.clear ();
}
Exemple #4
0
void append_richtext_line (std::wstring &text, RichTextLineList &lst,
		PaletteID id, unsigned repeat, wchar_t ch)
{
	RichTextLine tmp_line = { text.length (), repeat, id, repeat * ucs_width (ch) };
	lst.push_back (tmp_line);
	text.append (repeat, ch);
}
Exemple #5
0
void append_richtext_line (std::wstring &text, RichTextLineList &lst,
		PaletteID id, const std::wstring &line_text)
{
	RichTextLine tmp_line = { text.length (), line_text.length (), id, ucs_width (line_text) };
	lst.push_back (tmp_line);
	text += line_text;
}
Exemple #6
0
void append_richtext_line (std::wstring &text, RichTextLineList &lst,
		PaletteID id, const wchar_t *line_text)
{
	size_t len = wcslen (line_text);
	RichTextLine tmp_line = { text.length (), len, id, ucs_width (line_text, len) };
	lst.push_back (tmp_line);
	text.append (line_text, len);
}
Exemple #7
0
SplitStringLineList split_line(unsigned wid, std::wstring_view s) {
	SplitStringLineList ret;
	if (wid < 2) { // Robustness. Avoid dead loops
		for (size_t k = 0; k < s.length(); ++k) {
			ret.push_back({k, 1, ucs_width(s[k])});
		}
	} else {
		for (unsigned offset = 0; offset < s.length(); ) {
			SplitStringLine line;
			offset = split_line(&line, wid, s, offset, 0);
			ret.push_back(std::move(line));
		}
	}
	return ret;
}
Exemple #8
0
RichTextLineList combine_lines (std::wstring &str, const RichTextLineC *linec, size_t nlines)
{
	str.clear ();
	RichTextLineList line_list (nlines);
	RichTextLineList::iterator it = line_list.begin ();
	for (; nlines; --nlines) {
		it->id = linec->id;
		size_t len = wcslen (linec->text);
		it->offset = str.length ();
		it->len = len;
		it->screen_wid = ucs_width (linec->text, len);
		str.append (linec->text, len);
		++linec;
		++it;
	}
	return line_list;
}
Exemple #9
0
void ListBox::redraw ()
{
	unsigned disp_wid = get_size().x - 1; // Reserve one for scrollbar
	unsigned disp_hgt = get_size().y;
	if (disp_wid==0 || disp_hgt==0) {
		return;
	}
	choose_palette (PALETTE_ID_LISTBOX);
	clear ();
	const Scroll::Info info = scroll_.get_info();
	for (unsigned i=0; i<info.len; ++i) {
		const std::wstring &str = items[info.first+i];
		choose_palette ((select_any && i==info.focus_pos) ? PALETTE_ID_LISTBOX_SELECT : PALETTE_ID_LISTBOX);
		Size pos{0, i};
		unsigned strwid = ucs_width (str);
		// Are we going to overflow?
		if (strwid <= disp_wid) {
			//NO:
			pos = put (pos, str);
			if (select_any && i==info.focus_pos) // Focus? Highlight the whole line
				clear(pos, {disp_wid - pos.x, 1});
		}
		else {
			// YES: Cannot display all
			size_t display_wchars = max_chars_in_width (str, maxS (disp_wid - 4, 0));
			put (pos, str.c_str (), display_wchars);
			choose_palette (PALETTE_ID_LISTBOX);
			pos = put(Size(maxS(disp_wid - 4, 0), i), L' ');
			attribute_toggle (REVERSE);
			pos = put (pos, L"...");
		}
	}
	// Display the scroll bar
	choose_palette (PALETTE_ID_LISTBOX);
	clear({disp_wid, 0}, {1, disp_hgt});
	attribute_toggle (REVERSE);
	ScrollBarInfo scrollbar = scrollbar_info (disp_hgt, items.size(), info.first);
	clear({disp_wid, scrollbar.pos}, {1, scrollbar.size});

	move_cursor({0, info.focus_pos});
}
Exemple #10
0
void MainCtrl::redraw ()
{
	choose_palette (ui::PALETTE_ID_ENTRY);
	clear ();

	if (w().entries.empty ()) {
		put(ui::Size{}, L"No entry yet.");
		put(ui::Size{0, 1}, L"Press \"a\" to create one; press Esc for the menu.");
#ifdef TIARY_USE_MOUSE
		put(ui::Size{0, 2}, L"You can also use your mouse.");
#endif
		return;
	}

	if (w().filtered_entries_ && w().filtered_entries_->empty ()) {
		put(ui::Size{}, L"This is in filtered mode.");
		put(ui::Size{0, 1}, L"But no entry satisfies your requirement.");
		put(ui::Size{0, 2}, L"Press Ctrl-G to modify your filter; or LEFT to see all entries.");
		return;
	}

	unsigned expand_lines = w().global_options.get_num (GLOBAL_OPTION_EXPAND_LINES);
	scroll_.modify_height(get_size().y - expand_lines + 1);

	ui::Scroll::Info info = scroll_.get_info();

	ui::Size pos{};

	std::wstring date_format = w().global_options.get_wstring (GLOBAL_OPTION_DATETIME_FORMAT);

	// Build a map to get entry ID from pointer
	std::map <const DiaryEntry *, unsigned> id_map;
	for (size_t i=0; i<w().entries.size (); ++i) {
		id_map.insert (std::make_pair (w().entries[i], i+1));
	}
	// Is there a filter?
	const DiaryEntryList &ent_lst = w().get_current_list ();

	wchar_t *disp_buffer = new wchar_t [get_size ().x];

	for (unsigned i=0; i<info.len; ++i) {

		choose_palette (i == info.focus_pos ? ui::PALETTE_ID_ENTRY_SELECT : ui::PALETTE_ID_ENTRY);

		if (i == info.focus_pos) {
			move_cursor (pos);
			clear(pos, ui::Size{get_size().x, expand_lines});
		}
		const DiaryEntry &entry = *ent_lst[i+info.first];

		// Entry ID
		pos = put(pos, format(L"%04a  "sv, id_map[&entry]));

		// Date
		choose_palette (i == info.focus_pos ? ui::PALETTE_ID_ENTRY_DATE_SELECT : ui::PALETTE_ID_ENTRY_DATE);
		pos = put(pos, entry.local_time.format(date_format));
		pos.x++;

		// Title
		SplitStringLine split_info;
		const std::wstring &title = entry.title;
		choose_palette (i == info.focus_pos ? ui::PALETTE_ID_ENTRY_TITLE_SELECT : ui::PALETTE_ID_ENTRY_TITLE);
		split_line(&split_info, maxS (0, get_size().x-pos.x), title, 0, SPLIT_NEWLINE_AS_SPACE|SPLIT_CUT_WORD);
		pos = put (pos, disp_buffer,
				std::replace_copy_if (
						&title[split_info.begin], &title[split_info.begin+split_info.len],
						disp_buffer, [](auto x) { return !iswprint(x); }, L' ') - disp_buffer);
		pos.x++;

		// Labels
		const DiaryEntry::LabelList &labels = entry.labels;
		choose_palette (i == info.focus_pos ? ui::PALETTE_ID_ENTRY_LABELS_SELECT : ui::PALETTE_ID_ENTRY_LABELS);
		int left_wid = get_size().x - pos.x;
		for (DiaryEntry::LabelList::const_iterator it=labels.begin(); it!=labels.end(); ) {
			if (left_wid < 3) {
				break;
			}
			unsigned labelwid = ucs_width (*it);
			if (labelwid + 2 > unsigned (left_wid)) {
				pos = put (pos, L"...", 3);
				break;
			}
			pos = put (pos, *it);
			if (++it != labels.end ()) {
				pos = put (pos, L',');
			}
		}
		pos.x++;

		choose_palette (i == info.focus_pos ? ui::PALETTE_ID_ENTRY_TEXT_SELECT : ui::PALETTE_ID_ENTRY_TEXT);
		const std::wstring &text = entry.text;
		size_t offset = 0;
		if (i == info.focus_pos && expand_lines >= 2) {
			// Current entry
			// [Date] [Title] [Labels]
			// [...]
			for (unsigned j=1; j<expand_lines; ++j) {
				pos = ui::Size{0, pos.y + 1};
				offset = split_line(&split_info, get_size().x, text, offset,
						SPLIT_NEWLINE_AS_SPACE);
				wchar_t *bufend = std::replace_copy_if (
						&text[split_info.begin], &text[split_info.begin+split_info.len],
						disp_buffer, [](auto x) { return !iswprint(x); }, L' ');
				pos = put (pos, disp_buffer, bufend-disp_buffer);
			}
		} else {
			// Other entry
			// [Date] [Title] [Labels] [...]
			offset = split_line(&split_info, maxS (0, get_size().x - pos.x), text, offset,
					SPLIT_NEWLINE_AS_SPACE|SPLIT_CUT_WORD);
			wchar_t *bufend = std::replace_copy_if (
					&text[split_info.begin], &text[split_info.begin+split_info.len],
					disp_buffer, [](auto x) { return !iswprint(x); }, L' ');
			pos = put (pos, disp_buffer, bufend-disp_buffer);
		}
		pos = ui::Size{0, pos.y + 1};
	}
	delete [] disp_buffer;
}