1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2014 TextEditor.mcc Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 TextEditor class Support Site: http://www.sf.net/projects/texteditor-mcc
21 ***************************************************************************/
27 #include <dos/rdargs.h>
28 #include <exec/memory.h>
29 #include <clib/alib_protos.h>
30 #include <proto/utility.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
43 static const struct RexxCommand Commands
[] =
50 { "GOTOLINE", "/N/A" },
51 { "GOTOCOLUMN", "/N/A" },
52 { "CURSOR", "Up/S,Down/S,Left/S,Right/S" },
55 { "NEXT", "Word/S,Sentence/S,Paragraph/S,Page/S" },
56 { "PREVIOUS", "Word/S,Sentence/S,Paragraph/S,Page/S" },
57 { "POSITION", "SOF/S,EOF/S,SOL/S,EOL/S,SOW/S,EOW/S,SOV/S,EOV/S" },
58 { "SETBOOKMARK", "/N/A" },
59 { "GOTOBOOKMARK", "/N/A" },
64 { "GETCURSOR", "Line/S,Column/S" },
65 { "MARK", "On/S,Off/S" },
67 { "BACKSPACE", NULL
},
71 { "SELECTALL", NULL
},
72 { "SELECTNONE", NULL
},
78 CLEAR
= 0, CUT
, COPY
, PASTE
, ERASE
, GOTOLINE
, GOTOCOLUMN
, CURSOR
,
79 LINE
, COLUMN
, NEXT
, PREVIOUS
, POSITION
, SETBOOKMARK
, GOTOBOOKMARK
,
80 InsTEXT
, UNDO
, REDO
, GETLINE
, GETCURSOR
, MARK
, DELETE
, BACKSPACE
,
81 KILLLINE
, TOUPPER
, TOLOWER
, SELECTALL
, SELECTNONE
87 static IPTR
CallFunction(struct InstData
*data
, UWORD function
, IPTR
*args
, const char *txtargs
)
89 struct line_node
*oldactualline
= data
->actualline
;
90 LONG oldCPos_X
= data
->CPos_X
;
92 LONG new_y
= data
->visual_y
-1;
96 SHOWVALUE(DBF_REXX
, function
);
98 if(isFlagSet(data
->flags
, FLG_ReadOnly
))
114 new_y
+= data
->maxlines
;
121 new_y
-= data
->maxlines
;
127 if(new_y
!= data
->visual_y
-1)
129 if(new_y
> data
->totallines
-data
->maxlines
)
130 new_y
= data
->totallines
-data
->maxlines
;
133 set(data
->object
, MUIA_TextEditor_Prop_First
, new_y
*data
->fontheight
);
137 if(function
> GOTOBOOKMARK
|| function
< GOTOLINE
)
138 clearFlag(data
->flags
, FLG_ARexxMark
);
144 DoMethod(data
->object
, MUIM_TextEditor_ClearText
);
179 if((buffer
= AllocVecShared(16, MEMF_ANY
)) != NULL
)
181 set(data
->object
, MUIA_TextEditor_CursorY
, *(ULONG
*)*args
);
183 // return the current line number, this may differ from the input value!
184 snprintf(buffer
, 16, "%ld", xget(data
->object
, MUIA_TextEditor_CursorY
));
185 result
= (IPTR
)buffer
;
197 if((buffer
= AllocVecShared(16, MEMF_ANY
)) != NULL
)
199 set(data
->object
, MUIA_TextEditor_CursorX
, *(ULONG
*)*args
);
200 // return the current column number, this may differ from the input value!
201 snprintf(buffer
, 16, "%ld", xget(data
->object
, MUIA_TextEditor_CursorX
));
202 result
= (IPTR
)buffer
;
227 line
= xget(data
->object
, MUIA_TextEditor_CursorY
);
228 line
+= *(LONG
*)*args
;
229 set(data
->object
, MUIA_TextEditor_CursorY
, (line
< 0) ? 0 : line
);
240 column
= xget(data
->object
, MUIA_TextEditor_CursorX
);
241 column
+= *(LONG
*)*args
;
242 set(data
->object
, MUIA_TextEditor_CursorX
, (column
< 0) ? 0 : column
);
252 GoNextSentence(data
);
263 GoPreviousWord(data
);
265 GoPreviousSentence(data
);
267 GoPreviousLine(data
);
269 GoPreviousPage(data
);
284 GoPreviousWord(data
);
288 GoPreviousPage(data
);
298 struct Hook
*oldhook
= data
->ImportHook
;
300 data
->ImportHook
= &ImPlainHook
;
301 DoMethod(data
->object
, MUIM_TextEditor_InsertText
, txtargs
, MUIV_TextEditor_InsertText_Cursor
);
302 data
->ImportHook
= oldhook
;
323 if((buffer
= AllocVecShared(data
->actualline
->line
.Length
+1, MEMF_ANY
)) != NULL
)
325 strlcpy(buffer
, data
->actualline
->line
.Contents
, data
->actualline
->line
.Length
+1);
326 result
= (IPTR
)buffer
;
335 if((buffer
= AllocVecShared(16, MEMF_ANY
)) != NULL
)
340 pos
= xget(data
->object
, MUIA_TextEditor_CursorY
);
342 pos
= xget(data
->object
, MUIA_TextEditor_CursorX
);
344 snprintf(buffer
, 16, "%d", (int)pos
);
346 result
= (IPTR
)buffer
;
354 SetBookmark(data
, *(ULONG
*)*args
-1);
361 GotoBookmark(data
, *(ULONG
*)*args
-1);
369 data
->flags
&= ~FLG_ARexxMark
;
370 if(data
->blockinfo
.enabled
== TRUE
)
372 data
->blockinfo
.enabled
= FALSE
;
373 MarkText(data
, data
->blockinfo
.startx
, data
->blockinfo
.startline
, data
->blockinfo
.stopx
, data
->blockinfo
.stopline
);
378 setFlag(data
->flags
, FLG_ARexxMark
);
415 MarkAllBlock(data
, &data
->blockinfo
);
416 MarkText(data
, data
->blockinfo
.startx
, data
->blockinfo
.startline
, data
->blockinfo
.stopx
, data
->blockinfo
.stopline
);
422 if(data
->blockinfo
.enabled
== TRUE
)
424 data
->blockinfo
.enabled
= FALSE
;
425 MarkText(data
, data
->blockinfo
.startx
, data
->blockinfo
.startline
, data
->blockinfo
.stopx
, data
->blockinfo
.stopline
);
428 W(DBF_BLOCK
, "no text selected (startline=%08lx, stopline=%08lx)", data
->blockinfo
.startline
, data
->blockinfo
.stopline
);
433 if(data
->CPos_X
!= oldCPos_X
|| oldactualline
!= data
->actualline
)
435 if(isFlagSet(data
->flags
, FLG_Active
) && function
<= GOTOBOOKMARK
&& function
>= GOTOLINE
)
436 SetCursor(data
, oldCPos_X
, oldactualline
, FALSE
);
438 if(isFlagSet(data
->flags
, FLG_ARexxMark
))
440 data
->blockinfo
.stopline
= data
->actualline
;
441 data
->blockinfo
.stopx
= data
->CPos_X
;
442 if(data
->blockinfo
.enabled
== FALSE
)
444 data
->blockinfo
.enabled
= TRUE
;
445 data
->blockinfo
.startline
= oldactualline
;
446 data
->blockinfo
.startx
= oldCPos_X
;
448 MarkText(data
, oldCPos_X
, oldactualline
, data
->CPos_X
, data
->actualline
);
452 if(data
->blockinfo
.enabled
== TRUE
)
454 data
->blockinfo
.enabled
= FALSE
;
455 MarkText(data
, data
->blockinfo
.startx
, data
->blockinfo
.startline
, data
->blockinfo
.stopx
, data
->blockinfo
.stopline
);
459 ScrollIntoDisplay(data
);
461 if(isFlagSet(data
->flags
, FLG_Active
) && function
<= GOTOBOOKMARK
&& function
>= GOTOLINE
)
462 SetCursor(data
, data
->CPos_X
, data
->actualline
, TRUE
);
464 // make sure to notify others that the cursor has changed and so on.
465 data
->NoNotify
= TRUE
;
467 if(data
->CPos_X
!= oldCPos_X
)
468 set(data
->object
, MUIA_TextEditor_CursorX
, data
->CPos_X
);
470 if(data
->actualline
!= oldactualline
)
471 set(data
->object
, MUIA_TextEditor_CursorY
, LineNr(data
, data
->actualline
)-1);
473 data
->NoNotify
= FALSE
;
483 IPTR
mHandleARexx(struct IClass
*cl
, Object
*obj
, struct MUIP_TextEditor_ARexxCmd
*msg
)
485 struct InstData
*data
= INST_DATA(cl
, obj
);
487 STRPTR command
= msg
->command
;
491 if(data
->shown
== TRUE
&& command
!= NULL
&& command
[0] != '\0')
493 const char *txtargs
= "";
497 SHOWSTRING(DBF_REXX
, command
);
499 for(function
=0; (cmd
= Commands
[function
].Command
) != NULL
; function
++)
501 int cmdlen
= strlen(cmd
);
503 if(strnicmp(command
, cmd
, cmdlen
) == 0 &&
504 (command
[cmdlen
] == ' ' || command
[cmdlen
] == '\0'))
506 txtargs
= &command
[cmdlen
];
511 SHOWVALUE(DBF_REXX
, function
);
512 SHOWSTRING(DBF_REXX
, txtargs
);
514 if(Commands
[function
].Command
!= NULL
&& (*txtargs
== '\0' || Commands
[function
].Template
!= NULL
))
518 memset(Args
, 0, sizeof(Args
));
520 // skip leading spaces
521 while(isspace(*txtargs
))
524 if(*txtargs
!= '\0' && function
!= InsTEXT
)
526 struct RDArgs
*myrdargs
= NULL
;
528 if((myrdargs
= AllocDosObject(DOS_RDARGS
, NULL
)) != NULL
)
530 ULONG length
= strlen(txtargs
);
533 if((buffer
= AllocVecPooled(data
->mypool
, length
+2)) != NULL
)
535 struct RDArgs
*ra_result
= NULL
;
537 snprintf(buffer
, length
+2, "%s\n", txtargs
);
539 myrdargs
->RDA_Source
.CS_Buffer
= buffer
;
540 myrdargs
->RDA_Source
.CS_Length
= length
+1;
541 myrdargs
->RDA_Source
.CS_CurChr
= 0;
542 myrdargs
->RDA_Flags
|= RDAF_NOPROMPT
;
544 if((ra_result
= ReadArgs(Commands
[function
].Template
, (APTR
)Args
, myrdargs
)) != NULL
)
546 result
= CallFunction(data
, function
, Args
, NULL
);
550 FreeVecPooled(data
->mypool
, buffer
);
552 FreeDosObject(DOS_RDARGS
, myrdargs
);
556 result
= CallFunction(data
, function
, Args
, (char *)txtargs
);