Updated from its repository.
[cake.git] / workbench / classes / gadgets / texteditor / mcc / GetSetAttrs.c
blob9b9df7c9e60651f8c82258d754c8d6c5abd27861
1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2009 by 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/classes.h>
24 #include <utility/tagitem.h>
25 #include <clib/alib_protos.h>
27 #include <proto/graphics.h>
28 #include <proto/utility.h>
29 #include <proto/layers.h>
30 #include <proto/intuition.h>
32 #include <libraries/mui.h>
33 #include <proto/muimaster.h>
35 #include "private.h"
37 #include "version.h"
39 IPTR Get(struct IClass *cl, Object *obj, struct opGet *msg)
41 struct InstData *data = INST_DATA(cl, obj);
42 IPTR ti_Data;
44 ENTER();
46 switch(msg->opg_AttrID)
48 case MUIA_TextEditor_CursorPosition:
50 UWORD xplace, yplace, cursor_width;
51 UWORD x = data->CPos_X;
52 struct line_node *line = data->actualline;
53 LONG line_nr = LineToVisual(line, data) - 1;
54 struct pos_info pos;
56 OffsetToLines(x, line, &pos, data);
58 // calculate the cursor width
59 // if it is set to 6 then we should find out how the width of the current char is
60 if(data->CursorWidth == 6)
61 cursor_width = TextLength(&data->tmprp, line->line.Contents[x] < ' ' ? (char *)" " : (char *)&line->line.Contents[x], 1);
62 else
63 cursor_width = data->CursorWidth;
65 xplace = data->xpos + TextLength(&data->tmprp, &line->line.Contents[x-pos.x], pos.x);
66 xplace += FlowSpace(line->line.Flow, line->line.Contents+pos.bytes, data);
67 yplace = data->ypos + (data->height * (line_nr + pos.lines - 1));
69 data->CursorPosition.MinX = xplace;
70 data->CursorPosition.MinY = yplace;
71 data->CursorPosition.MaxX = xplace + cursor_width - 1;
72 data->CursorPosition.MaxY = yplace + data->height - 1;
73 ti_Data = (IPTR)&data->CursorPosition;
75 break;
77 case MUIA_TextEditor_UndoAvailable:
78 ti_Data = data->undolevel > 0 && data->undocur > 0;
79 break;
81 case MUIA_TextEditor_RedoAvailable:
82 ti_Data = data->undolevel > 0 && data->undofill > data->undocur;
83 break;
85 case MUIA_TextEditor_ActiveObjectOnClick:
86 ti_Data = ((data->flags & FLG_ActiveOnClick) ? TRUE : FALSE);
87 break;
89 case MUIA_TextEditor_AutoClip:
90 ti_Data = ((data->flags & FLG_AutoClip) ? TRUE : FALSE);
91 break;
93 case MUIA_TextEditor_KeyUpFocus:
94 ti_Data = (IPTR)data->KeyUpFocus;
95 break;
97 case MUIA_Version:
98 ti_Data = LIB_VERSION;
99 break;
101 case MUIA_Revision:
102 ti_Data = LIB_REVISION;
103 break;
105 case MUIA_ControlChar:
106 ti_Data = (IPTR)data->CtrlChar;
107 break;
109 case MUIA_TextEditor_AreaMarked:
110 ti_Data = Enabled(data);
111 break;
112 case MUIA_TextEditor_CursorX:
113 ti_Data = data->CPos_X;
114 break;
115 case MUIA_TextEditor_CursorY:
116 ti_Data = LineNr(data->actualline, data)-1;
117 break;
118 case MUIA_TextEditor_ExportWrap:
119 ti_Data = data->ExportWrap;
120 break;
121 case MUIA_TextEditor_FixedFont:
122 ti_Data = data->use_fixedfont;
123 break;
124 case MUIA_TextEditor_Pen:
125 ti_Data = data->Pen;
126 break;
127 case MUIA_TextEditor_Flow:
128 ti_Data = data->Flow;
129 break;
130 case MUIA_TextEditor_Separator:
131 ti_Data = data->Separator;
132 break;
133 case MUIA_TextEditor_HasChanged:
134 ti_Data = data->HasChanged;
135 break;
136 case MUIA_TextEditor_HorizontalScroll:
137 ti_Data = ((data->flags & FLG_HScroll) ? TRUE : FALSE);
138 break;
139 case MUIA_TextEditor_ImportWrap:
140 ti_Data = data->ImportWrap;
141 break;
142 /* case MUIA_TextEditor_InsertMode:
143 ti_Data = data->InsertMode;
144 break;
146 case MUIA_TextEditor_Prop_Entries:
147 ti_Data = data->totallines;
148 break;
149 case MUIA_TextEditor_Prop_Visible:
150 ti_Data = data->maxlines;
151 break;
152 case MUIA_TextEditor_Prop_DeltaFactor:
153 ti_Data = data->height;
154 break;
155 case MUIA_TextEditor_Prop_First:
156 ti_Data = (data->visual_y-1)*data->height;
157 break;
158 case MUIA_TextEditor_ReadOnly:
159 ti_Data = ((data->flags & FLG_ReadOnly) ? TRUE : FALSE);
160 break;
161 case MUIA_TextEditor_Quiet:
162 ti_Data = ((data->flags & FLG_Quiet) ? TRUE : FALSE);
163 break;
164 case MUIA_TextEditor_StyleBold:
165 ti_Data = ((GetStyle(data->CPos_X, data->actualline) & BOLD) ? TRUE : FALSE);
166 break;
167 case MUIA_TextEditor_StyleItalic:
168 ti_Data = ((GetStyle(data->CPos_X, data->actualline) & ITALIC) ? TRUE : FALSE);
169 break;
170 case MUIA_TextEditor_StyleUnderline:
171 ti_Data = ((GetStyle(data->CPos_X, data->actualline) & UNDERLINE) ? TRUE : FALSE);
172 break;
173 case MUIA_TextEditor_TypeAndSpell:
174 ti_Data = data->TypeAndSpell;
175 break;
177 case MUIA_TextEditor_WrapBorder:
178 ti_Data = data->WrapBorder;
179 break;
181 case MUIA_TextEditor_WrapMode:
182 ti_Data = data->WrapMode;
183 break;
185 case MUIA_Font:
186 ti_Data = (IPTR)data->font;
187 break;
189 case MUIA_TextEditor_UndoLevels:
190 ti_Data = data->undolevel;
191 break;
193 default:
194 LEAVE();
195 return(DoSuperMethodA(cl, obj, (Msg)msg));
197 *msg->opg_Storage = ti_Data;
199 RETURN(TRUE);
200 return(TRUE);
203 IPTR Set(struct IClass *cl, Object *obj, struct opSet *msg)
205 struct InstData *data = INST_DATA(cl, obj);
206 struct TagItem *tags, *tag;
207 char *contents = NULL;
208 IPTR result = FALSE;
209 ULONG crsr_x = 0xffff, crsr_y = 0xffff;
211 ENTER();
213 if(data->shown && !(data->flags & FLG_Draw))
215 if((tag = FindTagItem(MUIA_Disabled, msg->ops_AttrList)))
217 if(tag->ti_Data)
218 data->flags |= FLG_Ghosted;
219 else data->flags &= ~FLG_Ghosted;
221 data->UpdateInfo = msg;
222 MUI_Redraw(obj, MADF_DRAWUPDATE);
224 RETURN((IPTR)data->UpdateInfo);
225 return((IPTR)data->UpdateInfo);
228 tags = msg->ops_AttrList;
229 while((tag = NextTagItem((APTR)&tags)))
231 ULONG ti_Data = tag->ti_Data;
233 switch(tag->ti_Tag)
235 case MUIA_ControlChar:
236 data->CtrlChar = (UBYTE)ti_Data;
237 break;
239 case MUIA_Disabled:
240 if(ti_Data)
241 data->flags |= FLG_Ghosted;
242 else
243 data->flags &= ~FLG_Ghosted;
245 // make sure an eventually existing slider is disabled as well
246 if(data->slider)
247 set(data->slider, MUIA_Disabled, ti_Data);
249 MUI_Redraw(obj, MADF_DRAWOBJECT);
250 break;
252 case MUIA_TextEditor_Rows:
253 data->Rows = ti_Data;
254 break;
256 case MUIA_TextEditor_Columns:
257 data->Columns = ti_Data;
258 break;
260 case MUIA_TextEditor_AutoClip:
261 if(ti_Data)
262 data->flags |= FLG_AutoClip;
263 else
264 data->flags &= ~FLG_AutoClip;
265 break;
267 case MUIA_TextEditor_ColorMap:
268 data->colormap = (ULONG *)ti_Data;
269 break;
270 case MUIA_TextEditor_InVirtualGroup:
271 if(ti_Data)
272 data->flags |= FLG_InVGrp;
273 else
274 data->flags &= ~FLG_InVGrp;
275 break;
277 case MUIA_TextEditor_CursorX:
278 if(!data->NoNotify)
279 crsr_x = ti_Data;
280 break;
282 case MUIA_TextEditor_CursorY:
283 if(!data->NoNotify)
284 crsr_y = ti_Data;
285 break;
287 case MUIA_TextEditor_Prop_Release:
288 data->smooth_wait = ti_Data;
289 break;
291 case MUIA_TextEditor_Prop_First:
293 if(((data->visual_y-1)*data->height+(data->realypos - data->ypos) != (LONG)ti_Data) && (data->shown))
295 LONG diff, smooth;
296 LONG lastpixel = ((data->visual_y-1)*data->height) + (data->realypos - data->ypos);
297 struct Hook *oldhook;
298 void *cliphandle;
300 diff = data->visual_y - ((ti_Data/data->height)+1);
302 data->visual_y = (ti_Data/data->height)+1;
303 smooth = ti_Data - lastpixel;
305 if(smooth > 0)
306 data->scr_direction = 1;
307 else
308 data->scr_direction = 0;
310 oldhook = InstallLayerHook(data->rport->Layer, LAYERS_NOBACKFILL);
311 cliphandle = MUI_AddClipping(muiRenderInfo(data->object), data->xpos, data->realypos, data->innerwidth, data->maxlines*data->height);
312 if(smooth > 0 && smooth < data->maxlines*data->height)
314 LONG line_nr;
316 ScrollRasterBF(data->rport, 0, smooth,
317 data->xpos, data->realypos,
318 data->xpos + data->innerwidth - 1,
319 data->realypos + (data->maxlines * data->height) - 1);
321 data->ypos = data->realypos - ti_Data%data->height;
322 line_nr = data->maxlines-(smooth/data->height)-1;
325 struct Layer *layer = data->rport->Layer;
327 if(layer->DamageList && layer->DamageList->RegionRectangle)
329 if(MUI_BeginRefresh(muiRenderInfo(data->object),0))
331 MUI_Redraw(data->object, MADF_DRAWOBJECT);
332 MUI_EndRefresh(muiRenderInfo(data->object), 0);
337 DumpText(data->visual_y+line_nr, line_nr, data->maxlines+1, FALSE, data);
339 else
341 if(smooth < 0 && -smooth < data->maxlines*data->height)
343 LONG lines;
345 ScrollRasterBF(data->rport, 0, smooth,
346 data->xpos, data->realypos,
347 data->xpos + data->innerwidth - 1,
348 data->realypos + (data->maxlines * data->height) - 1);
349 data->ypos = data->realypos - ti_Data%data->height;
350 lines = (-smooth/data->height)+2;
352 struct Layer *layer = data->rport->Layer;
354 if(layer->DamageList && layer->DamageList->RegionRectangle)
355 if(MUI_BeginRefresh(muiRenderInfo(data->object),0))
357 MUI_Redraw(data->object, MADF_DRAWOBJECT);
358 MUI_EndRefresh(muiRenderInfo(data->object), 0);
362 DumpText(data->visual_y, 0, lines, FALSE, data);
364 else
366 if(smooth)
367 DumpText(data->visual_y, 0, data->maxlines+1, FALSE, data);
370 MUI_RemoveClipping(muiRenderInfo(data->object), cliphandle);
371 InstallLayerHook(data->rport->Layer, oldhook);
373 if(!data->scrollaction)
375 RequestInput(data);
376 data->smooth_wait = 1;
377 data->scrollaction = TRUE;
380 SetAttrs(obj, MUIA_TextEditor_Prop_Entries,
381 ((data->totallines-(data->visual_y-1) < data->maxlines) ?
382 ((data->visual_y-1)+data->maxlines) :
383 ((data->maxlines > data->totallines) ?
384 data->maxlines :
385 data->totallines))
386 * data->height,
387 TAG_DONE);
389 break;
391 case MUIA_TextEditor_ReadOnly:
393 if(ti_Data)
395 SetCursor(data->CPos_X, data->actualline, FALSE, data);
396 data->flags |= FLG_ReadOnly;
398 // force the activeOnClick to be turned off
399 // in case the user explicitly sets the readonly object
400 data->flags &= ~FLG_ActiveOnClick;
402 // enable that the object will automatically get a border when
403 // the ActiveObjectOnClick option is active
404 _flags(obj) &= ~(1<<7);
406 else
408 data->flags &= ~FLG_ReadOnly;
409 if(data->shown)
411 if(data->flags & FLG_Active)
412 SetCursor(data->CPos_X, data->actualline, TRUE, data);
415 // disable that the object will automatically get a border when
416 // the ActiveObjectOnClick option is active
417 if((data->flags & FLG_ActiveOnClick) != 0)
418 _flags(obj) |= (1<<7);
421 break;
423 case MUIA_TextEditor_ActiveObjectOnClick:
425 if(ti_Data)
427 data->flags |= FLG_ActiveOnClick;
429 // disable that the object will automatically get a border when
430 // the ActiveObjectOnClick option is active
431 _flags(obj) |= (1<<7);
433 else
435 data->flags &= ~FLG_ActiveOnClick;
437 // enable that the object will automatically get a border when
438 // the ActiveObjectOnClick option is active
439 _flags(obj) &= ~(1<<7);
442 break;
444 case MUIA_TextEditor_PopWindow_Open:
446 if(ti_Data)
447 data->flags |= FLG_PopWindow;
448 else
449 data->flags &= ~FLG_PopWindow;
451 break;
453 case MUIA_TextEditor_Quiet:
454 if(ti_Data)
456 data->flags |= FLG_Quiet;
458 else
460 data->flags &= ~FLG_Quiet;
461 MUI_Redraw(obj, MADF_DRAWOBJECT);
462 if(data->maxlines > data->totallines)
463 set(data->object, MUIA_TextEditor_Prop_Entries, data->maxlines*data->height);
464 else
465 set(data->object, MUIA_TextEditor_Prop_Entries, data->totallines*data->height);
466 set(data->object, MUIA_TextEditor_Prop_First, (data->visual_y-1)*data->height);
468 break;
470 case MUIA_TextEditor_StyleBold:
471 AddStyle(&data->blockinfo, BOLD, ti_Data, data);
472 break;
474 case MUIA_TextEditor_StyleItalic:
475 AddStyle(&data->blockinfo, ITALIC, ti_Data, data);
476 break;
478 case MUIA_TextEditor_StyleUnderline:
479 AddStyle(&data->blockinfo, UNDERLINE, ti_Data, data);
480 break;
482 case MUIA_TextEditor_Pen:
483 if(!data->NoNotify)
485 data->Pen = ti_Data;
486 AddColor(&data->blockinfo, (UWORD)ti_Data, data);
487 data->HasChanged = TRUE;
489 break;
491 case MUIA_TextEditor_KeyUpFocus:
492 data->KeyUpFocus = (Object *)ti_Data;
493 break;
495 case MUIA_TextEditor_Slider:
497 if(!data->shown)
499 data->slider = (void *)ti_Data;
501 // disable the slider right away if the texteditor
502 // gadget is disabled as well.
503 if(data->flags & FLG_Ghosted)
504 set(data->slider, MUIA_Disabled, TRUE);
506 DoMethod(data->slider, MUIM_Notify,
507 MUIA_Prop_Release, MUIV_EveryTime,
508 obj, 3, MUIM_NoNotifySet, MUIA_TextEditor_Prop_Release, MUIV_TriggerValue);
509 DoMethod(data->slider, MUIM_Notify,
510 MUIA_Prop_First, MUIV_EveryTime,
511 obj, 3, MUIM_NoNotifySet, MUIA_TextEditor_Prop_First, MUIV_TriggerValue);
512 DoMethod(obj, MUIM_Notify,
513 MUIA_TextEditor_Prop_First, MUIV_EveryTime,
514 data->slider, 3, MUIM_NoNotifySet, MUIA_Prop_First, MUIV_TriggerValue);
515 DoMethod(obj, MUIM_Notify,
516 MUIA_TextEditor_Prop_Entries, MUIV_EveryTime,
517 data->slider, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
518 DoMethod(obj, MUIM_Notify,
519 MUIA_TextEditor_Prop_Visible, MUIV_EveryTime,
520 data->slider, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
521 DoMethod(obj, MUIM_Notify,
522 MUIA_TextEditor_Prop_DeltaFactor, MUIV_EveryTime,
523 data->slider, 3, MUIM_NoNotifySet, MUIA_Prop_DeltaFactor, MUIV_TriggerValue);
526 break;
528 case MUIA_TextEditor_FixedFont:
530 if(!data->shown)
532 if(ti_Data)
534 data->font = data->fixedfont;
535 data->use_fixedfont = TRUE;
537 else
539 data->font = data->normalfont;
540 data->use_fixedfont = FALSE;
543 // now we check whether we have a valid font or not
544 // and if not we take the default one of our muiAreaData
545 if(data->font == NULL)
546 data->font = muiAreaData(obj)->mad_Font;
548 break;
550 case MUIA_TextEditor_DoubleClickHook:
551 data->DoubleClickHook = (struct Hook *)ti_Data;
552 break;
554 case MUIA_TextEditor_HasChanged:
555 data->HasChanged = ti_Data;
556 if(!ti_Data)
557 data->flags &= ~FLG_UndoLost;
558 break;
560 case MUIA_TextEditor_HorizontalScroll:
561 if(ti_Data)
562 data->flags |= FLG_HScroll;
563 else
564 data->flags &= ~FLG_HScroll;
565 break;
567 case MUIA_TextEditor_Contents:
568 contents = (char *)ti_Data;
569 break;
571 case MUIA_TextEditor_ImportHook:
572 switch(ti_Data)
574 case MUIV_TextEditor_ImportHook_Plain:
575 data->ImportHook = &ImPlainHook;
576 break;
577 case MUIV_TextEditor_ImportHook_EMail:
578 data->ImportHook = &ImEMailHook;
579 break;
580 case MUIV_TextEditor_ImportHook_MIME:
581 data->ImportHook = &ImMIMEHook;
582 break;
583 case MUIV_TextEditor_ImportHook_MIMEQuoted:
584 data->ImportHook = &ImMIMEQuoteHook;
585 break;
586 default:
587 data->ImportHook = (struct Hook *)ti_Data;
589 break;
591 case MUIA_TextEditor_ImportWrap:
592 data->ImportWrap = ti_Data;
593 break;
595 case MUIA_TextEditor_ExportHook:
597 switch(ti_Data)
599 case MUIV_TextEditor_ExportHook_Plain:
600 data->ExportHook = &ExportHookPlain;
601 break;
603 case MUIV_TextEditor_ExportHook_EMail:
604 data->ExportHook = &ExportHookEMail;
605 break;
607 case MUIV_TextEditor_ExportHook_NoStyle:
608 data->ExportHook = &ExportHookNoStyle;
609 break;
611 default:
612 data->ExportHook = (struct Hook *)ti_Data;
615 break;
617 case MUIA_TextEditor_ExportWrap:
618 data->ExportWrap = ti_Data;
619 break;
621 case MUIA_TextEditor_Flow:
622 if(!data->NoNotify)
624 LONG start, lines = 0;
626 data->Flow = ti_Data;
627 if(Enabled(data))
629 struct marking newblock;
630 struct line_node *startline;
632 NiceBlock(&data->blockinfo, &newblock);
633 startline = newblock.startline;
634 start = LineToVisual(startline, data);
636 do {
637 lines += startline->visual;
638 startline->line.Flow = ti_Data;
639 startline = startline->next;
641 while(startline != newblock.stopline->next);
643 else
645 start = LineToVisual(data->actualline, data);
646 lines = data->actualline->visual;
647 data->actualline->line.Flow = ti_Data;
648 data->pixel_x = 0;
650 if(start < 1)
651 start = 1;
652 if(start-1+lines > data->maxlines)
653 lines = data->maxlines-(start-1);
654 DumpText(data->visual_y+start-1, start-1, start-1+lines, TRUE, data);
655 data->HasChanged = TRUE;
657 break;
659 case MUIA_TextEditor_WrapBorder:
661 if(data->WrapBorder != ti_Data)
663 data->WrapBorder = ti_Data;
664 ResetDisplay(data);
667 break;
669 case MUIA_TextEditor_WrapMode:
671 if(data->WrapMode != ti_Data)
673 data->WrapMode = ti_Data;
674 ResetDisplay(data);
677 break;
679 case MUIA_TextEditor_TypeAndSpell:
680 data->TypeAndSpell = ti_Data;
681 break;
683 case MUIA_TextEditor_UndoLevels:
684 ResizeUndoBuffer(data, ti_Data);
685 data->userUndoSize = TRUE;
686 break;
690 if(contents)
692 struct line_node *newcontents;
694 if((newcontents = ImportText(contents, data, data->ImportHook, data->ImportWrap)))
696 FreeTextMem(data->firstline, data);
697 data->firstline = newcontents;
698 ResetDisplay(data);
699 ResetUndoBuffer(data);
700 result = TRUE;
704 if(crsr_x != 0xffff || crsr_y != 0xffff)
706 SetCursor(data->CPos_X, data->actualline, FALSE, data);
708 if(crsr_y != 0xffff)
710 data->actualline = LineNode(crsr_y+1, data);
711 if(data->actualline->line.Length < data->CPos_X)
712 data->CPos_X = data->actualline->line.Length-1;
714 if(crsr_x != 0xffff)
716 data->CPos_X = (data->actualline->line.Length > (ULONG)crsr_x) ? (UWORD)crsr_x : (UWORD)data->actualline->line.Length-1;
719 ScrollIntoDisplay(data);
720 SetCursor(data->CPos_X, data->actualline, TRUE, data);
722 data->pixel_x = 0;
723 result = TRUE;
726 RETURN(result);
727 return result;