Thomas, good point, i overlooked the fact it was stuffed with symbol's as well :)

Originally posted by sluggy
...i'm gonna jump in here with a suggestion. If i was you, i would create a private heap for the control to use.


Thanx for the thought, but im way ahead of you here ;)

I do create and store a private heap, and its handle is stored into the 'process' heap along with all other private data for the control. THe only process specific heap entry is the 'ECon' structure (Edit Control).
_HEAP STRUC

hHEAP dd ? ; Private Heap Pointer
lSTART dd ? ; Starting Line Heap Memory object
TOTALLINES dd ? ; Total # of Heap Objects
LINEBUFFER dd ? ; Editing Heap Memory Buffer (oversized).
_HEAP ENDS

_GDI STRUC
xBRUSH dd ? ; Brush for background
xBRUSHCLR dd ? ; Background color
xBM dd ? ; Bitmap
xFONT dd ? ; Font
xDC dd ? ; Back Buffer DC
_GDI ENDS

_WIN STRUC
CONTROL dd ? ; Control Flags for editing (See NES_****)
FONTWIDTH dd ? ; Text ave char width
FONTHEIGHT dd ? ; Font Height
xHEIGHT dd ? ; Window Client Width
xWIDTH dd ? ; Window Client Height
hSB_RIGHT dd ? ; Right Scroll Bar
hSB_BOTTOM dd ? ; Bottom Scroll Bar
DRCT RECT <> ; Drawing Rectangle (DC bitmap size)
SB_RCT_R RECT <> ; Right Scroll Bar Rect
SB_RCT_B RECT <> ; Bottom Scroll Bar Rect
_WIN ENDS

_USER STRUC
CURRENTLINE dd ? ; Current Line the cursor is on
FILESIZE dd ? ; Total Number of bytes in all lines
CURRENTPOS dd ? ; Cursor Position in bytes for the start of the line
XCARET dd ? ; Device location of caret's X pos
YCARET dd ? ; Device loaction of caret's y pos
_USER ENDS

ECon STRUC
BKP _GDI <> ; GDI BACK UP
GDI _GDI <> ; GDI TOOLS NEEDED
WIN _WIN <> ; WIndow Properties
USER _USER <> ; User Properties
HEAP _HEAP <> ; Heap Memory for Edit Data
ID dd ? ; Edit ID
ECon ENDS


So on creation, i simply have this:
     invoke GetProcessHeap

invoke HeapAlloc, eax, NULL, SIZEOF ECon ; Allocate Button off this heap
mov ebx, eax

invoke SetWindowLong, _hWnd, GWL_USERDATA, eax ; Store for future use

mov edx, lParam
assume ebx :PTR ECon

; Set up Data for text input by user
mov [ebx].USER.CURRENTLINE, 1 ; Starts on line #1
.... (etc)

I havent shown it, but the HEAP.hHEAP dword is the private heap handle that stores all text data. I have a separate include specific to the heap catagory for all the memory operations needed to deal with the data. One of which is the 'Line to long' message. You get 4Kb per line. So the above like represents one 'text' line. This is why there is no ENTER yet, as im still getting the editting tweeked before i expand over multiple lines.

This project has definitely been a trial of organization tho, and i think im wining the battle :), i have tight little handlers all over to take care of various isses. I've completely abandoned Hutch's prostart template on this one, as the .if/.elseif case structures get quite long and hard to follow, so a jmp method is implemented that is visually more readable and segmented.

Anywho, it looks like NT boxes can handle the current design, so i will push forward still :)

Thanx again.
:alright:
NaN
Posted on 2002-04-30 10:09:24 by NaN
I have another stumper tho:

The above posted image is a good example of the problem. The word wraping is Ez, its a style flag in the DrawTextEx API, however, properly tracking how many lines of *screen* space get wrapped, for every one line of 'data' is becoming a problem.

This is why the carret disapears. My original design is for one continous line viewed by the scroll bar. This is why i have filtered out the ENTER key. But when wraping is turned on, i have no idea howmany lines it spans. So cursor up/down would be very wrong. As it would move up to next 'data' line & pos x, but on the screen it could be the same 'data' line, only at pos x - width. ???

Anyone have a clue what im talking about. And if so, how to track it better?

Im kinda prefering option (c) :: forget word wrap all together... Anyone actually use this feature??

:alright:
NaN
Posted on 2002-04-30 11:03:33 by NaN
hi Nan

Maybe you could implament the wordrap yourself. you could just add a max line lenghth to your control's data header. Each time the user has changed wrapping your controls starts at line zero and goese thru each line checking if any line is longer then the line wrap and if it is creating a new line with the excess so the actual lines are changed to the same as they will be displayed.
Posted on 2002-04-30 11:36:52 by Kudos
NaN,
If you're going to completely replace the edit control, I think word wrapping is a must. Personally, I use it all the time. Currently, I'm working on a static text viewer... not an editor, but it does word wrap and this is the basic strategy I take:

1) call GetTextExtentExPoint to find where you're line will break
2) trace back to the beginning of the word so you don't break in the middle of a word
3) Draw up to that word
4) Save the offsets of the chars that got drawn on that line
5) Go to the next part of the line and do the same thing until you meet a CR-LF pair

It requires the added overhead of storing what offsets the lines break at. But you're probably going to need this down the road if you want scrolling done properly. When you start getting docs that are several pages long, scrolling becomes a hassle. If you don't save this information... I think you'll have to redraw the entire document everytime WM_PAINT is called

If you are using just one font through the whole document, you can maybe write a better routine than GetTextExtentExPoint. I think you could use GetCharWidth32 to make a table of character widths and just add em up yourself.

Oh, and I would look into ExtTextOut instead of DrawText. My winAPI guide says that DrawText just gets converted to ExtTextOut anyways, so you might save yourself the trouble. However, you have to do more of the work yourself.

--Chorus
Posted on 2002-04-30 11:51:57 by chorus
ExtTextOut

This is a new API for me, non of my referenes give any mention of this :(

(( Hey f0dder, MSDN is letting me down again! :grin: ))

Thanx for you suggestion. Between your thought and Kudos, i think i have a possible solution in mind. One which will keep the line #'s right as well.

:alright:
NaN
Posted on 2002-04-30 12:04:41 by NaN
This is a new API for me, non of my referenes give any mention of this


The latest platform SDK surely does :)

According to the PSDK, DrawTextEx returns the text height in logical units. Maybe you can use that to calculate the number of lines spanned by one 'data'line?

Thomas
Posted on 2002-04-30 12:11:59 by Thomas
Thanx for the tip Thomas,

This is what im currently using. I have the drawing Rect, and I add to the .top the return value (moving the top down), and draw the next line. (while the top < bottom, the lines are displayed).

As well, i did some tests, and multiple lines return multiple*FONTHEIGHT when word wrap is on. Which makes this process smooth. But my real delema is making the 'edit' cursor line up with the 'graphical' cursor, while moving up and down. If a line wraps, moving up could only move back 40 chars on the same line. If the line doesnt, then moving up means a new line.

I think i will have to abandon the DrawTextEx as well.

Here is more missing info on the design:
HLINK STRUC

LINKSIZE dd ? ; Number Of Bytes of 'data' in the link
LINENUM dd ? ; Current Link Line Number
LINECODE dd ? ; Codes for data on this line
PREVLINK dd ? ; Previous Line Link
NEXTLINK dd ? ; Next Line Link
DATA dd ? ; Data Starts for the line (USE ONLY WITH LEA!!)
HLINK ENDS


Every line has this header. (Data is only used to get the pointer of the start of data). I have a LINECODE structure taht currently has only 1 of the 32 available bits used for a Modified bit. Which tells the program to 'replace the link that was modified', if not, the buffer move on. If i set a bit stating the line has wrapped, then i can use this bit when moving into other lines, and as suggested, a global variable stating the # of chars per line will allow me to calculate 'where' im moving to.

:alright:
NaN
Posted on 2002-04-30 12:27:01 by NaN
NaN, you can also get the height of one line of text from GetTextExtentExPoint, or from GetTextMetrics. I think DrawText just calls these to get the appropriate info... can't be sure though. If you're going to be doing the word wrapping by hand, use the former method since you're gonna call it anyways.

--Chorus
Posted on 2002-04-30 12:37:06 by chorus
I also found a good strategy for the drawing rectagle is to keep a ClientRectangle and a DocumentRectangle. This comes in hand when scrolling down. The client rectangle is always (0,0),(xmax,ymax). If I've scrolled down say, 100 pixels I set DocumentRectangle.top = -100 and DocumentRectangle.bottom = top+FontHeight.
Everytime you draw a new line of text, set DocRect.top = DocRect.bottom and DocRect.bottom =+ FontHeight. If DocRect.bottom <0 the line isn't visible. Furthermore, stop drawing once DocumentRectangle.top > ClientRectangle.bottom as you've been doing.

When you scroll, it's as simple as setting a new initial value for DocumentRectangle.top

This info can also be sent to SetScrollInfo to fix up your scroll bars when you scroll down or up.

--Chorus
Posted on 2002-04-30 12:44:49 by chorus
Thanx again chorus. I have something simular in mind. I only *just* placed the scroll bars, so there is no code to make them active (obvioulsy). I also plan to do it by hand, and i do already have the FONTWIDTH and FONTHEIGHT fields filled by GetTextMetrics so i might as well try the ExtTextOut, as discussed earlier. I have alot to do today :) If i make any significant progress i will re-post the next "segment" seeing you interested :)

Thanx again for you helpful thoughts..
:alright:
NaN
Posted on 2002-04-30 17:48:04 by NaN
Well, i can say that the simple things you take for granted, like just *how* you cursor around left and right in an edit window, are not to be thought as 'simple'. I was surprised how long it took to get it right. Everytime you get one type of operation right, another goes out. :rolleyes:. But i got it all figured out now and streamlined. And it looks quite good so far.

    I currently have:
    [*]Single line editor at the moment (Word Wrap not implemented yet).
    [*]Left/Right cursor keys working. For all 3 'modes' (visible, outside left, or outside right)
    [*]Horizantal Scroll Bar. Repositions with keyboard inputs (cursor, home, end). As well as various mouse selections (left/right/track/page left/page right).
    [*]End key works.
    [*]Home key works, with two modes. Toggle between First position in line, and first character if spaces are found at the begining, or simply move to home postion if first character is NOT a space.
    [*]Fonts should be working with text resizes.
    [*]Caret is working properly.


    Like I said... the 'simple' things... :rolleyes:. I havent implemented any 'shift' HOME/END CURSORS yet, as im going to wait until i get onto multiple lines, and all the tweeking with its cursor movements.

    Check it out so far.. Lemme know if you find a problem i missed in its behavior. Its already getting complex, so it gets easier to 'hide' bugs ;) (( But i think i got all of em so far )

    EDIT: Attachment removed to save space.. See latest Post

    Thanx alot!
    :alright:
    NaN
Posted on 2002-05-01 22:07:24 by NaN
BTW: I was thinking of adding a Status Bar on the bottom of the control. Dunno if i should.

Upside is i save all the message passing out of the control, and keep it working 'tighter'.

Downside, you get less control over the status bar, as it would be handled by the Edit Control. As well, if the control is used as a fraction of the client area, ther status bar would be attached to the bottom of where ever the control is placed.

Whats your thoughts??

:NaN:
Posted on 2002-05-01 22:27:13 by NaN
NaN can you lock in the color and the font with an .ini file.
Also when i go back to previous text with the cursor it don't do it. I have to use the key strokes to go backwards... Win95

Also it only type on one line only...enter do not work to go to next line.
Posted on 2002-05-01 22:42:48 by cmax
I guess I just have one thought but its a little off topic I suppose.

I do like coding new controls, matter of fact I do it all the time heh :) but what I was really wondering was why you are coding a replacement? I have not seen anything (unless I midded something) that your control does that the regular one does not. Except for maybe the segmented memory model...

If its just for the learning experence then ive been there and done that lol :tongue:
Posted on 2002-05-01 22:45:23 by Graebel

NaN can you lock in the color and the font with an .ini file.
Also when i go back to previous text with the cursor it don't do it. I have to use the key strokes to go backwards... Win95

Also it only type on one line only...enter do not work to go to next line.
Key strokes *is* the cursor? Im confused here.. Do you mean with the mouse? Cause i have no mouse suport implemented yet.. Just what i have listed.. :confused:


I have not seen anything (unless I midded something) that your control does that the regular one does not. Except for maybe the segmented memory model...

If its just for the learning experence then ive been there and done that lol
Im doing it partly cause i like *harder* projects to invest my time into, but this is hardly the final version, nor is it the intended 'editor'.

The control is a separate entity from the window im presenting it in. Im not wasting my time with how well it acts as an IDE, but rather an EZ to use edit control, with alot of features that are normally a Pain to do in rich edit. As well, hopefully it will be a hell of alot faster than richedit.

I havent even 'caught up' to typical editors, so there is no *features* yet, but they will definitly be coming. :grin: (i have an entire .txt file of ideas i've been having over the last year, so i wont be done in the comming month, but i hope to get the 'basics' pounded out first, so i can have some ground to stand on when i *do* add my extra ideas.)

When its all done, It will be a small leap to an IDE for my object creator with an insane amount of control over how code is displayed, edited, and compiled :grin: (Basically a Full object orientated ASM IDE). This is why i wanted "segmented" memory for the data. As well, im a 100% fan of Ultra Edit, so im modelling most of its basic behaviors after their custom control. ;)

:alright:
NaN
Posted on 2002-05-01 23:12:01 by NaN
NaN, I tried your updated control and it's looking great! There are a couple of things I think that could be fixed up though...

1) It doesn't detect my spelling mistakes
2) It doesn't translate Japanese to English
3) I tried Ctrl-O (Order Pizza) and it never even asked me what toppings I wanted

:grin:

hehe... but seriously... I think a really cool idea would be the ability to have an application define a pre-processing function. ex., if someone actually wants to use a spellchecker with your edit control, they can write up a routine and your control can call it before before screen drawing takes place.

That's the only thing I would really want that I don't believe is offered by any alternatives...

--Chorus
Posted on 2002-05-01 23:38:27 by chorus
Are you getting at a scripting engin or something??

:NaN:
Posted on 2002-05-02 07:13:43 by NaN
No... I'm getting at an edit control with some very nice cusomizability.

Ex.
-Spell Checking
-Highlighting hyperlinks (sorta like outlook would in an email)
-Variable parsing (like wsprintf)
-Full text justification (instead of regular old left-justified)
-Parsing and censoring bad words
-Generating opcodes from asm source

Now, I'm not suggesting you program this stuff yourself... but that there's a backdoor for a callback procedure. Ex., the Edit Control as it stands allows the user to define their own word wrapping procedure. You could generalize this to a generic pre-processing feature. If somebody wanted to go to the extra lengths of making these features, they can. If not, then you've just got a regular edit control.

I imagine you would have to implement it like so:
1) initialize a pointer to NULL using the Window extra data space
2) accept a wm_command that changes a pointer to the user callback
3) everytime you process a wm_paint, at the beginning of drawing (each line...?) check the pointer. If it's NULL, just go on with the proc. Else call it.

You might want to have the call back function return a pointer to a new block of text. Say the function replaces every occurance of the f-word with f*** but you don't want to destroy the original. The function could allocate a temporary block of data that copies the original string and edits it as it wants. Then your wm_paint would draw *that* instead of the regular text.

Or suppose someone is using your edit control for a chat client. They could write a simple proc that would check text for user names to be ignored and return a NULL pointer (to be interpreted as "don't draw the line cause I'm not interested in it")

Anyways... I'm rambling. But that's pretty much what I was getting it

--Chorus
Posted on 2002-05-02 07:52:36 by chorus
Ahhh i see.. much more clear this time around... and a very good suggestion. I've made note of it in my txt file. I will see what i can work in..

Again, this will be a while from now. I only just got line returns working.. (took me all night to get the linked list tweeked and bug free)...

It took me 7 hrs to put the framework together... but actaully implementing the 'behaviors' has been teeth pulling to get right.. (real learning curve i have to say). Im only hoping once all the basics are finished, the bigger idea's will be more straight forward to code.

At any rate, i *will* get it done. If you have more sugestion that come to you, please let me know...

Thanx again!
:NaN:
Posted on 2002-05-02 08:52:02 by NaN
Ahh I see, a worthy project indeed.

Hmm, I am currently using a RichEdit and I have not noticed any slow downs at all. And my home machines a poor under powered 233mhz :P

Although I *will* grant you that doing some things are like pulling teeth with this thing...
Posted on 2002-05-02 09:06:44 by Graebel