The QPlainTextEdit class, the base class for the EditBox class, contains a feature called Extra Selections, which allows for temporarily marking certain regions of the document with a given format (color and/or style). Each extra selection is specified by the QTextEdit::ExtraSelection structure that consists of a cursor (QTextCursor) and a format (QTextCharFormat). A list (QList) of all the extra selections is given to the plain text edit widget using the setExtraSelection() function.
The selection, the characters to temporarily format, is specified by the cursor, which is initialized from the text cursor of edit widget. The cursor is them set to the beginning position of the selection to temporarily mark and moved to the end of the selection using the keep anchor position option.
The temporary format is specified by the format member. The format has many options including colors (foreground and background), and font style like italicized, bold, underlined, and curvy underline. The underlines can even be made a different color.
For translator errors, a simple red background will be used. Later, another color, possible yellow or light blue, will be used for warnings. There will be no warnings from the translator, but there will be warnings from the encoder. For example, when the beginning of an IF statement or FOR loop is entered before the END IF or NEXT is entered, or vice-versa. These are not errors as the line is valid, but these warnings will also prevent the program from being run until corrected.
Monday, April 8, 2013
Saturday, April 6, 2013
REM Operator (For BASIC Comments)
Implementing the REM operator (single quote) turned out to be simpler than anticipated. The REM operator type of REM always occurs at the end of a line, therefore, it can be treated as the end of the line except that the REM operator token (with comment string) will be added to the end of the RPN output list.
A new REM operator token handler was implemented, which first checks if the command stack is not empty or if the current token mode is not command (occurs for assignment statements without the LET keyword). Otherwise the REM operator being processed occurred at the beginning of the line and no current command needs to be processed.
To process the current command, the end of line token handler is called since it contains all the needed functionality for processing the command when the end of a line is reached. A new end of line token is created and passed to the end of line token handler. A new token was needed in case the command changes the end of line token into another token to add to the RPN output list (as the INPUT command does). If the command does not use this token, the end of line token handler will delete it. If an error is returned, then the end of line token is deleted and the error is returned. Otherwise, the REM operator token is appended to the end of the RPN output list.
Since the REM operator token acts as the end of the line, the table entry for the REM operator code entry was changed to include the end expression and end statement flags. The pointer to the new REM operator token handler was also added. Several new REM tests were added to translator test #15 for the REM operator on various types of commands. Some error tests were also added.
[commit da69b3ba07]
A new REM operator token handler was implemented, which first checks if the command stack is not empty or if the current token mode is not command (occurs for assignment statements without the LET keyword). Otherwise the REM operator being processed occurred at the beginning of the line and no current command needs to be processed.
To process the current command, the end of line token handler is called since it contains all the needed functionality for processing the command when the end of a line is reached. A new end of line token is created and passed to the end of line token handler. A new token was needed in case the command changes the end of line token into another token to add to the RPN output list (as the INPUT command does). If the command does not use this token, the end of line token handler will delete it. If an error is returned, then the end of line token is deleted and the error is returned. Otherwise, the REM operator token is appended to the end of the RPN output list.
Since the REM operator token acts as the end of the line, the table entry for the REM operator code entry was changed to include the end expression and end statement flags. The pointer to the new REM operator token handler was also added. Several new REM tests were added to translator test #15 for the REM operator on various types of commands. Some error tests were also added.
[commit da69b3ba07]
REM Command (For BASIC Comments)
Before continuing with highlighting errors in the edit box, I noticed (when implementing the routine that converts the token contents to text for display in the program view) that the Remark token type was not actually being used. The parser is handling two types of remarks, the REM command and the single quote comment method, which is treated as an operator since it can appear at the end of any line and does not need to be preceded by the colon statement separator.
However, these two tokens (REM command and REM operator) were not being handled in the translator. The REM command token was returning a "Not Yet Implemented" error message. For the REM command token to be handled and not return this error message, the REM code in the table needed to be assigned a token mode. It turned out that the specific token mode assigned was not important as long as it wasn't the default NULL token type, which triggers the error message, because the REM command will always be the last command on a line.
To process the REM command token, a new REM command handler was implemented that simply adds the REM command token (which contains the actual comment text in the string of the token) to the RPN output list. A new translator test (#15) was added for various REM command tests. The REM operator token is a little trickier to handle, which will be implemented next.
[commit 258f3a9df0]
However, these two tokens (REM command and REM operator) were not being handled in the translator. The REM command token was returning a "Not Yet Implemented" error message. For the REM command token to be handled and not return this error message, the REM code in the table needed to be assigned a token mode. It turned out that the specific token mode assigned was not important as long as it wasn't the default NULL token type, which triggers the error message, because the REM command will always be the last command on a line.
To process the REM command token, a new REM command handler was implemented that simply adds the REM command token (which contains the actual comment text in the string of the token) to the RPN output list. A new translator test (#15) was added for various REM command tests. The REM operator token is a little trickier to handle, which will be implemented next.
[commit 258f3a9df0]
Friday, April 5, 2013
Program Model Translator Integration Complete
The translator (with the parser) has now been integrated with the program model, though for now, the program model is only holding the translated RPN lists of the program lines (or error information). Eventually, the program model will hold the compiled program lines, but the encoder that will do this compiling has not yet been implemented.
The next step is to highlight any translator errors in the edit box. But first, this is a good point to make a development release. The release related files were updated, along with some minor file clean up, for a new release and the repository was given the tag v0.3.4.
[commit 2a19163e3c]
The next step is to highlight any translator errors in the edit box. But first, this is a good point to make a development release. The release related files were updated, along with some minor file clean up, for a new release and the repository was given the tag v0.3.4.
[commit 2a19163e3c]
Thursday, April 4, 2013
Comparing RPN Lists With Errors
RPN lists may also contains errors and this needs to be taken into account when comparing RPN lists. The RpnList compare operator function was modified for this by first checking if one list has an error and the other does not. If both has errors, the column and the length of the error token is compared along with the error message. If both lists do not have errors, it proceeds as before comparing the lists.
[commit d810bba51f]
[commit d810bba51f]
Comparing RPN Lists
Eventually, the program model will hold the program lines in an internal incrementally compiled format the will be ready to run. To detect when a line has changed, either the new line needs to be fully encoded into this internal format, the internal line needs to be converted (recreated) back into text, or both need to be converted to an intermediate comparable format.
I'm not sure at this moment which is best, but recreating the internal line back into text will not work because the recreated lines will not necessarily match the original lines. For example, the line "C=3" and "C = 3" don't match as text, but the internal lines are identical. Therefore, using text to compare is not an option unless the new line is compiled and then recreated (which is wasteful).
For now, the RPN lists will be compared. This required comparison operator functions (for the == and != operators) to be implemented for the Token, RpnItem and RpnList classes. Only the == operator function was fully implemented, with the != operator implemented as the opposite of the == operator. The program line string list member of the program model was moved since it is no longer needed (second commit).
[commit f33bb20df2] [commit 3a2317910c]
I'm not sure at this moment which is best, but recreating the internal line back into text will not work because the recreated lines will not necessarily match the original lines. For example, the line "C=3" and "C = 3" don't match as text, but the internal lines are identical. Therefore, using text to compare is not an option unless the new line is compiled and then recreated (which is wasteful).
For now, the RPN lists will be compared. This required comparison operator functions (for the == and != operators) to be implemented for the Token, RpnItem and RpnList classes. Only the == operator function was fully implemented, with the != operator implemented as the opposite of the == operator. The program line string list member of the program model was moved since it is no longer needed (second commit).
[commit f33bb20df2] [commit 3a2317910c]
Monday, April 1, 2013
Colon Precedence Correction
The segmentation fault mentioned in the last post that was occurring with some files (like accidentally loaded expected translator test file) was caused by the presence of a colon. The colon will be a statement separator or will indicate a label at the beginning of a line. In the translator, the colon is considered an operator. Eventually there will be a special colon token handler, but this has not yet been implemented.
The problem occurred when the colon operator token was processed as a regular operator. The precedence of the colon was set to zero, which is also the same as the NULL operator that is put on top of the of hold stack as a blocker to prevent it from being popped (because all operators are suppose to have higher precedences). However, since the colon also had a zero precedence, the translator popped the NULL operator from the hold stack. The segmentation fault occurred because the NULL operator had no expression information (a NULL pointer).
To correct this problem, the precedence of the colon operator was changed to a four, which is the same precedence as the End-of-Line operator since a colon is also indicate the end of a statement.
[commit d971d6d436]
The problem occurred when the colon operator token was processed as a regular operator. The precedence of the colon was set to zero, which is also the same as the NULL operator that is put on top of the of hold stack as a blocker to prevent it from being popped (because all operators are suppose to have higher precedences). However, since the colon also had a zero precedence, the translator popped the NULL operator from the hold stack. The segmentation fault occurred because the NULL operator had no expression information (a NULL pointer).
To correct this problem, the precedence of the colon operator was changed to a four, which is the same precedence as the End-of-Line operator since a colon is also indicate the end of a statement.
[commit d971d6d436]
Sunday, March 31, 2013
Program Model – Storing RPN Lists
The program model receives program line changes from the edit box, which up to now just stored the text of the program lines in a string list. Eventually the program model will store the internal code of the BASIC program after the line is translated and encoded. Since the encoder is not yet implemented, the output RPN lists from the translator will be stored so that more components of the GUI can be developed.
In order for the program model to store RPN lists, the program lines need to be translated, which means that the program model class needed a translator instance. A translator instance member pointer was added, which is created by the constructor and deleted in the destructor. To hold the RPN lists, a member was added for the list of RPN list pointers.
The update slot that receives the program lines from the edit box was modified to translate new lines and insert the resulting RPN list (which may contain an error); delete the RPN list for a deleted line; and delete the RPN list, translate a changed line and replace the RPN list pointer for the changed line.
The data function was modified to return the text of the RPN list for the requested line (if it doesn't have an error), or the column, length and message as a single string for a line with an error. Eventually the error will need to be highlighted some how in the edit box.
All uses of the program line string list were replaced with the new translated line RPN list. The string list member was left in and is still updated by the update slot, and it is also still used to detect line changes. Shortly this list will be removed when the comparison is made using the RPN lists.
But first a small problem needs to be investigated. During initial testing, an expected translator test file was loaded instead of the input data file and a segmentation fault occurred. Loading any text file should just produce a bunch of errors (which is did when one of the other text files used for debugging the edit box was loaded). Loading the desired translator test file and removing the comment lines produced the translated RPN lists in the program view as expected including lines with errors, which produced the expected error string.
[commit c77bdb9274]
In order for the program model to store RPN lists, the program lines need to be translated, which means that the program model class needed a translator instance. A translator instance member pointer was added, which is created by the constructor and deleted in the destructor. To hold the RPN lists, a member was added for the list of RPN list pointers.
The update slot that receives the program lines from the edit box was modified to translate new lines and insert the resulting RPN list (which may contain an error); delete the RPN list for a deleted line; and delete the RPN list, translate a changed line and replace the RPN list pointer for the changed line.
The data function was modified to return the text of the RPN list for the requested line (if it doesn't have an error), or the column, length and message as a single string for a line with an error. Eventually the error will need to be highlighted some how in the edit box.
All uses of the program line string list were replaced with the new translated line RPN list. The string list member was left in and is still updated by the update slot, and it is also still used to detect line changes. Shortly this list will be removed when the comparison is made using the RPN lists.
But first a small problem needs to be investigated. During initial testing, an expected translator test file was loaded instead of the input data file and a segmentation fault occurred. Loading any text file should just produce a bunch of errors (which is did when one of the other text files used for debugging the edit box was loaded). Loading the desired translator test file and removing the comment lines produced the translated RPN lists in the program view as expected including lines with errors, which produced the expected error string.
[commit c77bdb9274]
RPN Output List – Including Errors
When a program line is sent from the edit box to the program model, it will be translated to an RPN list. This RPN list will then be encoded into program code and stored. For now, the RPN list will be stored. However, a program line may contain an error. Program line errors will need to be displayed in the edit box and temporarily in the program view widget.
Previously, the translator held the error token (that points to the error on the line) and the error message. If there was a translation error, the RPN output list was cleared and the RPN list instance was deleted. The caller would then obtain the error token and message instead of the retrieving the RPN list. Since a program consists of many lines, several lines could contain errors. There errors need to be kept with the program line and not in the translator instance (which only holds one error; the most recent).
Since the program model will be storing the RPN lists of the program lines, the error token and error message was moved from the Translator class to the RPN List class along with their accessor functions. The RPN List instance is no longer deleted upon an error since it will be holding the error token and message, though the actual list is still cleared.
The translator's functions set input (given an input line, which was translated, and returned translation status) and output (returned the RPN output list upon successful translation) were replaced with a new translate function. This function is essentially the set input function except it now returns the RPN output list (which may contain an error). For safety, this function resets the RPN list output member pointer before returning - the caller takes possession of the RPN list instance. A new has error function was added to the RPN List used by the caller to check the translation status.
[commit 27cd073e43]
Previously, the translator held the error token (that points to the error on the line) and the error message. If there was a translation error, the RPN output list was cleared and the RPN list instance was deleted. The caller would then obtain the error token and message instead of the retrieving the RPN list. Since a program consists of many lines, several lines could contain errors. There errors need to be kept with the program line and not in the translator instance (which only holds one error; the most recent).
Since the program model will be storing the RPN lists of the program lines, the error token and error message was moved from the Translator class to the RPN List class along with their accessor functions. The RPN List instance is no longer deleted upon an error since it will be holding the error token and message, though the actual list is still cleared.
The translator's functions set input (given an input line, which was translated, and returned translation status) and output (returned the RPN output list upon successful translation) were replaced with a new translate function. This function is essentially the set input function except it now returns the RPN output list (which may contain an error). For safety, this function resets the RPN list output member pointer before returning - the caller takes possession of the RPN list instance. A new has error function was added to the RPN List used by the caller to check the translation status.
[commit 27cd073e43]
Clear RPN List Issue Resolved
The next small incremental change implemented the RpnItem::text() and RpnList::text() member functions that return string representations of the RPN item (token with any operand tokens in square brackets) and of the RPN list respectively. Previously the Tester::printOutput() function performed these tasks directly to the standard output stream. A string is now necessary so that it can be output to the program view widget.
It was hoped that having these functions would resolve the segmentation faults that was occurring at the conclusion of the foreach loop that processed the RPN list. However. it did not. Therefore, to eliminate this problem, the foreach was simply replaced with a regular for loop for the count of the items in the list using the at() function to access the elements in the list.
This eliminated the unwanted call to the destructor and a call to the clear() function was added to the destructor so it is no longer necessary to call the clear() function from the users of the RPN list instance when they are deleting the instance.
[commit e634d6f196] [commit 1438e1e987]
It was hoped that having these functions would resolve the segmentation faults that was occurring at the conclusion of the foreach loop that processed the RPN list. However. it did not. Therefore, to eliminate this problem, the foreach was simply replaced with a regular for loop for the count of the items in the list using the at() function to access the elements in the list.
This eliminated the unwanted call to the destructor and a call to the clear() function was added to the destructor so it is no longer necessary to call the clear() function from the users of the RPN list instance when they are deleting the instance.
[commit e634d6f196] [commit 1438e1e987]
Saturday, March 30, 2013
Translator RPN List Output
After two failed attempts to create an RPN list class to hold the translator output, smaller incremental changes were made and tested after each change, including the memory test, and then the small changes was committed.
The first small change implemented the new Token::text() member function that returns a string representation of the token. Previously the Tester::printSmallToken() function performed this task directly to the standard output stream. It is now necessary to have a string so that it can be output to the program view widget.
The second small change created a new RpnList class based on QList<RpnItem*>, which has all the same functionality as the original list. This class was defined in a new header file and the RpnItem class definition was moved to this header file from the translator header file. This class is necessary so that the instance of this class can also hold the error token and message.
The third small change implemented a clear memory function to the new RpnList class to delete the memory used by the RPN item instances created in the translator along with the token instance each item holds. It is a good idea to have the class perform this task and not every user of the class.
This was where at least one of the problems occurred. It made sense that the destructor for the RpnList class call this clear function so that the caller would not have clear the list before deleting the instance, but a segmentation fault occurred in the Tester::PrintOutput() function that outputs the text of the RPN List. The destructor of the instance was called, which deleted all the tokens (it appears the foreach macro is doing this). When the RPN List instance is then finally deleted, the fault occurred because the token had already been deleted.
This bad change was put on a failedClearAttempt branch [commit a16abf424a] to show what apparently cannot be done. This will be investigated next.
[commit 9d3d8bc834] [commit f49560c08f] [commit 9522d2a0ad]
The first small change implemented the new Token::text() member function that returns a string representation of the token. Previously the Tester::printSmallToken() function performed this task directly to the standard output stream. It is now necessary to have a string so that it can be output to the program view widget.
The second small change created a new RpnList class based on QList<RpnItem*>, which has all the same functionality as the original list. This class was defined in a new header file and the RpnItem class definition was moved to this header file from the translator header file. This class is necessary so that the instance of this class can also hold the error token and message.
The third small change implemented a clear memory function to the new RpnList class to delete the memory used by the RPN item instances created in the translator along with the token instance each item holds. It is a good idea to have the class perform this task and not every user of the class.
This was where at least one of the problems occurred. It made sense that the destructor for the RpnList class call this clear function so that the caller would not have clear the list before deleting the instance, but a segmentation fault occurred in the Tester::PrintOutput() function that outputs the text of the RPN List. The destructor of the instance was called, which deleted all the tokens (it appears the foreach macro is doing this). When the RPN List instance is then finally deleted, the fault occurred because the token had already been deleted.
This bad change was put on a failedClearAttempt branch [commit a16abf424a] to show what apparently cannot be done. This will be investigated next.
[commit 9d3d8bc834] [commit f49560c08f] [commit 9522d2a0ad]
Thursday, March 28, 2013
Expected Batch Test Results Change
The translator currently has several outputs depending on the input, either there is an RPN output list (if translation succeeds), or there is an error token and error message (if translation fails). For now, the program model will be changed to hold the RPN output list for each program line instead of the text of the line. However, if there is an error, details of the error (location and message) will need to be stored instead.
A new RpnList class was created to contain the list of RpnItem instances, and any error token (with location) and error message. An instance of this class will be stored in the program model. After making these changes and some other changes (though there is no point in describing these here), because as a result, all of the parser tests failed. Worst, all the expression and translator tests caused the application to crash.
The parser tests failed simply because the copyright year had been updated from 2012 to 2013. The test results could be updated for this, but this will need to be done every year. There is no point for these expected batch test output files to contain the copyright message along with the warranty and table initialization messages anyway.
Therefore, the copyright, warranty and table initialization messages were removed from the output, but these are still appropriately output in console input test mode. Since these messages are no longer being put in the expected results files, the translate tr() function was added to these strings. All of the tests results files were updated, and should not need to be updated again unless the test inputs change or for some reason the outputs change. Now back to the RPN list changes...
[commit ff17139321]
A new RpnList class was created to contain the list of RpnItem instances, and any error token (with location) and error message. An instance of this class will be stored in the program model. After making these changes and some other changes (though there is no point in describing these here), because as a result, all of the parser tests failed. Worst, all the expression and translator tests caused the application to crash.
The parser tests failed simply because the copyright year had been updated from 2012 to 2013. The test results could be updated for this, but this will need to be done every year. There is no point for these expected batch test output files to contain the copyright message along with the warranty and table initialization messages anyway.
Therefore, the copyright, warranty and table initialization messages were removed from the output, but these are still appropriately output in console input test mode. Since these messages are no longer being put in the expected results files, the translate tr() function was added to these strings. All of the tests results files were updated, and should not need to be updated again unless the test inputs change or for some reason the outputs change. Now back to the RPN list changes...
[commit ff17139321]
Saturday, March 23, 2013
Initial Program Model Complete
There were some minor problems with the Save As action causing it to not work as desired, namely the file name was incorrectly defaulting to "." and the directory of the file saved was not being remembered. The default file name was set to "." in the attempt to use the current directory, but the get save file name dialog saw this as the file name with no directory and used the directory the program was started in. The string "./" should have been used.
The way it should be working is that the file name should start with the current file name giving the user the option to replace it or modify it. If the user doesn't change the file name, the dialog will issue a warning asking if the file should be overwritten. If the current file is untitled, then the default file name will be set to the current directory, and the dialog will contain a blank file name. After the file is saved successfully, the current directory (that gets saved in the program settings upon exit) is set to the directory of the saved file.
Now it is time to start hooking up the parser and translator between the edit box and program model. But first, this is a good point to make a development release. The release related files were updated for a new release and the repository was given the tag v0.3.3.
[commit 143f449330] [commit f95a3d8d55]
The way it should be working is that the file name should start with the current file name giving the user the option to replace it or modify it. If the user doesn't change the file name, the dialog will issue a warning asking if the file should be overwritten. If the current file is untitled, then the default file name will be set to the current directory, and the dialog will contain a blank file name. After the file is saved successfully, the current directory (that gets saved in the program settings upon exit) is set to the directory of the saved file.
Now it is time to start hooking up the parser and translator between the edit box and program model. But first, this is a good point to make a development release. The release related files were updated for a new release and the repository was given the tag v0.3.3.
[commit 143f449330] [commit f95a3d8d55]
Another Undo Issue
Testing has now been completed and I think most of the possible change scenarios have been tested. There was some more problems with undo operations when at a new line that was not yet reported as inserted. For some undo operations, a line was not being reported as changed when it should have been. This occurred when the line of the beginning of the undo change was more than one line away from the current line that was new.
To correct this problem, a check was added if the line of the beginning of the change is more than one line away from the modified (new) line, then the number of lines modified is set to one from zero and since this is the next line, the changed line number is incremented.
Getting into this situation was rather complex, which required an insert of a new line (Control+Enter) in the middle of a line, moving to the end of this new line, deleting the end of this line to combine it with the next line, and then one undo. This worked so far, but doing undo again is when the problem occurred. I'm sure there could be more complex sequences that will not be detected correctly, but it's time to move on. Any new problems that occur will be dealt with as they appear.
There is also a screen update problem that sometime occurs during an undo where a entire line is not redrawn correctly on the screen. However, this was proven to be a bug in the QPlainTextEdit base class, not in the EditBox class because a simple program using just the QPlainTextEdit also exhibits the same bug (though the QTextEdit class does not).
[commit 2fc26b865a]
To correct this problem, a check was added if the line of the beginning of the change is more than one line away from the modified (new) line, then the number of lines modified is set to one from zero and since this is the next line, the changed line number is incremented.
Getting into this situation was rather complex, which required an insert of a new line (Control+Enter) in the middle of a line, moving to the end of this new line, deleting the end of this line to combine it with the next line, and then one undo. This worked so far, but doing undo again is when the problem occurred. I'm sure there could be more complex sequences that will not be detected correctly, but it's time to move on. Any new problems that occur will be dealt with as they appear.
There is also a screen update problem that sometime occurs during an undo where a entire line is not redrawn correctly on the screen. However, this was proven to be a bug in the QPlainTextEdit base class, not in the EditBox class because a simple program using just the QPlainTextEdit also exhibits the same bug (though the QTextEdit class does not).
[commit 2fc26b865a]
Friday, March 22, 2013
Paste Over Selection Update Screen Issue
Another unrelated issue was found while testing, this time with paste. The problem occurs when there is a selection, and some text is pasted over the selection, replacing the selected text. Sometimes, the screen does not update correctly where part of the selection remains.
This can be seen by first copying a single line (some characters followed by a new line) into the clipboard. Then selecting from the middle of a line to the end of the next non-empty line. Pasting at this point places the cursor at the beginning of the second, the first character on the second line is removed from the screen, but the rest of the line remains and appears selected. The document is properly updated as can be seen in the program view.
This problem was corrected by reimplementing the paste function (again). This time it was given an argument for the clipboard mode with a default of clipboard. The current text cursor is obtained. If the cursor has a selection, it is copied into a temporary cursor. With this temporary cursor, the selection is cleared and the edit box text cursor is set to the temporary cursor to applied the cleared selection. This may not be the best way to solve this issue, but several other attempts did not work and this solution did.
The selection remains in the origin cursor. The text is then obtained from the clipboard for the clipboard mode selected and inserted using the original cursor (replacing the selection if there was one). To also correct the middle-click paste, the insert text call with the current text cursor was replaced with a call to the reimplemented paste function with the clipboard selection mode.
[commit 0ef619bc5c]
This can be seen by first copying a single line (some characters followed by a new line) into the clipboard. Then selecting from the middle of a line to the end of the next non-empty line. Pasting at this point places the cursor at the beginning of the second, the first character on the second line is removed from the screen, but the rest of the line remains and appears selected. The document is properly updated as can be seen in the program view.
This problem was corrected by reimplementing the paste function (again). This time it was given an argument for the clipboard mode with a default of clipboard. The current text cursor is obtained. If the cursor has a selection, it is copied into a temporary cursor. With this temporary cursor, the selection is cleared and the edit box text cursor is set to the temporary cursor to applied the cleared selection. This may not be the best way to solve this issue, but several other attempts did not work and this solution did.
The selection remains in the origin cursor. The text is then obtained from the clipboard for the clipboard mode selected and inserted using the original cursor (replacing the selection if there was one). To also correct the middle-click paste, the insert text call with the current text cursor was replaced with a call to the reimplemented paste function with the clipboard selection mode.
[commit 0ef619bc5c]
Thursday, March 21, 2013
Handling Shift+Enter Correctly
Testing continues and no new problems have be found so far. However, an unrelated problem was discovered with the Shift+Enter key sequence. When there was no selection, a Shift+Enter behaved liked a regular Enter, either moving to the next line or entering a new line if the cursor was at the end of the line. But if there was a selection, a new line character was inserted in the middle of the line. This was evidenced because no line number was displayed including in the program view, which is the same as for a long line.
Normally, the plain text edit widget allows the insertion of a new line with Shift+Enter (like word processors). The reimplemented edit box key press event handler partially changed this behavior, but the old behavior remained when there was a selection.
I decided to make a Shift+Enter behave as extending the selection (or starting a selection if none is present) to the beginning of the next line. This is the same as when holding the Shift with other movement keys (arrows, Home, End, etc.). There is no reason to allow new lines to be inserted in the middle of program lines.
This was corrected by incepting the Shift+Enter key sequence first. The same moveCursor() function is called with the same NextBlock move operation, but instead of using the default MoveAnchor move mode, the KeepAnchor move mode was added, which extends (or starts) a selection.
[commit 32149da677]
Normally, the plain text edit widget allows the insertion of a new line with Shift+Enter (like word processors). The reimplemented edit box key press event handler partially changed this behavior, but the old behavior remained when there was a selection.
I decided to make a Shift+Enter behave as extending the selection (or starting a selection if none is present) to the beginning of the next line. This is the same as when holding the Shift with other movement keys (arrows, Home, End, etc.). There is no reason to allow new lines to be inserted in the middle of program lines.
This was corrected by incepting the Shift+Enter key sequence first. The same moveCursor() function is called with the same NextBlock move operation, but instead of using the default MoveAnchor move mode, the KeepAnchor move mode was added, which extends (or starts) a selection.
[commit 32149da677]
Subscribe to:
Posts (Atom)