Implementation of a code editor

Source: Internet
Author: User
Tags textout

I spent a lot of time writing a code editor over the past year. Most of the time, various functions are implemented, and many problems have been encountered. Now we can write out some solutions to the problems that implement this editing Control for your reference. Here, I use MFC. Of course, there is no ready-made control, but I directly inherit from cwnd to implement my own editing control.

Please give us a try. You can download the cutec editor here. Your comments are welcome.

 

Question 1: how to make the control accept all the buttons and Chinese characters.
Question 2: How to calculate the cursor position.
Question 3: how to store the text content of the editing control.
Question 4: How to highlight keywords.
Question 5: How to implement automatic line feed.
Question 6: How to parse the script. Well, I wrote a C language interpreter, which is quite good.

I. How to make the control accept all the buttons and Chinese characters.
It is easy to let cwnd receive all the buttons. You only need to respond to wm_getdlgcode. The Code is as follows:
Afx_msg uint ongetdlgcode ();
...
On_wm_getdlgcode ()
...
Uint cleditwnd: ongetdlgcode (){
Return dlgc_wantallkeys;
}

It is troublesome to receive Chinese characters. You must respond to the wm_ime_char message. I have to do the following. I wonder if there is any simpler method.
1. Reset the wnd_proc function of the form. Obtain the wm_ime_char message in this function, and return our cwnd form through custom consumption.
Wndproc leditwndprocold;
Lresult leditwndprocnew (hwnd, uint umsg, wparam, lparam ){
Cwnd * pwnd = cwnd: fromhandlepermanent (hwnd );
If (umsg = wm_ime_char ){
Pwnd-> postmessage (wm_ledit_zw, wparam, lparam );
Return 0;
}
Return callwindowproc (leditwndprocold, hwnd, umsg, wparam, lparam );
}
...
Void cleditwnd: presubclasswindow (){
Leditwndprocold = (wndproc) setwindowlong (this-> getsafehwnd (), gwl_wndproc, (long) leditwndprocnew );
Cwnd: presubclasswindow ();
}
2. Respond to the wm_ledit_zw custom message to get Chinese characters.

Set the leditwndprocnew callback function in presubclasswindow and assign the returned value to leditwndprocold. In the leditwndprocnew function, the wm_ime_char message is sent back to the cleditwnd form through custom consumption wm_ledit_zw. The Chinese characters are saved in the wparam parameter. Char Hz [3] = {wparam> 8, wparam, 0 };

2. How to calculate the cursor position.
This problem seems simple, but it is actually the most difficult to debug in the Process of program development. First, we need to clarify the following issues:
1. To know the position of the row where the cursor is located, calculate the pixel position in the interface.
2. Know the cursor position and convert it to the position corresponding to the string.
Windows provides gettextextent to calculate the string display width. We know that calling this function can solve the above problems. But when you do this, you know how low the efficiency is. When you move the mouse over the selected content, you must calculate the cursor position in time, you will know that efficiency cannot keep up. After thinking for a long time, I finally came up with a solution:
After creating the control, call gettextextent to calculate the width of all English characters and Chinese characters. Then, we will not directly call the gettextextent function. The string width is calculated based on the calculated character width. The efficiency is greatly improved. I have provided the relevant code here.
Char data [2];
M_ctext.ncharwidth [0] = 0;
For (I = 1; I <256; I ++ ){
Data [0] = I;
Data [1] = 0;
M_ctext.ncharwidth [I] = (unsigned char) PDC-> gettextextent (data). CX;
}
M_ctext.ncharwidth [256] = (unsigned char) PDC-> gettextextent ("medium"). CX;

The information in the ncharwidth array is sufficient to calculate the display width of any string. The only drawback is that when changing the font, we must replace the array content.

3 (1). How to store the text content of the editing Control
When opening a file and editing a file, we must store the latest content of the file in the memory and update it to the interface in real time. On MFC, nothing is more suitable than cstringarray. Although some people say that cstringarray will leak memory, I did not find this problem after testing, I always think that the Code of the Person who said this was not written. Cstringarray estimates that the insertion efficiency of data in many rows is not high, but we separate the file processing. Cstringarray provides array and string functions, making string operations much easier. The only disadvantage is that we must pre-process the file and save each row of the file to cstringarray. Reading large files wastes some time.

3 (2). Another important issue is the processing of large files. I have specially processed large files.
1. Use a memory ing file to scan the entire file and extract travel information.
2. Block Processing is used to operate the entire file, so that the data stored in the control is only a block of the file.
3. When a large file is modified and the block is switched, the block data must be stored in the memory or saved to another intermediate file. For unmodified blocks, no processing is required.
4. When saving a large file, you must re-write the file based on each piece of information.
* Block 01
* Block 02
* Block 03
*...
* Block N
Each block must store its related information. I have defined a class and declared it as follows:
Class cblocknode
{
Public:
Cblocknode ();
~ Cblocknode ();
Public:
_ Int64 lblkbegin; // start position of the block in the file
Long lblksize; // block size
Long llinetop; // start line
Long llinelow; // end line
Cstring sleftstring; // The remaining row of the block. It must be the segment between the connected blocks. One row may be separated. The first half of the last row is saved here.
// Special processing is required to ensure that the two parts are linefeeds. You can ensure that the field is empty.
Char * pdirtyctx; // dirty data, used to save the modified block data. If it is null, it indicates that the block has not been modified.

Public:
Cblocknode & operator = (cblocknode & SRC );
};

4. How to highlight keywords.
1. How to save keywords in the configuration file for everyone. The key issue is how to quickly find the keyword in the string.
2. When there are many keywords, the search efficiency will be well-tuned.
3. How to keep information in the memory and display it on the interface.
Let's talk about the following:
3. First, it is easy to display a line of text on the interface. You can call textout. It is better not to use drawtext, which is much less efficient than textout.
To provide color information when each line is displayed, a long enough array must be kept in the memory to maintain the color of each character. In the display, settextcolor is a character before textout. However, this is not very efficient. A good way is to re-paint words of the same color at a time to minimize the call of textout. So I added an array to save the length of each keyword.
There is a problem here. It is not possible to store such an array for each stable row, otherwise the memory space will be very large. Instead
2. When there are many keywords, we must judge each word one by one to determine whether the word is in the keyword. Therefore, the hash table is a suitable choice. I will not talk about it here.
1. Extract the word in a string and then judge whether it is a keyword Based on the word. Therefore, the string word breaking function is involved. For example, a string:
This is a test line string, haha :).
We must extract:
This
-
Is
-
A
-
Line
-
String
-
,
-
Haha
:
)
.
-Indicates space. Then match in the keyword table to determine whether the word is a keyword. If it is a keyword, modify the color information of the color array for the interface.

5. How to implement automatic line feed.
When displaying rows, we do not directly output the row data stored in the memory in textout. Instead, we need to take several steps to process the row data.
1. process the tab key (0x09). When we encounter 0x09, we must replace it with a space. Of course, no tab can be filled with different spaces at different positions, after completion, tab_len can be divisible. In this way, the string after the tab is removed.
2. Calculate the string obtained in step 1. Wrap the line automatically, save each line as cstringarray, and then display it on the interface.
3. the automatic line feed function is added, which affects the calculation of the optical mark. Therefore, when converting an interface Pixel into a cursor position, you must count the number of sublines on the current interface (the number of lines obtained after the automatic line feed ). Then you can determine the number of rows. Therefore, it is difficult to calculate.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.