CSpinButtonCtrl placing unwanted thousands separator period in buddy CEdit - c++

I'm using a CSpinButtonCtrl to modify the integer value of a buddy CEdit. Nice at it is the CSpinButtonCtrl places a thousands separator period in the number once the value gets higher than 1.000. Problem is that MFC's Direct Data Exchange only reads the digits before the thousands separator so that 1.000 in the CEdit becomes 1 in the int that the value is exchanged with.
Right now I'm just checking the CEdit for a thousands separator period and comma every time it changes and then possibly remove it like this:
//get current line from CEdit
CString line;
CEdit* pEdit = (CEdit*)GetDlgItem(nId);
pEdit->GetWindowText(line);
//replace periods and commas with nothing
line.Replace(".", "");
line.Replace(",", "");
//Write the CString back to the CEdit
pEdit->SetWindowText(line);
//Set the cursor to the end of the line again
pEdit->SetFocus();
pEdit->SetSel(-1);
But that is obviusly somewhat hacky and gives wrong behaviour when a user enters a digit not a the end of the CEdit. The CEdit is already set to "numerical only" but that is either being ignored by the CSpinButtonCtrl or a thousands separator period or comma are tolerated as numerical.
Isn't there a way to simply turn that thousands separator period placement off? I dont need it anyway.

In that case, from the documentation of CSpinButtonCtrl's create() function:
dwStyle
Specifies the spin button control's style
And one of those style is:
UDS_NOTHOUSANDS
Does not insert a thousands separator between every
three decimal digits.
so make sure your CSpinButtonCtrl has that style set to disable the thousand separators. You can probably do that from the Spin Button styles in the Properties window

Related

Caret position in EditBox after change in text length

I have an EditBox in a MFC-dialog. The user is supposed to enter a number. I'm trying to automatically add separators to the number while the user is inputting it:
When the number is more than 3 digits long, a separator is added between the hundreds and the thousands digit; a second one between the hundredthousands and the millions when it gets longer than 6 digits and so forth (so that 1234567 becomes 1,234,567 for example).
This is done in a function executed by ON_EN_CHANGE and basically works fine already. But the problem is that the caret position is set to the beginning of the EditBox once my function changes the length of the string in it, preventing continous typing.
I tried simulating the press of the end-key to send the caret to the end of the EditBox, which works as long as the user only enters a number from left to right. But it won't work when the user is trying to add, remove or edit digits in the middle of the number. I need the caret position at the exact spot of the number where it was before the user pressed a key.
I tried calculating the new caret position from the previous one (gotten with CEdit::GetSel()) and the previous length of the number:
OnEnChange()
{
int prevCursPos {HIWORD(m_editCtrl.GetSel())};
int prevStrLen {m_editCtrl.GetWindowTextLengthW()};
UpdateData(TRUE);
// Adding/Removing of separators as needed
UpdateData(FALSE);
int difference {m_editCtrl.GetWindowTextLengthW() - prevStrLen))};
if(difference > 0) // a separator has been added to the string
m_editCtrl.SetSel(-1, prevCursPos + 1);
}
However, the SetSel() function doesn't seem to have any effect. I also tried to send an EM_SETSEL message instead, but I couldn't figure out how to make that work either, the caret always resets itself to the beginning of the EditBox.
Does anyone have another idea on how to accomplish what I'm trying to do?
It is unclear how you are handling "/ Adding/Removing of separators as needed".
SetSel with the first parameter set to -1 will position the caret at the beginning of the string if the string changes after calling UpdateData(false)
Create CString type of the variable (m_csEdit for example) for this edit control and
int iLen = m_csDDx.GetLength();
m_editCtrl.SetSel(iLen, -1);
or
m_editCtrl.SetSel(iLen, iLen);
You can calculate the length differently from what I suggested.
Consider using masked edit control (maybe).
Forgot to mention. Use GetNumberFormatEx to format number with thousand delimiter.

QTextEdit changes control characters

I've encountered some feature in Qt widgets QTextEdit, QPlainTextEdit, etc that I wouldn't like to encounter. And I actually have no idea how to change this issue.
I want to cipher some text, replacing one unicode character with another unicode character, even if it is control one.
So I delcare a simple string this way:
QChar ch = (QChar)0x20;
QChar ch2 = (QChar)0xA0;
QString str; str.append(ch); str.append(ch2);
These are usual space (0x20) and some unusual No-Break Space (0xA0). In memory the string is absolutely perfect. But if I set it as a text of QTextEdit with ui->txt_ciphered->setPlainText(str); this No-Break Space (0xA0) becomes usual space. I guess that's because they are for some similar purposes, but I still want to get No-Break Space character in TextEdit so that I could copy it etc. like I can in Notepad++ in example.
How could I change this?
QTextEdit does not accept non-break space, why? How can I
still use non-break space with Qt edit controls?
The problem is that QTextEdit::plainText property expressively prevents non-break space from being inserted and converts it to just space character.
plainText : QString
This property gets and sets the text editor's contents as plain text.
Previous contents are removed and undo/redo history is reset when the
property is set.
If the text edit has another content type, it will not be replaced by
plain text if you call toPlainText(). The only exception to this is
the non-break space, nbsp;, that will be converted into standard
space.
Suggestion: use QTextEdit::setText.
If it still does an unwanted conversion or does not treat that symbol right, you need to choose HTML form of test for QTextEdit::setText by inserting the text containing in an envelope of html tags or <html>My text</html>.

Moving over tab spaces in ncurses

I am creating a basic text editor using ncurses. It can display text fine, but navigating with arrow keys causes a problem when tabs are encountered. Calling move(y, x) will freely move the cursor onto a tab space, where most text editors will jump to the next character. Is there functionality within ncurses to jump over tab spaces or do I need to find a way to do it myself?
You have to do it yourself: wmove moves to the given coordinates, ignoring the way characters are displayed on the screen.
If a destructive (filling with spaces) tab works for your application, then you could use waddch:
If ch is a tab, newline, carriage return or backspace, the
cursor is moved appropriately within the window:
Tabs are considered to be at every eighth column. The
tab interval may be altered by setting the TABSIZE
variable.
For an editor, you probably do not want that behavior (though it probably would be helpful to use the TABSIZE feature when displaying text).

SCI_AUTOCSHOW on Scintilla

I have a question, when I use
CallScintilla(SCI_AUTOCSHOW, nLen, (LPARAM)m_strCandidate.c_str())
to show the window about autocompletion, it works when I input a word but it doesn't always work when I press the backspace button, I wonder if there are some conflicts about the key backspace?
use SCI_AUTOCSETSEPARATOR to set the separator character used to separate words in the SCI_AUTOCSHOW list. The default is the space character.

Change tab stop size in rendered HTML using Qt's QLabel class

I'm rendering some HTML in a QT QLabel. The HTML looks like this:
<pre>foo\tbar</pre>
(note that I've put "\t" where there is a tab chracter in the code).
This renders fine, but the tab character appears to be rendered as eight spaces, whereas I want it to be redered as 4. How can I change this without having to change the source HTML?
According to W3 (HTML4):
The horizontal tab character (decimal 9 in [ISO10646] and [ISO88591]) is usually interpreted by visual user agents as the smallest non-zero number of spaces necessary to line characters up along tab stops that are every 8 characters. We strongly discourage using horizontal tabs in preformatted text since it is common practice, when editing, to set the tab-spacing to other values, leading to misaligned documents.
It's implementation-defined, essencially. Most, if not all, browsers/renderers use eight spaces for tabs. This cannot be configured in Qt.
It is, however somewhat trivial to go through your HTML and replace tabs with however many spaces you wish. Write a simple parser for that. Pseudocode:
for each <pre> block {
for each line in block {
position_in_line = 0
for each character in line {
if character is a tab {
remove tab character
do {
add a space character
++position_in_line
} while position_in_line % 8 != 0
} else {
++position_in_line
}
}
}
}
In case you're curious, HTML3 specifies the use of eight-character tabs:
Within <PRE>, the tab should be interpreted to shift the horizontal column position to the next position which is a multiple of 8 on the same line; that is, col := (col+8) mod 8.
While QLabel uses a QTextDocument internally when rendering rich text, it does not allow access to it in it's API. However, since QTextDocument is a QObject, you can try to use
QTextDocument * tl = label->findChild<QTextDocument>();
to get access to it (will work if the QLabel creates the QTextDocument as a (direct or indirect) child of itself).
Once you have a pointer to the text document, you can use the QTextDocument API, e.g. QTextOption::setTabsStop(), to change the tab stops.
The last step is to somehow make the QLabel repaint itself. Probably a call to QWidget::update() suffices, but caching (or worse, recreating the text document) might thward that. In this case, you can register an event listener on the label to adjust the text document just prior to a paintEvent(), but note that the sizeHint() might also change when the tab stops change, so it might be more complicated still.
That said, it's how I'd approach the problem.
Try this:
<pre style="tab-interval:0.5in">foo\tbar</pre>
Could work