revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / zune / texteditor / mcc / Methods.c
blob3567b217e785131ed1a69fbad675e95c6d530a9c
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
19 $Id$
21 ***************************************************************************/
23 #include <intuition/intuition.h>
24 #include <proto/exec.h>
25 #include <proto/graphics.h>
26 #include <proto/intuition.h>
28 #include "private.h"
29 #include "Debug.h"
31 #include "TextEditor_mcp.h"
33 /// mBlockInfo()
34 IPTR mBlockInfo(struct InstData *data, struct MUIP_TextEditor_BlockInfo *msg)
36 IPTR result = FALSE;
38 ENTER();
40 if(Enabled(data))
42 struct marking newblock;
44 NiceBlock(&data->blockinfo, &newblock);
45 *(msg->startx) = newblock.startx;
46 *(msg->stopx) = newblock.stopx;
47 *(msg->starty) = LineNr(data, newblock.startline)-1;
48 *(msg->stopy) = LineNr(data, newblock.stopline)-1;
50 result = TRUE;
53 RETURN(result);
54 return(result);
57 ///
58 /// mQueryKeyAction()
59 IPTR mQueryKeyAction(UNUSED struct IClass *cl, Object *obj, struct MUIP_TextEditor_QueryKeyAction *msg)
61 struct te_key *userkeys;
62 struct te_key *foundKey = NULL;
63 IPTR setting = 0;
64 int i;
66 ENTER();
68 // now we try to retrieve the currently active
69 // key bindings, or we take the default ones
70 if(!DoMethod(obj, MUIM_GetConfigItem, MUICFG_TextEditor_Keybindings, &setting) || setting == 0)
71 userkeys = (struct te_key *)default_keybindings;
72 else
73 userkeys = (struct te_key *)setting;
75 for(i=0; (WORD)userkeys[i].code != -1; i++)
77 struct te_key *curKey = &userkeys[i];
79 if(curKey->act == msg->keyAction)
81 foundKey = curKey;
82 break;
86 RETURN((IPTR)foundKey);
87 return (IPTR)foundKey;
90 ///
91 /// mMarkText()
92 IPTR mMarkText(struct InstData *data, struct MUIP_TextEditor_MarkText *msg)
94 ENTER();
96 if(Enabled(data))
98 data->blockinfo.enabled = FALSE;
99 MarkText(data, data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline);
101 else
103 SetCursor(data, data->CPos_X, data->actualline, FALSE);
106 // check if anything at all should be marked or not
107 if((LONG)msg->start_crsr_y != MUIV_TextEditor_MarkText_None)
109 // check if only the specified area should be marked/selected
110 if((LONG)msg->stop_crsr_y != MUIV_TextEditor_MarkText_All)
112 data->blockinfo.startline = LineNode(data, msg->start_crsr_y+1);
113 data->blockinfo.startx = (data->blockinfo.startline->line.Length > msg->start_crsr_x) ? msg->start_crsr_x : data->blockinfo.startline->line.Length-1;
114 data->blockinfo.stopline = LineNode(data, msg->stop_crsr_y+1);
115 data->blockinfo.stopx = (data->blockinfo.stopline->line.Length > msg->stop_crsr_x) ? msg->stop_crsr_x : data->blockinfo.stopline->line.Length-1;
116 data->blockinfo.enabled = TRUE;
118 data->actualline = data->blockinfo.stopline;
119 data->CPos_X = data->blockinfo.stopx;
120 ScrollIntoDisplay(data);
122 else
124 // the user selected to mark all available text
125 MarkAllBlock(data, &data->blockinfo);
128 MarkText(data, data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline);
131 RETURN(TRUE);
132 return(TRUE);
136 /// mClearText()
137 IPTR mClearText(struct IClass *cl, Object *obj, UNUSED Msg msg)
139 struct InstData *data = INST_DATA(cl, obj);
140 struct line_node *newcontents;
142 ENTER();
144 if((newcontents = AllocVecPooled(data->mypool, sizeof(struct line_node))) != NULL)
146 if(Init_LineNode(data, newcontents, "\n") == TRUE)
148 if(isFlagClear(data->flags, FLG_ReadOnly) && data->maxUndoSteps != 0)
150 struct marking newblock;
152 MarkAllBlock(data, &newblock);
154 data->CPos_X = 0;
155 data->actualline = GetFirstLine(&data->linelist);
157 // add the text to the undo buffer only if we really have some text
158 // i.e. the block contains at least some characters or some lines
159 if(newblock.startline != newblock.stopline || newblock.startx < newblock.stopx)
160 AddToUndoBuffer(data, ET_DELETEBLOCK_NOMOVE, &newblock);
162 FreeTextMem(data, &data->linelist);
163 AddLine(&data->linelist, newcontents);
164 ResetDisplay(data);
166 else
168 FreeVecPooled(data->mypool, newcontents);
172 RETURN(TRUE);
173 return(TRUE);
177 /// mToggleCursor()
178 IPTR mToggleCursor(struct IClass *cl, Object *obj, UNUSED Msg msg)
180 struct InstData *data = INST_DATA(cl, obj);
182 ENTER();
184 if(isFlagSet(data->flags, FLG_Active))
186 if(data->cursor_shown == TRUE)
188 SetCursor(data, data->CPos_X, data->actualline, FALSE);
189 data->cursor_shown = FALSE;
191 else
193 SetCursor(data, data->CPos_X, data->actualline, TRUE);
194 data->cursor_shown = TRUE;
198 RETURN(TRUE);
199 return(TRUE);
203 /// mInputTrigger()
204 IPTR mInputTrigger(struct IClass *cl, Object *obj, UNUSED Msg msg)
206 struct InstData *data = INST_DATA(cl, obj);
208 ENTER();
210 if(data->smooth_wait == 1 && data->scrollaction == TRUE)
212 if(data->ypos != _mtop(obj))
214 LONG move;
216 if(data->scr_direction)
217 move = data->fontheight-(_mtop(obj)-data->ypos);
218 else
219 move = -(_mtop(obj)-data->ypos);
221 if(move != 1 && move != -1)
222 move = (move*2)/3;
224 set(obj, MUIA_TextEditor_Prop_First, (data->visual_y-1)*data->fontheight+(_mtop(obj)-data->ypos)+move);
226 else
228 data->scrollaction = FALSE;
229 RejectInput(data);
231 if(isFlagSet(data->flags, FLG_Active))
233 SetCursor(data, data->CPos_X, data->actualline, TRUE);
238 if(data->mousemove == TRUE)
240 LONG MouseX = _window(obj)->MouseX;
241 LONG MouseY = _window(obj)->MouseY;
242 LONG oldCPos_X = data->CPos_X;
243 struct line_node *oldactualline = data->actualline;
244 BOOL scroll = TRUE;
246 if(xget(_win(obj), MUIA_Window_Activate) == FALSE)
248 data->mousemove = FALSE;
249 RejectInput(data);
251 RETURN(TRUE);
252 return(TRUE);
255 if(MouseY < data->ypos)
257 LONG diff = data->ypos - MouseY;
259 if(diff > 30)
260 GoUp(data);
261 if(diff > 20)
262 GoUp(data);
263 if(diff > 10)
264 GoUp(data);
265 GoUp(data);
266 MouseY = data->ypos;
268 else
270 LONG limit = data->ypos;
272 if(data->maxlines < (data->totallines-data->visual_y+1))
273 limit += (data->maxlines * data->fontheight);
274 else
275 limit += (data->totallines-data->visual_y+1)*data->fontheight;
277 if(MouseY >= limit)
279 LONG diff = MouseY - limit;
281 if(diff > 30)
282 GoDown(data);
283 if(diff > 20)
284 GoDown(data);
285 if(diff > 10)
286 GoDown(data);
288 GoDown(data);
290 else
292 PosFromCursor(data, MouseX, MouseY);
293 scroll = FALSE;
297 if(data->blockinfo.enabled == TRUE && scroll == TRUE && data->blockinfo.stopline == data->actualline && data->blockinfo.stopx == data->CPos_X)
299 PosFromCursor(data, MouseX, MouseY);
302 if(data->selectmode != 0)
304 struct marking tmpblock;
306 NiceBlock(&data->blockinfo, &tmpblock);
307 if(data->blockinfo.startx == tmpblock.startx && data->blockinfo.startline == tmpblock.startline)
309 if(MouseX > _mleft(obj))
311 if(data->selectmode == 1)
313 while(data->CPos_X < data->actualline->line.Length-1 && CheckSep(data, data->actualline->line.Contents[data->CPos_X]) == FALSE)
314 // while((data->CPos_X < data->actualline->line.Length-1) && (data->actualline->line.Contents[data->CPos_X] != ' '))
315 data->CPos_X++;
317 else
319 GoEndOfLine(data);
323 else
325 struct pos_info pos;
326 LONG flow;
328 OffsetToLines(data, data->CPos_X, data->actualline, &pos);
329 flow = FlowSpace(data, data->actualline->line.Flow, &data->actualline->line.Contents[pos.bytes]);
331 if(MouseX <= _mleft(obj)+flow+TextLengthNew(&data->tmprp, &data->actualline->line.Contents[pos.bytes], pos.extra-pos.bytes-1, data->TabSizePixels))
333 if(data->selectmode == 1)
335 while(data->CPos_X > 0 && CheckSep(data, data->actualline->line.Contents[data->CPos_X-1]) == FALSE)
336 // while(data->CPos_X > 0 && data->actualline->line.Contents[data->CPos_X-1] != ' ')
337 data->CPos_X--;
339 else
341 GoStartOfLine(data);
347 if(data->blockinfo.enabled == TRUE || data->selectmode == 0)
349 // if selectmode == 2, then the user has trippleclicked at the line
350 // and wants to get the whole line marked
351 if(data->selectmode == 2 || data->selectmode == 3)
353 data->selectmode = 2;
355 // if the line is a hard wrapped one we have to increase CPos_X by one
356 if(data->actualline->line.Contents[data->CPos_X] > ' ')
358 data->CPos_X++;
359 MarkText(data, data->blockinfo.stopx, data->blockinfo.stopline, data->CPos_X, data->actualline);
361 else
362 MarkText(data, data->blockinfo.stopx, data->blockinfo.stopline, data->CPos_X+1, data->actualline);
364 data->selectmode = 3;
366 else if(data->blockinfo.stopline != data->actualline || data->blockinfo.stopx != data->CPos_X)
368 data->blockinfo.enabled = TRUE;
369 MarkText(data, data->blockinfo.stopx, data->blockinfo.stopline, data->CPos_X, data->actualline);
372 data->blockinfo.stopline = data->actualline;
373 data->blockinfo.stopx = data->CPos_X;
375 else
377 data->mousemove = FALSE;
378 RejectInput(data);
381 if(oldCPos_X != data->CPos_X || oldactualline != data->actualline)
383 ScrollIntoDisplay(data);
384 PosFromCursor(data, MouseX, MouseY);
386 // make sure to notify others that the cursor has changed and so on.
387 data->NoNotify = TRUE;
389 if(data->CPos_X != oldCPos_X)
390 set(obj, MUIA_TextEditor_CursorX, data->CPos_X);
392 if(data->actualline != oldactualline)
393 set(obj, MUIA_TextEditor_CursorY, LineNr(data, data->actualline)-1);
395 data->NoNotify = FALSE;
399 RETURN(TRUE);
400 return(TRUE);
404 /// InsertText()
405 ULONG InsertText(struct InstData *data, STRPTR text, BOOL moveCursor)
407 struct MinList newlines;
408 struct line_node *actline = data->actualline;
409 LONG x = data->CPos_X;
410 LONG realx = 0;
412 ENTER();
414 if(ImportText(data, text, data->ImportHook, data->ImportWrap, &newlines) == TRUE)
416 BOOL oneline = FALSE;
417 BOOL newline = FALSE;
418 struct line_node *line;
419 LONG tvisual_y;
421 data->totallines += CountLines(data, &newlines);
423 line = GetLastLine(&newlines);
424 if(line->line.Contents[line->line.Length] == '\n')
425 newline = TRUE;
427 data->update = FALSE;
428 SplitLine(data, x, actline, FALSE, NULL);
429 InsertLines(&newlines, actline);
430 data->CPos_X = line->line.Length-1;
431 if(GetNextLine(actline) == line)
433 data->CPos_X += actline->line.Length-1;
434 oneline = TRUE;
436 if(newline == FALSE)
437 MergeLines(data, line);
438 MergeLines(data, actline);
439 if(oneline == TRUE)
440 line = actline;
441 if(newline == TRUE)
443 line = GetNextLine(line);
444 data->CPos_X = 0;
446 if(moveCursor == TRUE)
448 data->actualline = line;
450 else
452 realx = data->CPos_X;
453 data->CPos_X = x;
455 data->update = TRUE;
457 ScrollIntoDisplay(data);
459 tvisual_y = LineToVisual(data, actline)-1;
460 if(tvisual_y < 0)
461 tvisual_y = 0;
463 if(isFlagClear(data->flags, FLG_Quiet))
465 SetCursor(data, data->CPos_X, line, FALSE);
466 if(data->blockinfo.enabled == TRUE)
468 data->blockinfo.enabled = FALSE;
469 MarkText(data, data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline);
471 DumpText(data, data->visual_y+tvisual_y, tvisual_y, data->maxlines, TRUE);
473 else
475 data->blockinfo.enabled = FALSE;
478 if(moveCursor == FALSE)
480 data->CPos_X = realx;
481 data->actualline = line;
485 RETURN(TRUE);
486 return(TRUE);