revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / zune / texteditor / mcc / PrintLineWithStyles.c
blob50f6cc108afb1f98a1c032f234001076cc601f9a
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 #if defined(__amigaos4__)
24 #include <hardware/blit.h>
25 #endif
27 #include <graphics/gfxmacros.h>
28 #include <graphics/text.h>
29 #include <clib/alib_protos.h>
30 #include <proto/graphics.h>
31 #include <proto/intuition.h>
33 #include "private.h"
34 #include "Debug.h"
36 /// ConvertStyle()
37 ULONG ConvertStyle(UWORD style)
39 ULONG result = FS_NORMAL;
41 ENTER();
43 if(isFlagSet(style, BOLD))
44 setFlag(result, FSF_BOLD);
45 if(isFlagSet(style, ITALIC))
46 setFlag(result, FSF_ITALIC);
47 if(isFlagSet(style, UNDERLINE))
48 setFlag(result, FSF_UNDERLINED);
50 RETURN(result);
51 return(result);
54 ///
55 /// ConvertPen()
56 ULONG ConvertPen(struct InstData *data, UWORD color, BOOL highlight)
58 ULONG pen;
60 ENTER();
62 if(color != 0)
64 if(data->colormap != NULL)
65 pen = MUIPEN(data->colormap[color-1]);
66 else if(color <= 8)
67 pen = _pens(data->object)[color-1];
68 else
69 pen = color-9;
71 else
73 if(highlight == TRUE)
74 pen = MUIPEN(data->highlightcolor);
75 else
76 pen = MUIPEN(data->textcolor);
79 RETURN(pen);
80 return pen;
83 ///
84 /// DrawSeparator()
85 void DrawSeparator(struct InstData *data, struct RastPort *rp, LONG X, LONG Y, LONG Width, LONG Height)
87 ENTER();
89 if(Width > 3*Height)
91 SetAPen(rp, MUIPEN(data->separatorshadow));
92 RectFill(rp, X, Y, X+Width-2, Y);
93 RectFill(rp, X, Y, X, Y+Height);
95 SetAPen(rp, MUIPEN(data->separatorshine));
96 RectFill(rp, X+1, Y+Height, X+Width-1, Y+Height);
97 RectFill(rp, X+Width-1, Y, X+Width-1, Y+Height);
100 LEAVE();
104 /// PrintLine()
105 LONG PrintLine(struct InstData *data, LONG x, struct line_node *line, LONG line_nr, BOOL doublebuffer)
107 STRPTR text = line->line.Contents;
108 LONG length;
109 struct RastPort *rp = &data->doublerp;
111 ENTER();
113 length = LineCharsWidth(data, text+x);
115 if(doublebuffer == FALSE)
116 rp = &data->copyrp;
118 if(line_nr > 0 && data->update == TRUE && isFlagClear(data->flags, FLG_Quiet) && data->rport != NULL && data->shown == TRUE)
120 LONG c_length = length;
121 LONG startx = 0, stopx = 0;
122 LONG starty = 0, xoffset = 0;
123 LONG flow = 0;
124 LONG maxwidth;
125 struct LineStyle *styles = line->line.Styles;
126 struct LineColor *colors = line->line.Colors;
127 struct marking block;
128 BOOL cursor = FALSE;
130 if(line->line.Highlight == TRUE && x == 0 && line->line.Length == 1)
131 line->line.Highlight = FALSE;
133 if(doublebuffer == FALSE)
135 starty = data->ypos+(data->fontheight * (line_nr-1));
136 xoffset = _mleft(data->object);
139 flow = FlowSpace(data, line->line.Flow, text+x);
140 Move(rp, xoffset+flow, starty+rp->TxBaseline);
142 if(Enabled(data))
144 struct line_node *blkline;
146 NiceBlock(&data->blockinfo, &block);
148 blkline = GetNextLine(block.startline);
150 if(block.startline == block.stopline)
152 if(block.startline == line)
154 startx = block.startx;
155 stopx = block.stopx;
158 else
160 if(block.startline == line)
162 startx = block.startx;
163 stopx = line->line.Length;
165 else
167 if(block.stopline == line)
169 stopx = block.stopx;
171 else
173 while((blkline != block.stopline) && (!stopx))
175 if(blkline == line)
177 stopx = line->line.Length;
179 blkline = GetNextLine(blkline);
187 LONG blockstart = 0;
188 LONG blockwidth = 0;
189 struct RastPort *old = _rp(data->object);
191 if(startx < x+c_length && stopx > x)
193 if(startx > x)
194 blockstart = TextLengthNew(&data->tmprp, text+x, startx-x, data->TabSizePixels);
195 else
196 startx = x;
198 blockwidth = ((stopx >= c_length+x) ? _mwidth(data->object)-(blockstart+flow) : TextLengthNew(&data->tmprp, text+startx, stopx-startx, data->TabSizePixels));
200 else if(isFlagClear(data->flags, FLG_ReadOnly) &&
201 isFlagClear(data->flags, FLG_Ghosted) &&
202 line == data->actualline &&
203 data->CPos_X >= x &&
204 data->CPos_X < x+c_length &&
205 !Enabled(data) &&
206 (isFlagSet(data->flags, FLG_Active) || data->inactiveCursor == TRUE))
208 cursor = TRUE;
209 blockstart = TextLengthNew(&data->tmprp, text+x, data->CPos_X-x, data->TabSizePixels);
211 // calculate the cursor width
212 // if it is set to 6 then we should find out how the width of the current char is
213 if(data->CursorWidth == 6)
214 blockwidth = TextLengthNew(&data->tmprp, (text[data->CPos_X] < ' ') ? (char *)" " : (char *)&text[data->CPos_X], 1, data->TabSizePixels);
215 else
216 blockwidth = data->CursorWidth;
219 SetDrMd(rp, JAM1);
220 _rp(data->object) = rp;
222 // clear the background first
223 DoMethod(data->object, MUIM_DrawBackground, xoffset, starty,
224 flow+blockstart, data->fontheight,
225 isFlagSet(data->flags, FLG_InVGrp) ? 0 : _mleft(data->object),
226 isFlagSet(data->flags, FLG_InVGrp) ? data->fontheight*(data->visual_y+line_nr-2) : _mtop(data->object)+data->fontheight * (data->visual_y+line_nr-2),
229 if(blockwidth)
231 ULONG color;
233 // in case the gadget is in inactive state we use a different background
234 // color for our selected area
235 if(isFlagClear(data->flags, FLG_Active) &&
236 isFlagClear(data->flags, FLG_Activated) &&
237 isFlagSet(data->flags, FLG_ActiveOnClick))
239 color = MUIPEN(data->inactivecolor);
241 else
242 color = MUIPEN(data->markedcolor);
244 // if selectmode == 2 then a whole line should be drawn as being marked, so
245 // we have to start at xoffset instead of xoffset+flow+blockstart.
246 // Please note that the second part of the following "empiric" evaluation should
247 // prevent that centered or right aligned lines are not correctly marked right
248 // from the beginning of the line. However, it seems to be not cover 100% of all different
249 // cases so that the evaluation if a line should be completely marked should be probably
250 // moved elsewhere in future.
251 if(data->selectmode == 2 ||
252 (flow && data->selectmode != 1 && startx-x == 0 && cursor == FALSE &&
253 ((data->blockinfo.startline != data->blockinfo.stopline) || x > 0)))
255 LONG right = MIN(_mright(data->object), xoffset+flow+blockwidth-1);
257 SetAPen(rp, color);
258 RectFill(rp, xoffset, starty, right, starty+data->fontheight-1);
260 else
262 LONG right = MIN(_mright(data->object), xoffset+flow+blockstart+blockwidth-1);
264 SetAPen(rp, cursor ? data->cursorcolor : color);
265 RectFill(rp, xoffset+flow+blockstart, starty, right, starty+data->fontheight-1);
267 // if the gadget is in inactive state we just draw a skeleton cursor instead
268 if(cursor == TRUE &&
269 isFlagClear(data->flags, FLG_Active) &&
270 isFlagClear(data->flags, FLG_Activated))
272 DoMethod(data->object, MUIM_DrawBackground, xoffset+flow+blockstart+1, starty+1,
273 blockwidth-2, data->fontheight-2,
274 isFlagSet(data->flags, FLG_InVGrp) ? 0 : _mleft(data->object),
275 isFlagSet(data->flags, FLG_InVGrp) ? data->fontheight*(data->visual_y+line_nr-2) : _mtop(data->object)+data->fontheight * (data->visual_y+line_nr-2),
283 LONG x_start = xoffset+blockstart+blockwidth,
284 y_start = starty,
285 x_width = _mwidth(data->object)-(blockstart+blockwidth),
286 y_width = data->fontheight,
287 x_ptrn = blockstart+blockwidth,
288 y_ptrn = data->fontheight*(data->visual_y+line_nr-2);
290 if(blockwidth)
292 x_start += flow;
293 x_width -= flow;
294 x_ptrn += flow;
296 if(isFlagClear(data->flags, FLG_InVGrp))
298 x_ptrn += _mleft(data->object);
299 y_ptrn += _mtop(data->object);
302 DoMethod(data->object, MUIM_DrawBackground, x_start, y_start, x_width, y_width, x_ptrn, y_ptrn, 0);
304 _rp(data->object) = old;
307 if(doublebuffer == FALSE)
308 AddClipping(data);
310 SetAPen(rp, line->line.Highlight ? MUIPEN(data->highlightcolor) : MUIPEN(data->textcolor));
312 maxwidth = _mwidth(data->object) - flow;
313 while(c_length > 0)
315 LONG p_length = c_length;
316 struct TextExtent te;
318 SetSoftStyle(rp, ConvertStyle(GetStyle(x, line)), AskSoftStyle(rp));
319 if(styles != NULL)
321 while(styles->column-1 <= x)
322 styles++;
324 if(styles->column-x-1 < p_length)
325 p_length = styles->column-x-1;
328 if(colors != NULL)
330 while(colors->column-1 <= x)
332 SetAPen(rp, ConvertPen(data, colors->color, line->line.Highlight));
333 colors++;
336 if(colors->column-x-1 < p_length)
337 p_length = colors->column-x-1;
340 /* if(stopx)
342 if((startx > x) && (startx-x < p_length))
344 p_length = startx-x;
345 SetAPen(rp, 3);
347 else
349 if((stopx > x) && (stopx-x < p_length))
351 p_length = stopx-x;
352 SetAPen(rp, 4);
354 else
355 SetAPen(rp, line->color ? MUIPEN(data->highlightcolor) : MUIPEN(data->textcolor));
360 // check if there is space left to print some text
361 if(maxwidth > 0)
363 // calculate how many character really fit in the remaining space
364 ULONG fitting = TextFitNew(rp, text+x, p_length, &te, NULL, 1, maxwidth, data->fontheight, data->TabSizePixels);
366 if(fitting > 0)
368 if(text[x+fitting-1] < ' ')
369 TextNew(rp, text+x, fitting-1, data->TabSizePixels);
370 else
371 TextNew(rp, text+x, fitting, data->TabSizePixels);
374 // adjust the available horizontal pixel space
375 maxwidth -= te.te_Width;
378 // add the length calculated before no matter how many character really fitted
379 x += p_length;
380 c_length -= p_length;
382 SetSoftStyle(rp, FS_NORMAL, AskSoftStyle(rp));
384 if(line->line.Separator != LNSF_None)
386 LONG LeftX, LeftWidth;
387 LONG RightX, RightWidth;
388 LONG Y, Height;
390 LeftX = xoffset;
391 LeftWidth = flow-3;
392 RightX = rp->cp_x+3;
393 RightWidth = xoffset+_mwidth(data->object) - RightX;
394 Y = starty;
395 Height = isFlagSet(line->line.Separator, LNSF_Thick) ? 2 : 1;
397 if(isFlagSet(line->line.Separator, LNSF_Middle))
398 Y += (data->fontheight/2)-Height;
399 else if(isFlagSet(line->line.Separator, LNSF_Bottom))
400 Y += data->fontheight-(2*Height);
402 if(isFlagSet(line->line.Separator, LNSF_StrikeThru) || line->line.Length == 1)
404 LeftWidth = _mwidth(data->object);
406 else
408 DrawSeparator(data, rp, RightX, Y, RightWidth, Height);
410 DrawSeparator(data, rp, LeftX, Y, LeftWidth, Height);
414 if(isFlagSet(data->flags, FLG_Ghosted) && isFlagClear(data->flags, FLG_MUI4))
416 UWORD newPattern[] = {0x1111, 0x4444};
418 if(doublebuffer == TRUE)
420 ULONG ptrn1 = 0x11111111UL;
421 ULONG ptrn2 = 0x44444444UL;
423 ptrn1 = ptrn1>>((_mleft(data->object)-xoffset)%16);
424 ptrn2 = ptrn2>>((_mleft(data->object)-xoffset)%16);
426 if((data->fontheight*(data->visual_y+line_nr-2))%2 == 0)
428 newPattern[0] = ptrn2;
429 newPattern[1] = ptrn1;
431 else
433 newPattern[0] = ptrn1;
434 newPattern[1] = ptrn2;
437 else
439 if((data->fontheight*(data->visual_y-1))%2 == 0)
441 newPattern[0] = 0x4444;
442 newPattern[1] = 0x1111;
446 SetDrMd(rp, JAM1);
447 SetAPen(rp, _pens(data->object)[MPEN_SHADOW]);
448 SetAfPt(rp, newPattern, 1);
449 RectFill(rp, xoffset, starty, xoffset+_mwidth(data->object)-1, starty+data->fontheight-1);
450 SetAfPt(rp, NULL, (UBYTE)-1);
453 if(doublebuffer == FALSE)
454 RemoveClipping(data);
455 else
457 if(line_nr == 1)
459 BltBitMapRastPort(rp->BitMap, xoffset, _mtop(data->object)-data->ypos, data->rport, _mleft(data->object), _mtop(data->object)+(data->fontheight * (line_nr-1)), _mwidth(data->object), data->fontheight-(_mtop(data->object)-data->ypos), (ABC|ABNC));
461 else
463 if(line_nr == data->maxlines+1)
465 if(_mtop(data->object) != data->ypos)
467 BltBitMapRastPort(rp->BitMap, xoffset, 0, data->rport, _mleft(data->object), data->ypos+(data->fontheight * (line_nr-1)), _mwidth(data->object), _mtop(data->object)-data->ypos, (ABC|ABNC));
470 else
472 BltBitMapRastPort(rp->BitMap, xoffset, 0, data->rport, _mleft(data->object), data->ypos+(data->fontheight * (line_nr-1)), _mwidth(data->object), data->fontheight, (ABC|ABNC));
478 if(isFlagSet(data->flags, FLG_HScroll))
479 length = line->line.Length;
481 RETURN(length);
482 return(length);