module edit #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import gui from gui_win32.ala #!!!!!!!!!!!!!!!!!!!!!!!!!
#Edit classes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class EditOp
opCode=0
str letter
all variable
row=0 #cursor row before op
col=0
firstVisibleRow=0
selRow=0
selCol=0
auxCol=0
auxRow=0
#all undoOp
class Edit
Control control
StrTable text
cursorRow=0
cursorCol=0
firstVisibleRow=0
viewX=0
lineH=20
leftMargin=10
tabLength=64#8*8 72 #8*9
font=0
selLastRow=-1;selEndCol=-1 #end included in selection
horScrollRange=0
Fifo undo
Fifo redo
File file
hdc=0
cursorH=0
shiftPressed=0
ctrlPressed=0
mouseLBD=0
#Edit classes end ==============================================================
#Edit consts ++++++++++++++++++++++++++++++
const EDIT_UPPER_MARGIN 10
const EDIT_STATE_APPEND 0
const EDIT_STATE_INSERT 1
const EDIT_OP_INSERT_CHAR 1
const EDIT_OP_DELETE_CHAR 2
const EDIT_OP_DELETE_CHAR_1 3
const EDIT_OP_INSERT_PARAGRAPH 4
const EDIT_OP_DELETE_PARAGRAPH 5
const EDIT_OP_DELETE_PARAGRAPH_1 6
const EDIT_OP_DELETE_SELECTION 7
const EDIT_OP_INSERT_TEXT 8
const EDIT_OP_INSERT_LINES 9
#Edit consts end =================================================
#Edit start ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Edit Edit(int x,int y, int w, int h,int font,Window parent)= #*********************************
null=0; Edit edit;style=0
style=setBit(style,0) #has hor scroll
style=setBit(style,1) #has ver scroll
edit.control=Control(x,y,w,h,style,"",parent.id)
edit.text=StrTable() #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$if os mswindows #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
bind edit.control,WM_PAINT,eventDraw(edit)#draw(edit)
bind edit.control, WM_KEYDOWN, keyPressedWin32(edit,systemEvent)
bind edit.control, WM_KEYUP, keyUpWin32(edit,systemEvent)
bind edit.control, MOUSE_LBD, mouseLBD(edit, systemEvent)
bind edit.control, MOUSE_LBU, mouseLBU(edit, systemEvent)
bind edit.control, MOUSE_MOVE, mouseMove(edit, systemEvent)
bind edit.control, WM_VSCROLL, verScroll(edit, systemEvent)
bind edit.control, WM_HSCROLL, horScroll(edit, systemEvent)
edit.undo=Fifo(100)
edit.redo=Fifo(100)
client_rect=getClientRect(edit.control)
edit.horScrollRange=client_rect.w+client_rect.w/2
edit.cursorH=edit.lineH-3
edit.font=font
edit.hdc=getDC(edit.control.id)
call gdi32.SelectObject(edit.hdc,edit.font)
return edit
proc destructor(Edit edit)
releaseDC(edit.control.id,edit.hdc)
proc setVerScrollRange(Edit edit)
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)
proc eventDraw(Edit edit)=
PAINTSTRUCT ps; hdc=0
oldHdc=edit.hdc
call user32.BeginPaint(edit.control.id,ps); mov hdc,eax
edit.hdc=hdc
call gdi32.SelectObject(hdc,edit.font)
draw(edit)
call user32.EndPaint(edit.control.id,ps)
edit.hdc=oldHdc
proc draw(Edit edit)=#*******************************************
text_rect=getClientRect(edit.control)
drawText(edit,text_rect) #!!!!!!!!!!!!!!!!!
proc drawText(Edit edit, Rect rect)= #*************************************************
text="";c=""
#draw background
color=WHITE
drawRect(edit.hdc,rect,color)
lineIndex=edit.firstVisibleRow
cliRe=getClientRect(edit.control)
viewH=edit.lineH;y0t=cliRe.y+1
lenT=len(edit.text)
controlViewH=cliRe.h#!!!!!!!!!!
et1:#-------------------------
if lineIndex < lenT and viewH < controlViewH
withBackground=0
drawTextLine(edit,lineIndex,withBackground,rect) #!!!!!!!!!!!!
viewH=viewH+edit.lineH
lineIndex=lineIndex+1
goto et1#-------------------------
int tabPosition(Edit edit, int x)=
res=0
x_ala=x+edit.viewX
tab_no=(x_ala-edit.leftMargin)/edit.tabLength+1
res=tab_no*edit.tabLength +edit.leftMargin-edit.viewX
return res
int drawStr(Edit edit,str text,int x ,int y,int color, Rect inRect)=
xt=x
le_text=len(text);to_draw=""
drawRect=Rect(x,y,MAX_RES_X,MAX_RES_Y)
for ind=0 to le_text-1
char_to_draw=text[ind]
if ord(char_to_draw)=9 # tab code
if to_draw
drawRectHere=andRects(drawRect,inRect)
xt=drawCharA(edit.hdc,drawRectHere,char_to_draw,color)
to_draw=""
xt=tabPosition(edit,xt)
else
to_draw=to_draw+char_to_draw
if to_draw
drawRectHere=andRects(drawRect,inRect)
xt=drawStrA(edit.hdc,drawRectHere,to_draw,color)
return xt
int findTextEnd(Edit edit,str text,int x )=
xt=x
le_text=len(text);to_draw=""
for ind=0 to le_text-1
char_to_draw=text[ind]
if ord(char_to_draw)=9 # tab code
if to_draw
xt=xt+getTextWidth(edit.hdc,to_draw)
to_draw=""
xt=tabPosition(edit,xt)
else
to_draw=to_draw+char_to_draw
if to_draw
xt=xt+getTextWidth(edit.hdc,to_draw)
return xt
int drawStr(Edit edit,str text, int x, int y,int color,int backColor,int backDY,int backH,Rect rect)=
textWidth=findTextEnd(edit,text,x)-x
yBack=y-backDY
drawRect=Rect(x,yBack,textWidth,backH)
drawRect=andRects(drawRect,rect)
drawRect(edit.hdc,drawRect,backColor)
xt=drawStr(edit,text,x , y,color, rect)
return xt
proc drawTextLine(Edit edit,int lineIndex)=#***********************************************************
re=getClientRect(edit.control);withBackground=1
drawTextLine(edit,lineIndex,withBackground,re)
proc drawTextLine(Edit edit,int lineIndex,int withBackground,Rect inRect)= #***********************************
auxText="";c="";textSel=""
setBkMode(edit.hdc,TRANSPARENT) #mode TRANSPARENT when old background is left and OPAQUE
lineOff=lineIndex-edit.firstVisibleRow #!!!!!!!!!
if lineOff >=0
re=getClientRect(edit.control)
xt=re.x+edit.leftMargin-edit.viewX
y0=re.y#!!!!!!!!
yr=y0+lineOff*edit.lineH+EDIT_UPPER_MARGIN
re.y=yr;re.h=edit.lineH#!!!!!!!!!!!!
yre=yr+edit.lineH;yt=yr #!!!!!!!!!!!!!
yEnd=re.y+re.h
if yre<=yEnd
re.y=yr;re.h=edit.lineH
if withBackground
#draw background
color=WHITE
drawRect=andRects(re,inRect)
drawRect(edit.hdc,drawRect,color)
textLine=edit.text[lineIndex]#!!!!!!!!!!!!!!
color=BLACK
no_selection=1
if edit.selLastRow >=0
if edit.selLastRow = edit.cursorRow
if lineIndex=edit.cursorRow :no_selection=0
elif edit.selLastRow > edit.cursorRow
if lineIndex >= edit.cursorRow and lineIndex <= edit.selLastRow : no_selection=0
else
if lineIndex >= edit.selLastRow and lineIndex <= edit.cursorRow : no_selection=0
if no_selection # so selection
if lineIndex=edit.cursorRow #with cursor
le=len(textLine)
cursorY=yt #+2
if edit.cursorCol>=le #cursor at the end of line
xs=drawStr(edit,textLine.s,xt , yt,color, inRect)#!!!!!!!!!!!!!!!!
xs=xs+1;drawCursor(edit.hdc,xs,cursorY,edit.cursorH,inRect) #draw cursor !!!!!!!!!!!!!!!!!!
xt=xs
else
if edit.cursorCol >0
auxText=textLine[0:edit.cursorCol]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#!!!!!!!!!!!!!!!!
if xt !=AFTER_RECT
cursorX=xt
auxText=textLine[edit.cursorCol:]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#!!!!!!!!!!!!!!!!
drawCursor(edit.hdc,cursorX,cursorY,edit.cursorH,inRect) #draw cursor !!!!!!!!!!!!!!!!!!
else
xt=drawStr(edit,textLine.s,xt , yt,color,inRect)
else # with selection++++++++++++++++++++++++++++++++++
if edit.selLastRow = edit.cursorRow
selBeginRow=edit.cursorRow
selLastRow=selBeginRow
if edit.selEndCol > edit.cursorCol
selBeginCol=edit.cursorCol;selEndCol=edit.selEndCol
else
selBeginCol=edit.selEndCol;selEndCol=edit.cursorCol
elif edit.selLastRow >edit.cursorRow
selBeginRow=edit.cursorRow;selBeginCol=edit.cursorCol
selLastRow=edit.selLastRow;selEndCol=edit.selEndCol
else
selBeginRow=edit.selLastRow;selBeginCol=edit.selEndCol
selLastRow=edit.cursorRow;selEndCol=edit.cursorCol
colorSel=WHITE;selBackColor=BLUE
ySelDelta=3;hSel=edit.lineH#!!!!!!!!!!!!
if lineIndex=selBeginRow and lineIndex=selLastRow
auxText=textLine[0:selBeginCol]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#draw not selected!!!!!!!!!!!!!!!!
if xt !=AFTER_RECT
auxText=textLine[selBeginCol:selEndCol]
xt=drawStr(edit,auxText,xt , yt,colorSel, selBackColor,ySelDelta,hSel,inRect)#draw selected!!!!!!!!!!!!!!!!
if xt !=AFTER_RECT
auxText=textLine[selEndCol:]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#draw not selected!!!!!!!!!!!!!!!!
elif lineIndex=selBeginRow
auxText=textLine[0:selBeginCol]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#draw not selected!!!!!!!!!!!!!!!!
if xt !=AFTER_RECT
auxText=textLine[selBeginCol:]
xt=drawStr(edit,auxText,xt , yt,colorSel, selBackColor,ySelDelta,hSel,inRect)#draw selected!!!!!!!!!!!!!!!!
elif lineIndex=selLastRow
#endSelCol=edit.cursorCol+1
auxText=textLine[:selEndCol]
xt=drawStr(edit,auxText,xt , yt,colorSel, selBackColor,ySelDelta,hSel,inRect)#draw selected!!!!!!!!!!!!!!!!
if xt !=AFTER_RECT
auxText=textLine[selEndCol:]
xt=drawStr(edit,auxText,xt , yt,color, inRect)#draw not selected!!!!!!!!!!!!!!!!
else
xt=drawStr(edit,textLine.s,xt , yt,colorSel, selBackColor,ySelDelta,hSel,inRect)#draw selected!!!!!!!!!
end:#===========
proc clearTextLine(Edit edit,int lineIndex)= #***********************************
re=getClientRect(edit.control)
auxText="";c="";textSel=""
lineOff=lineIndex-edit.firstVisibleRow #!!!!!!!!!
if lineOff >=0
re=getClientRect(edit.control)
xt=re.x+edit.leftMargin-edit.viewX
y0=re.y#!!!!!!!!
yr=y0+lineOff*edit.lineH+EDIT_UPPER_MARGIN
re.y=yr;re.h=edit.lineH#!!!!!!!!!!!!
yre=yr+edit.lineH;yt=yre#-3 #!!!!!!!!!!!!!
yEnd=re.y+re.h
if yre<=yEnd
re.y=yr;re.h=edit.lineH
#draw background
color=WHITE
drawRect(edit.control.parentId,re,color)
#------------------------------------------------------------
proc writeUndo(Edit edit,int opCode,str key)=#****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.letter=key; append(edit.undo,edit_op)
proc writeUndo(Edit edit,int opCode,int var )=#*****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.variable=var; append(edit.undo,edit_op)
proc writeUndo(Edit edit,int opCode,list var,int row, int col)=#*****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.selRow=edit.selLastRow; edit_op.selCol=edit.selEndCol
edit_op.variable=var; edit_op.auxRow=row; edit_op.auxCol=col;append(edit.undo,edit_op)
proc writeUndo(Edit edit,int opCode,int row, int col)=#*****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.selRow=edit.selLastRow; edit_op.selCol=edit.selEndCol
edit_op.auxRow=row; edit_op.auxCol=col;append(edit.undo,edit_op)
#---------------------------------------------------------
proc keyPressed(Edit edit, int keyCode)= #**********************************
key=chr(keyCode)
writeUndo(edit,EDIT_OP_INSERT_CHAR,key) #!!!!!!!!!!!!!
text=""
leET=len(edit.text)
if leET=0
new=append(edit.text,key)
edit.cursorCol=1
elif edit.cursorRow= 65 and keyCode <= 90 #letter from A to Z
if edit.shiftPressed=0 :keyCode=keyCode+32 # change A -> a
et1:#--------------------------
key=chr(keyCode)
writeUndo(edit,EDIT_OP_INSERT_CHAR,key) #!!!!!!!!!!!!!
text=""
leET=len(edit.text)
if leET=0
new=append(edit.text,key)
edit.cursorCol=1
elif edit.cursorRow=48 and keyCode <=57 # 0 to 9
if edit.shiftPressed
if keyCode=48 :keyPressed=33
elif keyCode=49:keyPressed=64
elif keyCode=50:keyPressed=35
elif keyCode=51:keyPressed=36
elif keyCode=52:keyPressed=37
elif keyCode=53:keyPressed=94
elif keyCode=54:keyPressed=38
elif keyCode=55:keyPressed=42
elif keyCode=56:keyPressed=40
elif keyCode=57:keyPressed=41
goto et1#------------------------
elif keyCode=219
if edit.shiftPressed: keyCode=123
else: keyCode=91
goto et1#--------------------
elif keyCode=221
if edit.shiftPressed: keyCode=125
else: keyCode=93
goto et1#--------------------
elif keyCode=222
if edit.shiftPressed: keyCode=34
else: keyCode=39
goto et1#--------------------
elif keyCode=186
if edit.shiftPressed: keyCode=58
else: keyCode=59
goto et1#--------------------
elif keyCode=220
if edit.shiftPressed: keyCode=124
else: keyCode=92
goto et1#--------------------
elif keyCode=188
if edit.shiftPressed: keyCode=60
else: keyCode=44
goto et1#--------------------
elif keyCode=191
if edit.shiftPressed: keyCode=63
else: keyCode=47
goto et1#--------------------
elif keyCode=190
if edit.shiftPressed: keyCode=62
else: keyCode=46
goto et1#--------------------
elif keyCode=192
if edit.shiftPressed: keyCode=126
else: keyCode=39
goto et1#--------------------
elif keyCode=189
if edit.shiftPressed: keyCode=95
else: keyCode=45
goto et1#--------------------
elif keyCode=187
if edit.shiftPressed: keyCode=43
else: keyCode=61
goto et1#--------------------
elif keyCode >= 32 and keyCode <127 #ascii char
goto et1#-----------------------------
proc keyUpWin32(Edit edit, Event event)= #**********************************
keyCode=event.wParam
if keyCode=KEY_SHIFT: edit.shiftPressed=0
elif keyCode=KEY_CTRL: edit.ctrlPressed=0
proc keyEnter(Edit edit)= #******************************************************
writeUndo(edit,EDIT_OP_INSERT_PARAGRAPH,"") #!!!!!!!!!!!!!
Rect move_rect
cursor_row=edit.cursorRow; new_cursor_row=cursor_row+1
text1="";scroll=0
lines=len(edit.text); last_row=lines-1
text=edit.text[cursor_row]
le=len(text)
client_rect=getClientRect(edit.control)
if edit.cursorCol >=le-1 #last char
if edit.cursorRow >=lines-1 #last line
ns=append(edit.text,text1)
else
insert(edit.text,new_cursor_row,text1)
else
curr_line=edit.text[cursor_row]
text1=curr_line.s[0:edit.cursorCol]
text2=curr_line.s[edit.cursorCol:]
curr_line.s=text1
if cursor_row < last_row
insert(edit.text,new_cursor_row,text2)
else
ns=append(edit.text,text2)
view_lines=client_rect.h/edit.lineH
last_visible=edit.firstVisibleRow+view_lines-1
if cursor_row =last_row or cursor_row=last_visible#last row
if cursor_row+1>last_visible
edit.firstVisibleRow=edit.firstVisibleRow+1
x=client_rect.x;y=client_rect.y
setXYWH(move_rect,x,y+edit.lineH,client_rect.w,(view_lines-2)*edit.lineH)
moveRect(edit.hdc,x,y,move_rect)
edit.cursorCol=0
edit.cursorRow=edit.cursorRow+1
drawTextLine(edit,cursor_row)#draw old without cursor
drawTextLine(edit,edit.cursorRow)#draw new with cursor
else # not last row
curr_off=cursor_row-edit.firstVisibleRow
x=client_rect.x; y=client_rect.y+(curr_off+1)*edit.lineH
if lines< view_lines
h=(lines-curr_off-1)*edit.lineH
else
h=(view_lines-curr_off-2)*edit.lineH
setXYWH(move_rect,x,y,client_rect.w,h)
moveRect(edit.hdc,x,y+edit.lineH,move_rect)
edit.cursorCol=0
edit.cursorRow=edit.cursorRow+1
drawTextLine(edit,cursor_row)#draw old without cursor
drawTextLine(edit,edit.cursorRow)#draw new with cursor
drawControl(edit.control)
proc keyBackspace(Edit edit)= #***********************************
if edit.cursorCol>0
#delete char
text=edit.text[edit.cursorRow]
deleted=text.s[edit.cursorCol-1]
writeUndo(edit,EDIT_OP_DELETE_CHAR,deleted) #!!!!!!!!!!!!!
delete(text.s,edit.cursorCol-1)
edit.cursorCol=edit.cursorCol-1
drawTextLine(edit,edit.cursorRow)
elif edit.cursorRow >0
old_cursor_row=edit.cursorRow
deleted_line=edit.text[edit.cursorRow]
delete(edit.text,old_cursor_row)
new_cursor_row=edit.cursorRow-1
line=edit.text[new_cursor_row]
new_col=len(line.s)
writeUndo(edit,EDIT_OP_DELETE_PARAGRAPH,new_col) #!!!!!!!!!!!!!
if len(deleted_line.s) >0
line.s=line.s+deleted_line.s
edit.cursorRow=new_cursor_row
edit.cursorCol=new_col
if old_cursor_row > edit.firstVisibleRow
moveUp(edit,edit.cursorRow+2)
drawTextLine(edit,edit.cursorRow) #draw new with cursor
drawControl(edit.control)
proc keyDelete(Edit edit)= #**************************
if edit.selLastRow=-1 # no selection
text=edit.text[edit.cursorRow]
le=len(text)
if le >0
if edit.cursorCol0
move_rect.x=client_rect.x;move_rect.w=client_rect.w
move_rect.y=client_rect.y+offset*lineH
move_rect.h=row_count*lineH
new_y=move_rect.y-lineH
moveRect(edit.hdc,client_rect.x,new_y,move_rect)
last_visible=edit.firstVisibleRow+visible_lines-1
if visible_lines=view_lines
drawTextLine(edit,last_visible)
else
new_y=client_rect.y+(last_visible+1)*lineH
drawRect(edit.control.parentId,client_rect.x,new_y,client_rect.w,lineH,WHITE) #clear last row
proc clearSelection(Edit edit)=
if edit.selLastRow >= edit.cursorRow
start=edit.cursorRow; end=edit.selLastRow
else
start=edit.selLastRow; end=edit.cursorRow
edit.selLastRow=-1;edit.selEndCol=-1
for ind=start to end
drawTextLine(edit,ind)
proc keyArrowLeft(Edit edit)=
if edit.cursorCol>0
edit.cursorCol=edit.cursorCol-1;drawTextLine(edit,edit.cursorRow)
clearSelection(edit)
drawControl(edit.control)
proc keyArrowRight(Edit edit)=
text=edit.text[edit.cursorRow]
le=len(text)
if edit.cursorCol0
changeCursorRow(edit,-1) #!!!!!!!!!!!!!!
if edit.cursorRow0 #!!!!!!!!!!!!
scrollLineUp(edit,1,0)#!!!!!!!!!!!!!!!!!!
drawTextLine(edit,edit.firstVisibleRow)#draw first!!!!!!!!
proc scrollLineUp(Edit edit, int skip_rows_count, int first_row)= #move down
Rect move_rect;delta=0
if first_row
delta=edit.lineH*first_row;delta_ala=delta
else:delta_ala=edit.lineH
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
visible_lines=min(lines-edit.firstVisibleRow,view_lines)
move_rect.x=client_rect.x;move_rect.w=client_rect.w
move_rect.y=client_rect.y+delta
if visible_lines > skip_rows_count
move_rect.h=(visible_lines-skip_rows_count)*edit.lineH
new_y=move_rect.y+delta_ala
moveRect(edit.hdc,client_rect.x,new_y,move_rect)
edit.firstVisibleRow=edit.firstVisibleRow-1 #!!!!!!!!!!
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)#!!!!!!!!!!!!!!!
proc keyArrowDown(Edit edit)=
oldcursorRow=edit.cursorRow#!!!!!!!!!
leText=len(edit.text)
if edit.cursorRowlast_line
scrollLineDown(edit,client_rect,view_lines-2)#!!!!!!!!!!!!!!!!!!
drawTextLine(edit,oldcursorRow)#!!!!!!!!
drawTextLine(edit,edit.cursorRow)#!!!!!!!!
updateVerScroll(edit.firstVisibleRow,view_lines,leText,edit.control)
clearSelection(edit)
proc verScrollLineDown(Edit edit,Event event)=
lines=len(edit.text)
client_rect=getClientRect(edit.control)
viewLines=client_rect.h/edit.lineH
if viewLines < lines and edit.firstVisibleRow < lines-viewLines #!!!!!!!!!!!!
scrollLineDown(edit,client_rect,viewLines-1)#!!!!!!!!!!!!!!!!!!
drawTextLine(edit,edit.firstVisibleRow+viewLines-1)#draw last!!!!!!!!
updateVerScroll(edit.firstVisibleRow,viewLines,lines,edit.control)
proc scrollLineDown(Edit edit, Rect client_rect,int row_count)= #move up
Rect move_rect
if row_count >0
move_rect.x=client_rect.x;move_rect.w=client_rect.w
move_rect.y=client_rect.y+edit.lineH
move_rect.h=row_count*edit.lineH
new_y=client_rect.y
moveRect(edit.hdc,client_rect.x,new_y,move_rect)
edit.firstVisibleRow=edit.firstVisibleRow+1
proc verScrollMove(Edit edit,Event event)=
Rect move_rect
button_pos=hiWord(event.wParam)
#---------------------------
SCROLLINFO si
si.cbSize=28
si.fMask=SIF_RANGE #SIF_POS SIF_PAGE
call user32.GetScrollInfo (edit.control.id, SB_VERT, si)
scroll_range= si.nMax+1 #nPos, nPage
#----------------------------
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
if button_pos >=0 and button_pos<=scroll_range
first_visible=button_pos
if first_visible > edit.firstVisibleRow # scroll down
delta=first_visible-edit.firstVisibleRow
if delta =lines
new_first=lines-view_lines
edit.firstVisibleRow=new_first#!!!!!!!!!!!!!!!
edit.cursorRow=new_first+offset
adjustCursorCol(edit)
drawText(edit,client_rect)#!!!!!!!!!!!!!!!!!!
clearSelection(edit)
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)
drawControl(edit.control)
proc verScrollPageDown(Edit edit)=
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
new_first=edit.firstVisibleRow + view_lines-1
new_last=new_first+view_lines-1
if new_last >=lines
new_first=lines-view_lines
edit.firstVisibleRow=new_first#!!!!!!!!!!!!!!!
drawText(edit,client_rect)#!!!!!!!!!!!!!!!!!!
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)
proc keyPageUp(Edit edit)=
offset=edit.cursorRow-edit.firstVisibleRow
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
new_first=edit.firstVisibleRow - view_lines+1
if new_first <0:new_first=0
edit.firstVisibleRow=new_first#!!!!!!!!!!!!!!!
edit.cursorRow=new_first+offset
adjustCursorCol(edit)
drawText(edit,client_rect)#!!!!!!!!!!!!!!!!!!
clearSelection(edit)
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)
drawControl(edit.control)
proc verScrollPageUp(Edit edit)=
lines=len(edit.text)
client_rect=getClientRect(edit.control)
view_lines=client_rect.h/edit.lineH
new_first=edit.firstVisibleRow - view_lines+1
if new_first <0:new_first=0
edit.firstVisibleRow=new_first#!!!!!!!!!!!!!!!
drawText(edit,client_rect)#!!!!!!!!!!!!!!!!!!
updateVerScroll(edit.firstVisibleRow,view_lines,lines,edit.control)
proc changeCursorRow(Edit edit, int incr)=
edit.cursorRow=edit.cursorRow+incr #!!!!!!!!!!!!!!!!!!!!!!!!!
Str curLine
curLine=edit.text[edit.cursorRow]
leLine=len(curLine)
if edit.cursorCol>=leLine
edit.cursorCol=leLine#-1
proc adjustCursorCol(Edit edit)=#**********************************************
Str curLine
curLine=edit.text[edit.cursorRow]
leLine=len(curLine)
if edit.cursorCol>=leLine
edit.cursorCol=leLine#-1
list mouseXYToColLine(Edit edit, int mouseX,int mouseY)=
ol=[]
Str line;char sign
cliRe=getAbsClientRect(edit.control)
xt=cliRe.x+edit.leftMargin-edit.viewX
lineNo=(mouseY-cliRe.y)/edit.lineH
dx=mouseX-xt
line=edit.text[lineNo]
le=len(line)
width=0
for k=0 to le-1
sign=line[k]
charW=getCharWidth(edit.hdc,sign)
width=width+charW
if width >= dx
goto end#=============
end:#=============
append(ol,k);append(ol,lineNo)
return ol
#---------------------------------------------------------------------
proc writeRedo(Edit edit,int opCode,str key)=#****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.letter=key
append(edit.redo,edit_op)
proc writeRedo(Edit edit,int opCode)=#****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.selRow=edit.selLastRow; edit_op.selCol=edit.selEndCol
append(edit.redo,edit_op)
proc writeRedoVar(Edit edit,int opCode, str var)=#****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.selRow=edit.selLastRow; edit_op.selCol=edit.selEndCol
edit_op.variable=var
append(edit.redo,edit_op)
proc writeRedo(Edit edit,int opCode, list var)=#****************************************************
EditOp edit_op; edit_op.opCode=opCode
edit_op.row=edit.cursorRow;edit_op.col=edit.cursorCol;edit_op.firstVisibleRow=edit.firstVisibleRow
edit_op.selRow=edit.selLastRow; edit_op.selCol=edit.selEndCol
edit_op.variable=var
append(edit.redo,edit_op)
proc undoLastOP(Edit edit)=
Str line;text_ala=""; text2=""; new_text="";selection_lines=[]
edit_op=popEditOp(edit.undo);new_col=0
if edit_op.opCode
edit.cursorRow=edit_op.row; edit.cursorCol=edit_op.col;edit.firstVisibleRow=edit_op.firstVisibleRow
if edit_op.opCode=EDIT_OP_INSERT_CHAR
line=edit.text[edit_op.row]
text_ala=line.s[edit_op.col]
delete(line.s,edit_op.col)
writeRedo(edit,edit_op.opCode,text_ala)
elif edit_op.opCode=EDIT_OP_DELETE_CHAR
delete_char: #----------------------
line=edit.text[edit_op.row]
insert(line.s,edit_op.col,edit_op.letter)
writeRedo(edit,edit_op.opCode)
elif edit_op.opCode=EDIT_OP_DELETE_CHAR_1
goto delete_char #----------------------
elif edit_op.opCode=EDIT_OP_INSERT_PARAGRAPH
line=edit.text[edit_op.row]; next_row=edit_op.row+1; next=edit.text[next_row]
line.s=line.s+next.s
delete(edit.text,next_row)
writeRedo(edit,edit_op.opCode)
elif edit_op.opCode=EDIT_OP_DELETE_PARAGRAPH
new_row=edit_op.row-1; new_col=edit_op.variable
line=edit.text[new_row]
text_ala=line.s[0:new_col]
text2=line.s[new_col:]
line.s=text_ala
insert(edit.text,edit_op.row,text2)
writeRedo(edit,edit_op.opCode)
elif edit_op.opCode=EDIT_OP_DELETE_PARAGRAPH_1
new_row=edit_op.row; new_col=edit_op.variable
line=edit.text[new_row]
text_ala=line.s[0:new_col]
text2=line.s[new_col:]
line.s=text2
insert(edit.text,edit_op.row,text_ala)
writeRedo(edit,edit_op.opCode)
elif edit_op.opCode=EDIT_OP_DELETE_SELECTION
edit.selLastRow=edit_op.selRow; edit.selEndCol=edit_op.selCol
selection_lines=edit_op.variable
le_selection=len(selection_lines)
if le_selection=1 # one line selection
text_ala=selection_lines[0]
line=edit.text[edit_op.row]
insert(line.s,edit_op.auxCol,text_ala)
elif le_selection >1
text_ala=selection_lines[0]
line=edit.text[edit_op.auxRow]; new_text=line.s[:edit_op.auxCol];text2=line.s[edit_op.auxCol:]
line.s=new_text+text_ala
for ind=1 to le_selection-2
ind_white=ind+edit_op.auxRow
new_text=selection_lines[ind]
insert(edit.text,ind_white,new_text)
if ind_white
ind_white=ind_white+1
else
ind_white=edit_op.auxRow+1
text_ala=selection_lines[le_selection -1]
new_text=text_ala+text2
insert(edit.text,ind_white,new_text)
writeRedo(edit,edit_op.opCode)
elif edit_op.opCode=EDIT_OP_INSERT_TEXT
line=edit.text[edit_op.row]
text_ala=line.s[edit_op.col:edit_op.auxCol]
writeRedoVar(edit,edit_op.opCode,text_ala)
delete(line.s,edit_op.col,edit_op.auxCol)
elif edit_op.opCode=EDIT_OP_INSERT_LINES
#first line
line=edit.text[edit_op.row]
text_ala=line.s[edit_op.col:]
append(selection_lines,text_ala)
line.s=line.s[:edit_op.col]
if edit_op.auxRow > edit_op.row+1
deleted=subButS(edit.text,edit_op.row+1, edit_op.auxRow)
selection_lines=selection_lines+deleted
last_line=edit.text[edit_op.auxRow]
text_ala=last_line.s[:edit_op.auxCol];append(selection_lines,text_ala)
text2= last_line.s[edit_op.auxCol:]
for ind= edit_op.auxRow to edit_op.row+1 step -1
delete(edit.text,ind)
line.s=line.s+text2
writeRedo(edit,edit_op.opCode,selection_lines)
draw(edit) #!!!!!!!!!!!!!!!!!!!!
proc redoLastOP(Edit edit)=
EditOp edit_op;Str line;text_ala=""; text2=""; new_text="";selection_lines=[];EditOp undo_op
edit_op=popEditOp(edit.redo);new_col=0
if edit_op.opCode
edit.cursorRow=edit_op.row; edit.cursorCol=edit_op.col;edit.firstVisibleRow=edit_op.firstVisibleRow
if edit_op.opCode=EDIT_OP_INSERT_CHAR
key_code=ord(edit_op.letter)
keyPressed(edit,key_code)
elif edit_op.opCode=EDIT_OP_DELETE_CHAR
keyBackspace(edit)
elif edit_op.opCode=EDIT_OP_DELETE_CHAR_1
keyDelete(edit)
elif edit_op.opCode=EDIT_OP_INSERT_PARAGRAPH
keyEnter(edit)
elif edit_op.opCode=EDIT_OP_DELETE_PARAGRAPH
keyBackspace(edit)
elif edit_op.opCode=EDIT_OP_DELETE_PARAGRAPH_1
keyDelete(edit)
elif edit_op.opCode=EDIT_OP_DELETE_SELECTION
edit.selLastRow=edit_op.selRow; edit.selEndCol=edit_op.selCol
delete=1;copy=0;forSelection(edit,delete,copy)
elif edit_op.opCode=EDIT_OP_INSERT_TEXT
text_ala=edit_op.variable
append(selection_lines,text_ala)
insertLines(edit,selection_lines)
elif edit_op.opCode=EDIT_OP_INSERT_LINES
selection_lines=edit_op.variable
insertLines(edit,selection_lines)
#append(edit.undo,undo_op)#!!!!!!!!!!!!!!
draw(edit) #!!!!!!!!!!!!!!!!!!!!
end:#=========================================
proc insertLines(Edit edit, list lines)=
text=""; Str line; before=""; after=""
le_lines=len(lines)
if le_lines=1
text=lines[0]
line=edit.text[edit.cursorRow]
insert(line.s,edit.cursorCol,text)
new_col=edit.cursorCol+len(text)
writeUndo(edit,EDIT_OP_INSERT_TEXT,edit.cursorRow,new_col) #!!!!!!!!!!!!!
edit.cursorCol=new_col
elif le_lines>1
#first line
line=edit.text[edit.cursorRow]
before=line.s[:edit.cursorCol]; after=line.s[edit.cursorCol:]
text=lines[0]
line.s=before+text #!!!!!!!!!!!!
new_ind=edit.cursorRow+1
for ind=1 to le_lines-2
text=lines[ind]
insert(edit.text,new_ind,text)
new_ind=new_ind+1
#last line
text=lines[le_lines-1] # take last
new_col=len(text) #!!!!!!!!!!
text=text+after
insert(edit.text,new_ind,text)
new_row=edit.cursorRow+le_lines-1
writeUndo(edit,EDIT_OP_INSERT_LINES,new_row,new_col) #!!!!!!!!!!!!!
edit.cursorRow=new_row
edit.cursorCol=new_col
draw(edit)
proc forSelection(Edit edit, int delete, int copy)= #*******************************
to_delete=""; Str line; selection_lines=[]; deleted_lines=[];last_str=""
if edit.selLastRow=edit.cursorRow #one line selection
line=edit.text[edit.cursorRow]
if edit.selEndCol > edit.cursorCol
start_col=edit.cursorCol; end_col=edit.selEndCol
else
start_col=edit.selEndCol; end_col=edit.cursorCol
to_delete=line[start_col:end_col]
append(selection_lines,to_delete)
if delete
writeUndo(edit,EDIT_OP_DELETE_SELECTION,selection_lines,edit.cursorRow,start_col) #!!!!!!!!!!!!!
delete(line.s,start_col,end_col) #!!!!!!!!!!!!!!!!!!
edit.cursorCol=start_col #!!!!!!!!!!
if copy:ok=writeClippboard(selection_lines)
else # more rows
#prepare undo
if edit.selLastRow > edit.cursorRow
start_row=edit.cursorRow; start_col=edit.cursorCol
end_row=edit.selLastRow+1;end_col=edit.selEndCol
else
start_row=edit.selLastRow; start_col=edit.selEndCol
end_row=edit.cursorRow+1; end_col=edit.cursorCol
last_row=end_row-1
#first selection line
line=edit.text[start_row]; to_delete=line[start_col:]; append(selection_lines,to_delete)
#whole lines in the middle
if last_row > start_row+1 # some whole lines
new_start=start_row+1
deleted_lines=subButS(edit.text,new_start,last_row)
selection_lines=selection_lines+deleted_lines
#last selection line
last_line=edit.text[last_row]; to_delete=last_line[:end_col]; append(selection_lines,to_delete)
if delete
writeUndo(edit,EDIT_OP_DELETE_SELECTION,selection_lines,start_row,start_col) #!!!!!!!!!!!!!
#delete
line.s=line.s[:start_col]
last_str=last_line.s[end_col:] #!!!!!!!!!!!!
line.s=line.s+last_str
if last_row > start_row+1 # some whole lines
delete(edit.text,start_row+1,end_row) #!!!!!!!!!
else #delte last
delete(edit.text,last_row) #!!!!!!!!!
edit.cursorRow=start_row #!!!!!!!!!!!!!
edit.cursorCol=start_col #!!!!!!!!!!
if copy:ok=writeClippboard(selection_lines)
if delete
edit.selLastRow=-1;edit.selEndCol=-1 #!!!!!!!!!!1
draw(edit) #!!!!!!!!!!!!!!!!
#-------------------------------------------------------------------
proc mouseLBD(Edit edit, Event event)=# ***************************************************
mouse_x=loWord(event.lParam)
mouse_y=hiWord(event.lParam)
Str line;char letter; old=-1
cliRe=getClientRect(edit.control)
lineNo=(mouse_y-cliRe.y)/edit.lineH +edit.firstVisibleRow
if lineNo >=0
le_text=len(edit.text)
if lineNo >=le_text:lineNo=le_text-1 #!!!!!!!!!!!!!!
xt=cliRe.x+edit.leftMargin-edit.viewX
if mouse_x> xt
line=edit.text[lineNo]
le=len(line)
for k=0 to le-1
letter=line[k]
if toInt(letter)=9 #tab code
if edit.tabLength>0
xt=tabPosition(edit,xt)
else
charW=getCharWidth(edit.hdc,letter)
xt=xt+charW
if xt >= mouse_x
goto end#=============
end:#=============
clearSelection(edit) #!!!!!!!!!!!!!!!!!
if lineNo != edit.cursorRow
old=edit.cursorRow
edit.cursorRow=lineNo #!!!!!!!!!!!!!
edit.cursorCol=k #!!!!!!!!!!!!!!!
edit.mouseLBD=1 #!!!!!!!!!!!!!!!
if old >=0 :drawTextLine(edit,old)
drawTextLine(edit,edit.cursorRow)
drawControl(edit.control)
proc mouseLBU(Edit edit, Event event)=#******************************************************
edit.mouseLBD=0 #!!!!!!!!!!!!!!!!!
proc mouseMove(Edit edit,Event event)=
mouse_x=loWord(event.lParam)
mouse_y=hiWord(event.lParam)
Str line;char letter; old=-1
if edit.mouseLBD
cliRe=getClientRect(edit.control)
lineNo=(mouse_y-cliRe.y)/edit.lineH +edit.firstVisibleRow
text_len=len(edit.text)
if lineNo >=0 and lineNo < text_len
xt=cliRe.x+edit.leftMargin-edit.viewX
if mouse_x> xt
line=edit.text[lineNo]
le=len(line)
for k=0 to le-1
letter=line[k]
if toInt(letter)=9 #tab code
if edit.tabLength>0
xt=tabPosition(edit,xt)
else
charW=getCharWidth(edit.hdc,letter)
xt=xt+charW
if xt >= mouse_x
goto end#=============
end:#=============
edit.selLastRow=lineNo
edit.selEndCol=k
if lineNo = edit.cursorRow
if k != edit.cursorCol
drawTextLine(edit,lineNo) #draw with selection
elif lineNo > edit.cursorRow
for ind= edit.cursorRow to lineNo
drawTextLine(edit,ind)
else
for ind= lineNo to edit.cursorRow
drawTextLine(edit,ind)
#----------------------------------------------------------------
proc horScroll(Edit edit, Event event)=
code=loWord(event.wParam)
#---------------------------
SCROLLINFO si
si.cbSize=28
si.fMask=SIF_RANGE #SIF_POS SIF_PAGE
call user32.GetScrollInfo (edit.control.id, SB_HORZ, si)
scroll_range= si.nMax+1 #nPos, nPage
if code=H_SCROLL_RIGHT: horScrollRight(edit, scroll_range)
elif code=H_SCROLL_LEFT: horScrollLeft(edit, scroll_range)
elif code=H_SCROLL_MOVE: horScrollMove(edit, scroll_range,event)
proc horScrollRight(Edit edit, int scroll_range)=#****************************************************
null=0
disX=edit.tabLength
horScrollProc(edit,disX,null,scroll_range)
proc horScrollLeft(Edit edit, int scroll_range)=
null=0
disX=0-edit.tabLength
horScrollProc(edit,disX,null,scroll_range)
proc horScrollMove(Edit edit, int scroll_range, Event event)=
null=0
button_pos=hiWord(event.wParam)
horScrollProc(edit,null,button_pos,scroll_range)
proc horScrollProc(Edit edit,int dX, int buttonPos,int scrollRange)=
#if dX >0 to the right
rect=getClientRect(edit.control)
viewX=edit.viewX
if edit.horScrollRange >0
if edit.horScrollRange > rect.w
if dX #left or right button
viewX1=viewX+dX
if viewX1<0: viewX1=0
elif viewX1 > edit.horScrollRange-rect.w
edit.horScrollRange=viewX1+rect.w #!!!!!!!!!!!
if viewX1 != viewX
scroll_et1: #-------------------------------------------------
updateHorScroll(viewX1, rect.w, edit.horScrollRange,edit.control)
edit.viewX=viewX1 #!!!!!!!!!!!!!!!!!!
drawText(edit,rect) #!!!!!!!!!!!!!!
else #move on
viewX1=(edit.horScrollRange-rect.w)*buttonPos/scrollRange #!!!!!!!!!!!!!!!!!
if viewX1 != viewX
goto scroll_et1 #-------------------------------------------------
#Fifo and EditOp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
proc append(Fifo fifo, EditOp x)=
FifoElement element;FifoElement first;FifoElement beforeLast;FifoElement last
element.value=x
if fifo.first=0
fifo.last=element
fifo.first=element
fifo.len=1
else
first=fifo.first
element.next=first
first.prev=element
fifo.first=element
fifo.len=fifo.len+1
if fifo.maxLen
if fifo.len>fifo.maxLen
last=fifo.last
beforeLast=last.prev
beforeLast.next=0
fifo.last=beforeLast
fifo.len=fifo.len-1
EditOp popEditOp(Fifo fifo)=
EditOp res;FifoElement element
if fifo.first !=0
element=fifo.first
fifo.first=element.next
res=element.value
fifo.len=fifo.len-1
return res
#Fifo and EditOp end ====================================================================
# to implement ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int writeClippboard(list selection_lines)=
res=1; return res
#===============================================================================================================================
#main ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
initGui() #!!!!!!!!!!!!!!!!!!!!
screen=getScreen()
style=0;mode=0;parentId=0
main_x=screen.w/4; main_y=screen.h/8+40
main_w=screen.w-main_x-40; main_h=screen.h-main_y-40
mainWnd= Window(main_x,main_y,main_w,main_h,style,mode,parentId,"document 1.txt")
if mainWnd.id=0 :printLastError(); goto end #========================
global guiFont; int guiFont
margin=20
edit_w=main_w-main_w/8-margin
edit_h=main_h-main_h/8-margin
edit=Edit(margin,margin,edit_w,edit_h,guiFont,mainWnd)
tab=chr(9)
for k=1 to 120
s=toStr(k)
text=tab+s+" Alice has a cat 1234abcdefghijklmnopqxyz "+s
ns=append(edit.text,text)
last=edit.text[edit.cursorRow]
edit.cursorCol=len(last)
setVerScrollRange(edit) #!!!!!!!!!!!!!!!
show(mainWnd)
setFocus(edit.control)
eventLoop()
end: #========================