April 29, 2024, 10:40:32 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


CColorEdit

Started by sapero, August 21, 2006, 01:52:57 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

August 21, 2006, 01:52:57 PM Last Edit: August 25, 2006, 02:55:24 PM by sapero
CColorEdit is (will be) a text editor with syntax coloring.
Current stage: can only display colorized text; scrolls only vertically (with mouse wheel too)

The source code contains a bit of unneeded commented out code - this is normal for 'very' alpha versions :)
I have problems with drawing tabstops using api DrawText (Ex)
- tabstops are not displayed, or a rectangle [] is drawn, or the tab is 1000 pixels to right :D

Horizontal scrolling seems to be more complicated, at least with temporary memory HDC + bitblt to screen.
This project is open, any suggestions are welcome.

Parker

Great start, that's pretty cool. I started something like that in IBasic a couple years ago but I had a bunch of problems then. I probably still would ;D

James at http://www.catch22.net/ has a project/tutorial like this you may be interested in. His goes really in depth with drawing unicode strings, but you can get whatever you need out of it. The regular expressions part of the tutorial should be here soon, since it's been a couple months since the last part.

Bruce Peaslee

Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

kryton9

What an undertaking. Looks great!!

kryton9

Running at 1440x900, I just maximized the window and noticed some strangeness. Screenshot will show it much better than me trying to explain it.
Scroll to the righ to see the strangeness.

This is going to be nice to write programs in with all the extra lines available, great project!!

Parker

That's a problem with tabs - sometimes they get displayed way over to the right. I've never used APIs like DrawText, but I would probably just expand tabs to spaces when I need to draw and use TextOut. I haven't looked at how the other open source editor components do this though.

sapero

August 24, 2006, 05:42:24 AM #6 Last Edit: August 24, 2006, 06:05:36 AM by sapero
Uploaded new version. This version can be used in your projects to display colorized text.
Whats new?
- tabstops are displayed correctly. Changed DrawText to TabbedTextOut. Details in CColorEdit::DrawLine.
- horizontal scrolling works too - every text line is first drawn to temporary DC starting at offset X = -hScrollPos, then DC is copied onto screen.
- added basic caret handling - moves only vertically.
- fixed string parsing - ''' or "\"" is correctly colorized
- text parser is now virtual, so you can implement rules for other languages than Aurora. Here is one extra virtual method for strings.
- fixed CLineToken destructor - single delete frees two linked lists.
- added basic keyboard handling: up,down moves the caret. PageUp,PageDown scrolls text, and (if MOVE_CARET_WITH_PAGE_UPDOWN defined) moves the caret. HOME, END scrolls text too.

Problems:
- CColorEdit::CalculateMaxLineWidth scans the text for longest line (in pixels) to adjust the horizontal scroll range.
First line of displayed text (CColorEdit.src) has extra long line, last character is partially visible.
I can add x extra pixels to m_MaxLineWidth, but will this be always working correctry?

ÂÃ,  ÂÃ, // hFont has been selected into HDC m_memc
ÂÃ,  ÂÃ, m_MaxLineWidth = 0;
ÂÃ,  ÂÃ, CLineToken *pLine = m_lines.GetNextLine();
ÂÃ,  ÂÃ, while (pLine)
ÂÃ,  ÂÃ, {
ÂÃ,  ÂÃ,  ÂÃ,  DWORD width = ::GetTabbedTextExtent(m_memc, pLine->m_lpText, pLine->m_TextLen, 1, &m_TabSizeInPixels) & 0xFFFF;
ÂÃ,  ÂÃ,  ÂÃ,  if (m_MaxLineWidth < width) m_MaxLineWidth = width;
ÂÃ,  ÂÃ,  ÂÃ,  pLine = pLine->GetNextLine();
ÂÃ,  ÂÃ, }


edit: Thinked ScrollDC will be better than redrawing all lines. This is incorrect!
If you see flickers while scrolling - make sure the first "if" in CColorEdit::ScrollToLine will be always executed.
The gray rectangle is done by edit.SetWindowColor + edit.SetMargins(10,10,10,10) ;D

Ionic Wind Support Team

Very similar to the editor component I wrote for IBasic.  I didn't bother with looping through all of the lines to calculate the longest, as it turned out to be very slow on the machines back then.  Instead I picked a value for horizontal extent that was large enough to cover lines up to 640 characters at a 10 pt font.

Anyway your problem with tabbed text extent can be solved by just getting the line length in characters and multipling by the largest character width of the selected font.  Usually the character X will do. 
Ionic Wind Support Team

Ionic Wind Support Team

Actually that won't work since you're not converting spaces to tabs.  Use TabbedTextExtent and add the width of an extra character.
Ionic Wind Support Team

sapero

Thanks for 'X' tipp, I know that speed has always priority. Current time for opening a 600KB asm file is same as in notepad.

Paul, do you remember the api for calculating character offset from number of pixels, and using custom tabulator?
Need this to move the caret in OnLButtonDown, and probably later in other methods.
Found a 'untechnical' way: call x-times GetTabbedTextExtent changing string lenght, until returned width will be ok.
My latest algorithm needs maximum 6 calls to this api.
It works ok for printable characters and tab, and allows to detect if the caret should be placed before or after character.

Ionic Wind Support Team

Don't know of a simple way to do it.  I looped through each character in the line, here is my PositionFromPoint (C++ code) routine for the IBasic editor.


CPoint EditView::PositionFromPoint(CPoint &point,BOOL bNonClient)
{
CPoint ptReturn = CPoint(-1,-1);
CPoint pt = point;
CRect rectClient;
GetClientRect(rectClient);
CPoint scroll = GetScrollPosition();
CSize tx,tChar;
long lLine=0,lChar=0,lLength = 0;
char *pData = NULL,*c,g;
if(rectClient.PtInRect(point) || bNonClient)
{
CDC *pDC = GetDC();
int nSave = pDC->SaveDC();
pDC->SelectObject(&m_Font);
pDC->SetMapMode(MM_TEXT);
pDC->SetTextColor(0);
tChar = pDC->GetTextExtent("X",1);
pt+=scroll;  //abs position in document;
lLine = pt.y/tChar.cy;
ptReturn.y = lLine;

pData = GetLine(lLine);
if(pData)
{
lLength = GetLineLength(lLine);
int x = 0;
for(x = 0;x <= lLength;x++)
{
c = (pData + x);
g = *c;
*c = 0;
tx = pDC->GetOutputTabbedTextExtent(pData,strlen(pData),1,&m_nTabW);
*c = g;
if((tx.cx-(tChar.cx/2)) >= (pt.x-LEFTINDENT))
break;
}
ptReturn.x = x - 1;
if(ptReturn.x < 0)
ptReturn.x = 0;
}

pDC->RestoreDC(nSave);
ReleaseDC(pDC);

}
return ptReturn;
}


It stored the current column/line in a point structure for return.  Was reasonably fast even on slow machines.

I don't use this code anymore since switching to Scintilla.  Figure why reinvent the wheel for Aurora ;).
Ionic Wind Support Team

sapero

August 25, 2006, 02:01:52 PM #11 Last Edit: August 25, 2006, 02:05:59 PM by sapero
Again reuploaded new version.
Caret movement works correctry, I can't find any bugs; maybe you find?
It follows mouse clicks and dragging. Standard keystokes up,down,right and left move the caret exact to the proper position.
I have removed margins, but one on left side is still handled - as you see on first screenshot - the editor displays line numbers.
Width of this area is adjusted automatically (can be easy disabled, the width can be fixed).

To Paul: CWindow mouse methods with x and y have a bug. If OnLButtonDown you set capture and move the mouse to left or above client area - coordinates are incorrectly converted from word to int. instead int -1 is 0x0000FFFF.
I know this is a small mistake movzx <-> movsx.
And something with window font. After minimizing/restoring the window - the m_hFont changes.
I have stored m_hFont in other variable to detect when the user calls SetFont, to recalculate some global metrics.