Part of learning to use C++ more effectively should include the latest C++ standard, which at the moment is C++11. Support for C++11 is being or has been implemented in compilers. This project uses GCC (The GNU Compiler Collection), which is standard on Linux systems and can be installed on Windows systems (the MinGW program is the one recommended). Sorry MAC OS-X users, I do not have access to MAC system to figure what is needed to build and run this project on OS-X even though OS-X is Linux like and shouldn't be much different than Linux.
Even though many of the recent GCC versions support various features of C++11 (which was previously known as C++0X before the standard was finalized) starting with GCC 4.3, all the C++11 features highlighted in the The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup require and more recent version of GCC, specifically GCC 4.8 or later. Fortunately, this version is available both on Linux (the current Mint/Ubuntu LTS or Long-Term-Support versions) and MinGW (Windows).
The current version of GCC on Mint 13 LTS (Ubuntu 12.04 LTS) is only GCC 4.6.3. Fortunately there is a way to update to GCC 4.8.1 by adding the tool chains repository. On Mint 17 LTS (Ubuntu 14.04 LTS) GCC 4.8.2 is available. The latest version installed with MinGW is also GCC 4.8.1. However, since Qt is also required, it is easier to install Qt that includes MinGW, which happens to have GCC 4.8.2 GCC 4.8 should be sufficient for using the major C++11 features. Details for upgrading and installing the necessary versions and tools will be provided in subsequent posts.
Monday, August 4, 2014
Sunday, August 3, 2014
Project – Better C++
The primary goals for this project was to get back to C++ programming, to learn using it more effectively after more than a decade doing only C programming, and to learn GUI programming. Creating an incremental (interactive) BASIC compiler seemed to be an ideal way to accomplish this. The GUI programming came later with the selection and use of the Qt toolkit. Learning about the CMake build system and the git distributed revision control also came along the way.
After reading the book API Design For C++ by Martin Reddy recommended by a coworker, I started to get more of a taste for what C++ is capable of. Even though this project is not an API (Application Programming Interface), when you think about it, any C++ class is an like API for other code that uses it.
I then picked up an old C++ book I purchased over two decodes ago when I was first learning C++, but couldn't get past the first chapter at the time. I won't bother mentioning the title since this 1989 book is way out of date now (for example, C++ did not even have templates or the delete[] operator when the book was written). Any way, I read the book and it wasn't really that bad, so I decided to pick up a more up to date book on C++.
I selected the book The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup (the creator of C++). I never liked older editions of this book, but decided to give this book a try since it includes the new C++11 standard. I've picked up quite a bit that I did not previously know about C++ and I'm barely into the book at this point. What I have realized that parts of what has been implemented in the project fails at being good C++ code.
One example is the memory management of tokens. A lot of work went into tracking tokens. There were two separate implementations in the attempt to make sure the ownership of the tokens and allocation of tokens worked properly - and to report any errors upon termination of the application. The C++ facility of overloading the new and delete operators was used to accomplish this. There is a better C++ facility using existing library classes that can be used to drastically simplify this.
Another example is the code table that holds information for all the BASIC program elements (commands, operators, functions, etc.). The current solution is very much a straight C solution with C++ wrapped around it. The current method on how code IDs are assigned is very kludgy (via an awk script that scans for special comments in a source file). The method of how associated codes are setup is also very kludgy (via elaborate C macros). As a result, it is very easy to setup table entries incorrectly. There must be a better way to accomplish this with C++ (though I'm not sure what that is yet).
After reading the book API Design For C++ by Martin Reddy recommended by a coworker, I started to get more of a taste for what C++ is capable of. Even though this project is not an API (Application Programming Interface), when you think about it, any C++ class is an like API for other code that uses it.
I then picked up an old C++ book I purchased over two decodes ago when I was first learning C++, but couldn't get past the first chapter at the time. I won't bother mentioning the title since this 1989 book is way out of date now (for example, C++ did not even have templates or the delete[] operator when the book was written). Any way, I read the book and it wasn't really that bad, so I decided to pick up a more up to date book on C++.
I selected the book The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup (the creator of C++). I never liked older editions of this book, but decided to give this book a try since it includes the new C++11 standard. I've picked up quite a bit that I did not previously know about C++ and I'm barely into the book at this point. What I have realized that parts of what has been implemented in the project fails at being good C++ code.
One example is the memory management of tokens. A lot of work went into tracking tokens. There were two separate implementations in the attempt to make sure the ownership of the tokens and allocation of tokens worked properly - and to report any errors upon termination of the application. The C++ facility of overloading the new and delete operators was used to accomplish this. There is a better C++ facility using existing library classes that can be used to drastically simplify this.
Another example is the code table that holds information for all the BASIC program elements (commands, operators, functions, etc.). The current solution is very much a straight C solution with C++ wrapped around it. The current method on how code IDs are assigned is very kludgy (via an awk script that scans for special comments in a source file). The method of how associated codes are setup is also very kludgy (via elaborate C macros). As a result, it is very easy to setup table entries incorrectly. There must be a better way to accomplish this with C++ (though I'm not sure what that is yet).
Saturday, January 11, 2014
Program – Saving Text Of Error Lines
Now that two minor problems found during testing have been corrected, the next step in changing the program loading process is to handle lines with errors when loading the program. This is accomplished by saving the text of the line with an error in the line information array (which also contains the offset into the program code, the code size, and error index if any of the line).
When a line has an error, the text of the line is stored in the new text variable in the line information for the line. This variable is cleared when a line does not have an error. Now, when the text of a line is requested (by the edit box when processing a program change signal), if the line has an error, this text is returned instead of recreating the code for the line (since there is no code for the line).
When a line is changed or inserted and the line has an error, a program change signal is no longer emitted. Only the edit box changes and it already has the text of lines inserted with an error. However, when a line is appended, a program change signal is always emitted regardless of whether it has an error (lines will only be appended during loading and the edit box will need the text for all lines including those with errors).
The program changed slot of the edit box class was modified to no longer check for lines with errors (by checking if the line text string was null) because the program unit attached no longer sends signals for lines with errors (if the change originated from the edit box).
[commit 4a110b2735]
When a line has an error, the text of the line is stored in the new text variable in the line information for the line. This variable is cleared when a line does not have an error. Now, when the text of a line is requested (by the edit box when processing a program change signal), if the line has an error, this text is returned instead of recreating the code for the line (since there is no code for the line).
When a line is changed or inserted and the line has an error, a program change signal is no longer emitted. Only the edit box changes and it already has the text of lines inserted with an error. However, when a line is appended, a program change signal is always emitted regardless of whether it has an error (lines will only be appended during loading and the edit box will need the text for all lines including those with errors).
The program changed slot of the edit box class was modified to no longer check for lines with errors (by checking if the line text string was null) because the program unit attached no longer sends signals for lines with errors (if the change originated from the edit box).
[commit 4a110b2735]
Dictionary – Remove Correction
A minor problem was discovered with the dictionary class, which can be demonstrated by entering the single statement "a=0" into an empty program and then introducing an error on the line (for example, "a=0b") and entering the line. Once the error is removed, the line is recreated incorrectly as " = 0" (note the space where the "a" should be).
When the statement is first entered, the "a" variable gets entered into the dictionary as "A" (because variable names are case insensitive). When the error is introduced, the statement is dereferenced (both the variable "a" and the constant "0" should be removed from the dictionaries). However, when the attempt to remove "a" from the hash in the dictionary, it does not match the "A" that was put into the hash originally. The dictionary item is removed (from the key list). When the "a" is added back, the dictionary sees that it is already in the hash because it was not correctly removed and returns it index and the name doesn't get added back to the key list, which still has an empty name for the index.
This problem was corrected by adding a case sensitivity argument to the remove functions of the dictionary and info dictionary classes with a default of case insensitive (same as for the add functions). For dictionaries that use the case sensitive option (remark and string constant), they must also use it when removing dictionary entries. The remove function converts the obtained key from the key list for the index specified to upper case for a case insensitive dictionary so that the hash is properly removed.
[commit d7dec3ca11]
When the statement is first entered, the "a" variable gets entered into the dictionary as "A" (because variable names are case insensitive). When the error is introduced, the statement is dereferenced (both the variable "a" and the constant "0" should be removed from the dictionaries). However, when the attempt to remove "a" from the hash in the dictionary, it does not match the "A" that was put into the hash originally. The dictionary item is removed (from the key list). When the "a" is added back, the dictionary sees that it is already in the hash because it was not correctly removed and returns it index and the name doesn't get added back to the key list, which still has an empty name for the index.
This problem was corrected by adding a case sensitivity argument to the remove functions of the dictionary and info dictionary classes with a default of case insensitive (same as for the add functions). For dictionaries that use the case sensitive option (remark and string constant), they must also use it when removing dictionary entries. The remove function converts the obtained key from the key list for the index specified to upper case for a case insensitive dictionary so that the hash is properly removed.
[commit d7dec3ca11]
Friday, January 10, 2014
Edit Box – New Program Correction
A problem was found with the New program command. The problem occurs when clearing (New) the loaded program. After clearing the program, as soon as a character is entered, a crash occurred. The problem occurred because while the document in the edit box was cleared, several of the other variables were not, so the edit box tried to remove all the lines from the attached program unit that had already been removed. The extra selections list, line count, modified line number, and modified line is new flag variables also needed to be reset.
[commit 96557e5562]
[commit 96557e5562]
Wednesday, January 8, 2014
Program – Append Update Operation
Complicating the new loading process is the handling of lines with errors. When a line containing an error is entered into the edit box, no recreation of the line is necessary since the edit box already has the text. However, when a program is being loaded from a file and a line has an error, the text of the line has to be entered into the edit box.
When the edit box retrieves the recreated text for a changed line, the program unit returns a null string for a line with an error. For null strings (lines with errors), the edit box ignores the line since it already has the line in the document. The program unit will be changed to return the line with an error, and it will not send a program change signal if the line originated by a change from the edit box document. However, when the program class is loading a program from a file, it will send program change signals for lines with errors.
The program unit will need to know whether an update came from the edit box (no signal) or program load (send signal). During the loading of the program, the lines are loaded sequentially and each will be added (appended) to the end of the program. If the current program unit update routine was used as is, the new program load routine would need to maintain a line number which would be incremented for each line and passed to the update routine.
To simplify the program load routine and give the update routine the ability to determine the caller (edit box or program load), a new append operation was added (in addition to the insert, change and remove operations). The update routine detects the append operation by whether the line number passed to it is set to a -1, which the program load routine will use as it adds lines to the end of the program (and it won't need to keep track of line numbers).
When the update routine sees the line number set to -1, it sets the operation to append and the line number to the current count of lines in the program. Otherwise, the append operation is the same as the insert operation. The operation enumeration was moved from the error list header file to the program model header file with the new append operation. This enumeration was only in the error list header file for the set change index routine, but this routine had been removed though its definition was accidentally left behind (it was removed).
[commit b795a47120]
When the edit box retrieves the recreated text for a changed line, the program unit returns a null string for a line with an error. For null strings (lines with errors), the edit box ignores the line since it already has the line in the document. The program unit will be changed to return the line with an error, and it will not send a program change signal if the line originated by a change from the edit box document. However, when the program class is loading a program from a file, it will send program change signals for lines with errors.
The program unit will need to know whether an update came from the edit box (no signal) or program load (send signal). During the loading of the program, the lines are loaded sequentially and each will be added (appended) to the end of the program. If the current program unit update routine was used as is, the new program load routine would need to maintain a line number which would be incremented for each line and passed to the update routine.
To simplify the program load routine and give the update routine the ability to determine the caller (edit box or program load), a new append operation was added (in addition to the insert, change and remove operations). The update routine detects the append operation by whether the line number passed to it is set to a -1, which the program load routine will use as it adds lines to the end of the program (and it won't need to keep track of line numbers).
When the update routine sees the line number set to -1, it sets the operation to append and the line number to the current count of lines in the program. Otherwise, the append operation is the same as the insert operation. The operation enumeration was moved from the error list header file to the program model header file with the new append operation. This enumeration was only in the error list header file for the set change index routine, but this routine had been removed though its definition was accidentally left behind (it was removed).
[commit b795a47120]
Tuesday, January 7, 2014
Program Loading Process
The main window class currently loads the entire text of the program read from the selected file. This text is given to the edit box instance using the setPlainText function, which is overloaded from the QPlainTextEdit base class, and just resets the cursor valid flag before calling the base class function.
The document of the edit box then emits a document changed signal, which is processed and the attached program unit is updated. The cursor valid flag prevents the program change and error signals from the updated program unit from being processed, otherwise an infinite loop would occur. Once the cursor is moved (the cursor position is changed after the document is changed), the cursor valid flag is set and the errors are processed.
This process will be changed to where the new program class will load the program from the file into the program unit. Later all the subroutines and functions that are included in the program file will be detected and each loaded into a separate program unit. This change in the program loading process will be handled over several sets of changes and will be explained in the next set of posts.
The document of the edit box then emits a document changed signal, which is processed and the attached program unit is updated. The cursor valid flag prevents the program change and error signals from the updated program unit from being processed, otherwise an infinite loop would occur. Once the cursor is moved (the cursor position is changed after the document is changed), the cursor valid flag is set and the errors are processed.
This process will be changed to where the new program class will load the program from the file into the program unit. Later all the subroutines and functions that are included in the program file will be detected and each loaded into a separate program unit. This change in the program loading process will be handled over several sets of changes and will be explained in the next set of posts.
Sunday, January 5, 2014
Edit Box – Error Handling During Startup
During startup when the program is loaded into the edit box, any errors detected in the program were saved in a member variable until the cursor became valid. A valid cursor is needed in order to generated the extra selections used to highlight the errors. The error list changed routine was then called, which would process the saved errors and clear the saved errors list.
The mechanism was modified where any errors are ignored during startup. When the cursor becomes valid, the errors are retrieved from the attached program unit and the extra selections are generated. The saved error list member variable was no longer needed and was removed. Access functions were added to the program model to obtain the error count and an error item by index.
[commit 10724e4aab]
The mechanism was modified where any errors are ignored during startup. When the cursor becomes valid, the errors are retrieved from the attached program unit and the extra selections are generated. The saved error list member variable was no longer needed and was removed. Access functions were added to the program model to obtain the error count and an error item by index.
[commit 10724e4aab]
Edit Box – Line Wrapping Problem
While working on the next set of changes, an unrelated problem was discovered with error highlighting. The problem occurred when there were long lines that wrapped onto the next line. The problem was first noticed when a line with an error was modified and error was shifted to the wrong place. The problem also occurred in other situations, including moving to an error that was in the wrapped portion of a line, or when a recreated line was after a wrapped line.
The problem was identified to be the use of the findBlockByLineNumber() function, a member of the QTextDocument class that holds the document of the edit box (in the QPlainTextEdit base class). This function was being used to get the text block for a given line number, which was then used to gets its position within the document to set the position of the cursor.
However, this function was not working as expected. What it actually does is return the text block of the actual physical line specified, which takes into account wrapped lines where each part of a wrapped line counts as separate lines. The findBlockByNumber() function does work as needed and does not consider wrapped lines. This latter function was already being used in two places, but not in three others.
On the surface, these two functions appear to do the same thing for a plain text document. The only difference in the help documentation was in the argument, one taking a line number and the other taking a block number. It was incorrectly assumed that line number meant the same thing as block number. It is true that each line is a block in a plain text document, but a line number actually represents the physical line on the screen. Once the latter function was used throughout, there were no problems.
[commit bf7fb54a79]
The problem was identified to be the use of the findBlockByLineNumber() function, a member of the QTextDocument class that holds the document of the edit box (in the QPlainTextEdit base class). This function was being used to get the text block for a given line number, which was then used to gets its position within the document to set the position of the cursor.
However, this function was not working as expected. What it actually does is return the text block of the actual physical line specified, which takes into account wrapped lines where each part of a wrapped line counts as separate lines. The findBlockByNumber() function does work as needed and does not consider wrapped lines. This latter function was already being used in two places, but not in three others.
On the surface, these two functions appear to do the same thing for a plain text document. The only difference in the help documentation was in the argument, one taking a line number and the other taking a block number. It was incorrectly assumed that line number meant the same thing as block number. It is true that each line is a block in a plain text document, but a line number actually represents the physical line on the screen. Once the latter function was used throughout, there were no problems.
[commit bf7fb54a79]
Saturday, January 4, 2014
Main Window – Multiple Edit Boxes
The application will eventually support multiple edit boxes where the subroutines and functions can be opened at the same time in additional edit boxes. The main routine or any of the subroutines or functions could also be opened in multiple edit boxes. This support will be added later, but some preparation work can be done and this will be useful in the reorganization of the program and edit box classes.
Currently there is a list of actions that are built and given to the edit box instance for its context menu. This context menu will only be assigned to the edit box that is currently active and only one edit box will be active at a given time (the one that has focus). When the focus changes to a different edit box, the context menu needs to be removed from the edit box losing focus and added to the one gaining focus. To make this easier, the list of actions are built and stored into a new member variable. This list will be assigned to an edit box instance as needed.
In addition to setting the actions (context menu) of an edit box, the various signals from the edit box needs to be connected to the various actions in the context menu (for enabling and disabling the actions) and to the status bar update slot (for the cursor changed signal). These items need to be done when an edit box instance becomes active. For the edit box losing focus, the context menu (actions) needs to be removed and the signals disconnected.
This code was put into a new edit box set active routine that takes an edit box instance as an argument. Preliminary code was added for first disconnecting the signals and removing the actions of the edit box losing focus. This code was commented since there is currently only one edit box instance.
[commit 5b8741768c]
Currently there is a list of actions that are built and given to the edit box instance for its context menu. This context menu will only be assigned to the edit box that is currently active and only one edit box will be active at a given time (the one that has focus). When the focus changes to a different edit box, the context menu needs to be removed from the edit box losing focus and added to the one gaining focus. To make this easier, the list of actions are built and stored into a new member variable. This list will be assigned to an edit box instance as needed.
In addition to setting the actions (context menu) of an edit box, the various signals from the edit box needs to be connected to the various actions in the context menu (for enabling and disabling the actions) and to the status bar update slot (for the cursor changed signal). These items need to be done when an edit box instance becomes active. For the edit box losing focus, the context menu (actions) needs to be removed and the signals disconnected.
This code was put into a new edit box set active routine that takes an edit box instance as an argument. Preliminary code was added for first disconnecting the signals and removing the actions of the edit box losing focus. This code was commented since there is currently only one edit box instance.
[commit 5b8741768c]
Friday, January 3, 2014
Program View – Edit Box Dependencies
Continuing with the reorganization of the program and edit box classes, the program view dock widget used in the main window class and is connected to the program unit, contained two minor dependencies on the edit box class the needed to be removed. One of these dependencies required the edit box instance to be created before the program view widget could be initialized.
This dependency was that the font of the program view was set to the same fixed width font set in the edit box. In was not necessary to use this font for the program view. In fact, using the default proportional font uses less width than the fixed width font. So the font of the program view widget is no longer set to the edit box font letting it use the default font.
The other dependency was in the creation of the program line delegate used to draw the program lines of the program view widget. The base line number is passed to this delegate so that it knows what line number to use for the first program line. This constant is currently set to zero so that the line numbers match the program line indexes to make debugging easier. This constant was defined in the edit box class since it also needs this value. To eliminate the dependency on the edit box class definition, this constant was moved to the main header file as a global definition.
[commit f06fa7c304]
This dependency was that the font of the program view was set to the same fixed width font set in the edit box. In was not necessary to use this font for the program view. In fact, using the default proportional font uses less width than the fixed width font. So the font of the program view widget is no longer set to the edit box font letting it use the default font.
The other dependency was in the creation of the program line delegate used to draw the program lines of the program view widget. The base line number is passed to this delegate so that it knows what line number to use for the first program line. This constant is currently set to zero so that the line numbers match the program line indexes to make debugging easier. This constant was defined in the edit box class since it also needs this value. To eliminate the dependency on the edit box class definition, this constant was moved to the main header file as a global definition.
[commit f06fa7c304]
Thursday, January 2, 2014
Main Window – Status Bar Ready Flag
In the main window class there was a flag indicating when the status bar was ready to accept the signal from the edit box for when the cursor was moved. The line and columns numbers in the status bar along with the message are updated when this signal is received.
The status bar ready flag was needed in the program load routine to prevent the "Program loaded" message was being displayed during the initial loading of a program at startup because the status bar was not created yet. The status bar was created after the edit box instance and the program was loaded. The edit box instance needed to be created first since that is where the program was loaded to, and the status bar create routine made the connection from the edit box cursor changed signal to the state bar create slot.
The main window constructor was modified to create the status bar first. The connection of the signal was moved from the status bar create routine to after where the other edit box to main window signal/slot connections are made. This eliminated the need for the status bar ready flag and it was removed.
[commit ac678921b3]
The status bar ready flag was needed in the program load routine to prevent the "Program loaded" message was being displayed during the initial loading of a program at startup because the status bar was not created yet. The status bar was created after the edit box instance and the program was loaded. The edit box instance needed to be created first since that is where the program was loaded to, and the status bar create routine made the connection from the edit box cursor changed signal to the state bar create slot.
The main window constructor was modified to create the status bar first. The connection of the signal was moved from the status bar create routine to after where the other edit box to main window signal/slot connections are made. This eliminated the need for the status bar ready flag and it was removed.
[commit ac678921b3]
Sunday, December 29, 2013
Program – New Action
The next addition to the program class is to handle the New program action. Previously, the clear function of the edit box was called. This function is part of the QPlainTextEdit base class that the edit box class is derived from. When this function was called, it generated a document changed signal, which the edit box processed and ended up clearing the program unit that was attached to the edit box. However, the program class should have this responsibility since there may not be an attached edit box.
The new action routine in the main window class was modified to call the new clear function in the program class. This new clear function calls a new clear function of the program unit member (a program model instance). Eventually, all of the program units of the program (for subroutines and functions) will be deleted with only the program unit for the main routine being cleared.
The new program model class clear function clears the line information list, program code vector, error list and all of the dictionaries. This required new clear functions be added to the dictionary and information dictionary classes. A new clear function was also added to the abstract information class, which was implemented for the constant number and string information classes. Finally, the clear function sends the new program cleared signal, which is connected to the edit box clear funtion.
The clear function was reimplemented in the edit box class. This was necessary so that a flag could be set before calling the clear function of the QPlainTextEdit base class. This flag indicates to the document changed slot of the edit box routine that the signal should be ignored as it didn't originate by editing the program. The recreating line flag, that is used to ignore document changes when lines are replaced with their recreated text, was used for this purpose. This flag was renamed to the more appropriate ignore change.
A minor problem was also corrected in the main window class. Previously, before a program was saved, the main window instance called the capture modified line routine of the edit box to make sure that any changes made to the current line are saved. This normally takes place when the cursor is moved from the line being changed. This check also needs to take place before the check to see if the program should be saved before it is cleared by the new action. This functionality was put into the new program capture edit changes routine since it is called from two different places.
[commit 8d6e5703c0]
The new action routine in the main window class was modified to call the new clear function in the program class. This new clear function calls a new clear function of the program unit member (a program model instance). Eventually, all of the program units of the program (for subroutines and functions) will be deleted with only the program unit for the main routine being cleared.
The new program model class clear function clears the line information list, program code vector, error list and all of the dictionaries. This required new clear functions be added to the dictionary and information dictionary classes. A new clear function was also added to the abstract information class, which was implemented for the constant number and string information classes. Finally, the clear function sends the new program cleared signal, which is connected to the edit box clear funtion.
The clear function was reimplemented in the edit box class. This was necessary so that a flag could be set before calling the clear function of the QPlainTextEdit base class. This flag indicates to the document changed slot of the edit box routine that the signal should be ignored as it didn't originate by editing the program. The recreating line flag, that is used to ignore document changes when lines are replaced with their recreated text, was used for this purpose. This flag was renamed to the more appropriate ignore change.
A minor problem was also corrected in the main window class. Previously, before a program was saved, the main window instance called the capture modified line routine of the edit box to make sure that any changes made to the current line are saved. This normally takes place when the cursor is moved from the line being changed. This check also needs to take place before the check to see if the program should be saved before it is cleared by the new action. This functionality was put into the new program capture edit changes routine since it is called from two different places.
[commit 8d6e5703c0]
Tuesday, December 24, 2013
Program – Program Unit
Continuing with the transition to the new program class, the pointer to the program model was moved from the main window class to the program class and renamed to unit. When support for subroutines and functions is added, the single unit will become a list of units with the first one holding the main routine and the list growing for each subroutine and function added to the program. An access function for the program unit was also added to the program class.
[commit 5bc9d15f43]
[commit 5bc9d15f43]
Saturday, December 21, 2013
Program – New Program Class
Currently a program is loaded by the main window class and given to the edit box using the set plain text access function. This will set the text document of the edit box, which causes a document changed signal. When this signal is processed, the edit box updates the program unit that is attached. Because the text cursor is not valid during this operation, the recreated text from the program model cannot be inserted into the text document (the first of two issues mentioned in the last post).
One way to resolve this issue is to load the program directly into the program unit bypassing the edit box. The program generates signals that lines have been changed by line number. The edit box receives these signals, retrieves the recreated text for the lines from the program and puts them into the document. Special handling is needed for lines that contain errors since there would be no code for these lines to recreate text from.
Eventually, when support for subroutines and functions is added, a loaded program will consist of a number of program units, one for the main routine and one for each of the subroutines and functions. The program will consist of a list of program units. When a program is loaded, the load routine will create a new program unit for each routine or function. Likewise for the save routine, which accesses the list of program units.
The list of program units will be contained in a new program class. This class will contain the routines for loading and saving programs. The current program file path name will also be contained in this class. New source and header files were added for the new program class. To start simple, the new class only contains the program file path. Since the file path is included in the applications settings, save and restore settings routines were also implemented.
[commit 17f3e958ed]
One way to resolve this issue is to load the program directly into the program unit bypassing the edit box. The program generates signals that lines have been changed by line number. The edit box receives these signals, retrieves the recreated text for the lines from the program and puts them into the document. Special handling is needed for lines that contain errors since there would be no code for these lines to recreate text from.
Eventually, when support for subroutines and functions is added, a loaded program will consist of a number of program units, one for the main routine and one for each of the subroutines and functions. The program will consist of a list of program units. When a program is loaded, the load routine will create a new program unit for each routine or function. Likewise for the save routine, which accesses the list of program units.
The list of program units will be contained in a new program class. This class will contain the routines for loading and saving programs. The current program file path name will also be contained in this class. New source and header files were added for the new program class. To start simple, the new class only contains the program file path. Since the file path is included in the applications settings, save and restore settings routines were also implemented.
[commit 17f3e958ed]
Sunday, December 15, 2013
Edit Box – Recreated Line Replacement
When a program line is changed or inserted, the line should be recreated and the recreated text should replace the line entered in the edit box. To accomplish this, the program model class will send a signal with the line number of a line that is changed or inserted. The edit box will receive this signal, retrieve the recreated text for the line, and replace the text of the line with this recreated text.
The new program changed signal was added to the program model class. The update line routine was modified to send this signal when a line is changed or inserted. When a line is changed, the actual code of the line may not have changed, for example, if spaces were added or removed, or the case of keywords was changed. In this case, the program code will not be modified, but this signal still needs to be sent so that the edit box reflects the correct recreated program code.
The new program changed slot routine was added to the edit box class, which starts be retrieving the recreated text for the changed line. A text cursor is obtained for the edit box and its position is set to the beginning position of the block containing the line. The cursor is moved to the end of the block keeping the anchor at the beginning, which selects the entire line. The recreated text is inserted at the cursor and since text is selected, the selected text is replaced.
The program model line text routine was modified to return a null string if the line has an error. The program changed slot routine does not replace the text if the text is null indicating that the line has an error. This required the recreator class recreate routine to be modified where the output string is initialized to an empty string (a pair of double quotes) instead of being cleared. Clearing a string creates a null string, and a null string is not quite the same as an empty string (a null string is empty but an empty string is not null).
When text is replaced in the document using a text cursor, document changed and cursor moved signals are generated from the document. These signals need to be ignored when the line is being recreated, otherwise an infinite loop occurs because the document change signal updates the program, which generates another program changed signal, an so on. A flag was added to the edit box and is set before replacing text and cleared afterward. The document changed and cursor moved slot routines were modified to do nothing if this flag is set.
There are two unresolved issues resulting from these changes. The first issue occurs during the initial loading of a program. As a new program is being loaded, each line added to the program should be recreated to the edit box. However, this cannot occur because until the program has been loaded into the document of the edit box, the text cursor is not valid, so can't be used to replace text. The second issue occurs when a line is replaced with recreated text; extra undo commands are added to the undo stack.
[commit 4b34bd2dde]
The new program changed signal was added to the program model class. The update line routine was modified to send this signal when a line is changed or inserted. When a line is changed, the actual code of the line may not have changed, for example, if spaces were added or removed, or the case of keywords was changed. In this case, the program code will not be modified, but this signal still needs to be sent so that the edit box reflects the correct recreated program code.
The new program changed slot routine was added to the edit box class, which starts be retrieving the recreated text for the changed line. A text cursor is obtained for the edit box and its position is set to the beginning position of the block containing the line. The cursor is moved to the end of the block keeping the anchor at the beginning, which selects the entire line. The recreated text is inserted at the cursor and since text is selected, the selected text is replaced.
The program model line text routine was modified to return a null string if the line has an error. The program changed slot routine does not replace the text if the text is null indicating that the line has an error. This required the recreator class recreate routine to be modified where the output string is initialized to an empty string (a pair of double quotes) instead of being cleared. Clearing a string creates a null string, and a null string is not quite the same as an empty string (a null string is empty but an empty string is not null).
When text is replaced in the document using a text cursor, document changed and cursor moved signals are generated from the document. These signals need to be ignored when the line is being recreated, otherwise an infinite loop occurs because the document change signal updates the program, which generates another program changed signal, an so on. A flag was added to the edit box and is set before replacing text and cleared afterward. The document changed and cursor moved slot routines were modified to do nothing if this flag is set.
There are two unresolved issues resulting from these changes. The first issue occurs during the initial loading of a program. As a new program is being loaded, each line added to the program should be recreated to the edit box. However, this cannot occur because until the program has been loaded into the document of the edit box, the text cursor is not valid, so can't be used to replace text. The second issue occurs when a line is replaced with recreated text; extra undo commands are added to the undo stack.
[commit 4b34bd2dde]
Subscribe to:
Posts (Atom)