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 ***************************************************************************/
25 #include <exec/memory.h>
26 #include <libraries/mui.h>
27 #include <clib/alib_protos.h>
28 #include <proto/muimaster.h>
29 #include <proto/intuition.h>
30 #include <proto/diskfont.h>
31 #include <proto/graphics.h>
32 #include <proto/keymap.h>
33 #include <proto/exec.h>
34 #include <proto/dos.h>
36 #include "TextEditor_mcp.h"
41 static struct TextFont
*GetFont(UNUSED
struct InstData
*data
, void *obj
, long attr
)
43 struct TextFont
*font
= NULL
;
48 if(DoMethod(obj
, MUIM_GetConfigItem
, attr
, &setting
) && setting
!= NULL
)
53 fontnameLen
= strlen(setting
)+6;
54 if((fontname
= AllocVecShared(fontnameLen
, MEMF_CLEAR
)) != NULL
)
57 struct TextAttr textAttr
;
59 textAttr
.ta_Name
= fontname
;
60 textAttr
.ta_YSize
= 8;
61 textAttr
.ta_Style
= FS_NORMAL
;
62 textAttr
.ta_Flags
= 0;
64 strlcpy(fontname
, setting
, fontnameLen
);
65 if((sizePtr
= strchr(fontname
, '/')) != NULL
)
69 StrToLong(sizePtr
+ 1, &size
);
70 strlcpy(sizePtr
, ".font", fontnameLen
-(sizePtr
-fontname
));
71 textAttr
.ta_YSize
= size
;
74 font
= OpenDiskFont(&textAttr
);
86 static void SetCol(struct InstData
*data
, void *obj
, long item
, ULONG
*storage
, long bit
)
88 struct MUI_PenSpec
*spec
;
92 if(DoMethod(obj
, MUIM_GetConfigItem
, item
, &spec
))
94 *storage
= MUI_ObtainPen(muiRenderInfo(obj
), spec
, 0L);
95 data
->allocatedpens
|= 1<<bit
;
98 W(DBF_STARTUP
, "couldn't get config item: 0x%08lx", item
);
105 void InitConfig(struct IClass
*cl
, Object
*obj
)
107 struct InstData
*data
= INST_DATA(cl
, obj
);
109 BOOL loadDefaultKeys
= FALSE
;
110 LONG oldTabSize
= data
->TabSize
;
114 data
->allocatedpens
= 0;
115 data
->textcolor
= _pens(obj
)[MPEN_TEXT
];
116 data
->backgroundcolor
= _pens(obj
)[MPEN_BACKGROUND
];
117 data
->highlightcolor
= _pens(obj
)[MPEN_SHINE
];
118 data
->cursorcolor
= _pens(obj
)[MPEN_SHINE
];
119 data
->cursortextcolor
= _pens(obj
)[MPEN_TEXT
];
120 data
->markedcolor
= _pens(obj
)[MPEN_FILL
];
121 data
->separatorshine
= _pens(obj
)[MPEN_HALFSHINE
];
122 data
->separatorshadow
= _pens(obj
)[MPEN_HALFSHADOW
];
123 data
->inactivecolor
= _pens(obj
)[MPEN_HALFSHADOW
];
125 SetCol(data
, obj
, MUICFG_TextEditor_TextColor
, &data
->textcolor
, 0);
126 SetCol(data
, obj
, MUICFG_TextEditor_CursorColor
, &data
->cursorcolor
, 1);
127 SetCol(data
, obj
, MUICFG_TextEditor_CursorTextColor
, &data
->cursortextcolor
, 2);
128 SetCol(data
, obj
, MUICFG_TextEditor_HighlightColor
, &data
->highlightcolor
, 3);
129 SetCol(data
, obj
, MUICFG_TextEditor_MarkedColor
, &data
->markedcolor
, 4);
130 SetCol(data
, obj
, MUICFG_TextEditor_SeparatorShine
, &data
->separatorshine
, 5);
131 SetCol(data
, obj
, MUICFG_TextEditor_SeparatorShadow
, &data
->separatorshadow
, 6);
132 SetCol(data
, obj
, MUICFG_TextEditor_InactiveColor
, &data
->inactivecolor
, 7);
134 if(isFlagClear(data
->flags
, FLG_OwnBackground
))
136 IPTR background
= MUII_BACKGROUND
;
138 data
->backgroundcolor
= 0;
140 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_Background
, &setting
) && setting
!= 0)
142 char *bg_setting
= (char *)setting
;
144 if(bg_setting
[0] == '2' && bg_setting
[1] == ':' )
146 struct MUI_PenSpec
*spec
= (struct MUI_PenSpec
*)(bg_setting
+2);
148 data
->backgroundcolor
= MUI_ObtainPen(muiRenderInfo(obj
), spec
, 0L);
149 data
->allocatedpens
|= 1<<8;
152 background
= (IPTR
)setting
;
154 set(obj
, MUIA_Background
, background
);
157 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_TabSize
, &setting
))
159 ULONG size
= MINMAX(2, *(ULONG
*)setting
, 12);
161 // use the configured value only if the TAB size is not yet overridden
162 if(isFlagClear(data
->flags
, FLG_ForcedTabSize
))
163 data
->TabSize
= size
;
165 // remember the configured value in case the TAB size is being reset to the default value
166 data
->GlobalTabSize
= size
;
170 // assume the default value for both
172 data
->GlobalTabSize
= 4;
175 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_CursorWidth
, &setting
))
176 data
->CursorWidth
= MINMAX(1, *(long *)setting
, 6);
178 data
->CursorWidth
= 6;
180 data
->normalfont
= GetFont(data
, obj
, MUICFG_TextEditor_NormalFont
);
181 data
->fixedfont
= GetFont(data
, obj
, MUICFG_TextEditor_FixedFont
);
182 data
->font
= (data
->use_fixedfont
== TRUE
) ? data
->fixedfont
: data
->normalfont
;
184 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_BlockQual
, &setting
))
186 switch(*(LONG
*)setting
)
190 data
->blockqual
= IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
;
193 data
->blockqual
= IEQUALIFIER_CONTROL
;
196 data
->blockqual
= IEQUALIFIER_LALT
| IEQUALIFIER_RALT
;
204 data
->blockqual
= IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
;
206 data
->BlinkSpeed
= FALSE
;
207 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_BlinkSpeed
, &setting
))
209 if(*(LONG
*)setting
!= 0)
211 data
->blinkhandler
.ihn_Object
= obj
;
212 data
->blinkhandler
.ihn_Millis
= MINMAX(1, *(LONG
*)setting
, 20)*25;
213 data
->blinkhandler
.ihn_Method
= MUIM_TextEditor_ToggleCursor
;
214 data
->blinkhandler
.ihn_Flags
= MUIIHNF_TIMER
;
215 data
->BlinkSpeed
= 1;
219 if(isFlagClear(data
->flags
, FLG_OwnFrame
))
221 if(MUIMasterBase
->lib_Version
>= 20)
222 set(obj
, MUIA_Frame
, DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_Frame
, &setting
) ? (STRPTR
)setting
: (STRPTR
)"302200");
224 set(obj
, MUIA_Frame
, MUIV_Frame_String
);
227 data
->TypeAndSpell
= FALSE
;
228 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_TypeNSpell
, &setting
))
231 data
->TypeAndSpell
= TRUE
;
232 set(obj
, MUIA_TextEditor_TypeAndSpell
, data
->TypeAndSpell
);
235 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_CheckWord
, &setting
))
238 setFlag(data
->flags
, FLG_CheckWords
);
240 clearFlag(data
->flags
, FLG_CheckWords
);
243 data
->Flow
= data
->actualline
->line
.Flow
;
244 data
->Pen
= GetColor(data
->CPos_X
, data
->actualline
);
246 if(isFlagClear(data
->flags
, FLG_FirstInit
))
248 setFlag(data
->flags
, FLG_FirstInit
);
249 data
->NoNotify
= TRUE
;
251 MUIA_FillArea
, FALSE
,
252 MUIA_TextEditor_Flow
, data
->Flow
,
253 MUIA_TextEditor_Pen
, data
->Pen
,
254 MUIA_TextEditor_AreaMarked
, FALSE
,
255 MUIA_TextEditor_UndoAvailable
, FALSE
,
256 MUIA_TextEditor_RedoAvailable
, FALSE
,
257 MUIA_TextEditor_HasChanged
, FALSE
,
259 data
->NoNotify
= FALSE
;
267 setting
= (long)&lort
;
268 DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_Smooth
, &setting
);
269 if(data
->slider
!= NULL
)
270 set(data
->slider
, MUIA_Prop_DoSmooth
, *(long *)setting
);
273 data
->selectPointer
= TRUE
;
274 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_SelectPointer
, &setting
))
276 if(*(long *)setting
== 0)
277 data
->selectPointer
= FALSE
;
280 data
->inactiveCursor
= TRUE
;
281 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_InactiveCursor
, &setting
))
283 if(*(long *)setting
== 0)
284 data
->inactiveCursor
= FALSE
;
290 // get the saved undo size only if it was not yet set by the application
291 if(data
->userUndoBufferSize
== FALSE
)
295 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_UndoSize
, &setting
))
297 undoSteps
= *(long *)setting
;
299 // constrain the number of undo levels only if undo is enabled
301 undoSteps
= MAX(undoSteps
, 20);
305 undoSteps
= data
->maxUndoSteps
;
307 ResizeUndoBuffer(data
, undoSteps
);
310 data
->LookupSpawn
= FALSE
;
311 data
->LookupCmd
[0] = '\0';
312 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_LookupCmd
, &setting
))
314 data
->LookupSpawn
= (BOOL
)*(ULONG
*)setting
;
315 strlcpy(data
->LookupCmd
, (char *)setting
+4, sizeof(data
->LookupCmd
));
318 data
->SuggestSpawn
= TRUE
;
319 strlcpy(data
->SuggestCmd
, "\"Open('f', 'T:Matches', 'W');WriteLn('f', '%s');Close('f')\"", sizeof(data
->SuggestCmd
));
320 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_SuggestCmd
, &setting
))
322 data
->SuggestSpawn
= (BOOL
)*(ULONG
*)setting
;
323 strlcpy(data
->SuggestCmd
, (char *)setting
+4, sizeof(data
->SuggestCmd
));
326 if(DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_ConfigVersion
, &setting
))
328 if(*(ULONG
*)setting
!= CONFIG_VERSION
)
330 if(MUI_Request(_app(obj
), NULL
, 0L, "TextEditor.mcc Warning", "Ok|Abort",
331 "Your current keybindings setup of TextEditor.mcc\n"
332 "was found to be incompatible with this version of\n"
335 "The keybindings of this object will be temporarly\n"
336 "set to the default. Please visit the MUI preferences\n"
337 "of TextEditor.mcc to permanently update the keybindings.") == 1)
339 loadDefaultKeys
= TRUE
;
345 struct te_key
*userkeys
;
350 if(loadDefaultKeys
== TRUE
|| !DoMethod(obj
, MUIM_GetConfigItem
, MUICFG_TextEditor_Keybindings
, &setting
) || setting
== 0)
351 userkeys
= (struct te_key
*)default_keybindings
;
353 userkeys
= (struct te_key
*)setting
;
355 while((WORD
)userkeys
[count
].code
!= -1)
358 // now we calculate the memory size
359 size
= (count
+1)*sizeof(struct te_key
);
361 if((data
->RawkeyBindings
= AllocVecPooled(data
->mypool
, size
)) != NULL
)
364 struct te_key
*mykeys
= data
->RawkeyBindings
;
366 memcpy(mykeys
, userkeys
, size
);
368 for(i
=0; i
< count
&& (WORD
)mykeys
[i
].code
!= -1; i
++)
370 struct te_key
*curKey
= &mykeys
[i
];
372 //D(DBF_STARTUP, "checking curKey[%d]: %08lx", i, curKey);
374 if(curKey
->code
>= 500)
377 char code
= curKey
->code
-500;
379 MapANSI(&code
, 1, RAW
, 1, NULL
);
381 curKey
->code
= RAW
[0];
382 curKey
->qual
|= RAW
[1];
384 if(RAW
[0] == 67 && isFlagClear(curKey
->qual
, IEQUALIFIER_NUMERICPAD
))
393 if(data
->TabSize
!= oldTabSize
)
395 // reimport the current text if the TAB size has changed
396 ReimportText(cl
, obj
);
404 void FreeConfig(struct IClass
*cl
, Object
*obj
)
406 struct InstData
*data
= INST_DATA(cl
, obj
);
410 if(data
->RawkeyBindings
!= NULL
)
411 FreeVecPooled(data
->mypool
, data
->RawkeyBindings
);
413 if(data
->allocatedpens
& (1<<0))
414 MUI_ReleasePen(muiRenderInfo(obj
), data
->textcolor
);
415 if(data
->allocatedpens
& (1<<1))
416 MUI_ReleasePen(muiRenderInfo(obj
), data
->cursorcolor
);
417 if(data
->allocatedpens
& (1<<2))
418 MUI_ReleasePen(muiRenderInfo(obj
), data
->cursortextcolor
);
419 if(data
->allocatedpens
& (1<<3))
420 MUI_ReleasePen(muiRenderInfo(obj
), data
->highlightcolor
);
421 if(data
->allocatedpens
& (1<<4))
422 MUI_ReleasePen(muiRenderInfo(obj
), data
->markedcolor
);
423 if(data
->allocatedpens
& (1<<5))
424 MUI_ReleasePen(muiRenderInfo(obj
), data
->separatorshine
);
425 if(data
->allocatedpens
& (1<<6))
426 MUI_ReleasePen(muiRenderInfo(obj
), data
->separatorshadow
);
427 if(data
->allocatedpens
& (1<<7))
428 MUI_ReleasePen(muiRenderInfo(obj
), data
->inactivecolor
);
429 if(data
->allocatedpens
& (1<<8))
430 MUI_ReleasePen(muiRenderInfo(obj
), data
->backgroundcolor
);
432 if(data
->normalfont
!= NULL
)
433 CloseFont(data
->normalfont
);
434 if(data
->fixedfont
!= NULL
)
435 CloseFont(data
->fixedfont
);
437 if(data
->BlinkSpeed
== 2)
439 DoMethod(_app(data
->object
), MUIM_Application_RemInputHandler
, &data
->blinkhandler
);
440 data
->BlinkSpeed
= 1;