/* ------------------------------------ * * Functions which updates the display * * ------------------------------------ */ void OptimizedPrint(LONG x, struct line_node *line, LONG line_nr, LONG width, struct InstData *data) { ENTER(); do { LONG twidth; twidth = PrintLine(x, line, line_nr, TRUE, data); line_nr++; if(twidth != width && x+twidth < (LONG)line->line.Length && line_nr <= data->maxlines) { x += twidth; width = LineCharsWidth(line->line.Contents+x+width, data) + width - twidth; } else break; } while(TRUE); LEAVE(); }
LONG PrintLine(LONG x, struct line_node *line, LONG line_nr, BOOL doublebuffer, struct InstData *data) { STRPTR text = line->line.Contents; LONG length; struct RastPort *rp = &data->doublerp; ENTER(); length = LineCharsWidth(text+x, data); if(doublebuffer == FALSE) rp = &data->copyrp; if((line_nr > 0) && (data->update) && !(data->flags & FLG_Quiet) && data->rport != NULL && data->shown == TRUE) { LONG c_length = length; LONG startx = 0, stopx = 0; LONG starty = 0, xoffset = ((data->height-rp->TxBaseline+1)>>1)+1; LONG flow = 0; UWORD *styles = line->line.Styles; UWORD *colors = line->line.Colors; struct marking block; BOOL cursor = FALSE; if(line->line.Color && x == 0 && line->line.Length == 1) line->line.Color = FALSE; if(doublebuffer == FALSE) { starty = data->ypos+(data->height * (line_nr-1)); xoffset = data->xpos; } flow = FlowSpace(line->line.Flow, text+x, data); Move(rp, xoffset+flow, starty+rp->TxBaseline); if(Enabled(data)) { struct line_node *blkline; NiceBlock(&data->blockinfo, &block); blkline = block.startline->next; if(block.startline == block.stopline) { if(block.startline == line) { startx = block.startx; stopx = block.stopx; } } else { if(block.startline == line) { startx = block.startx; stopx = line->line.Length; } else { if(block.stopline == line) { stopx = block.stopx; } else { while((blkline != block.stopline) && (!stopx)) { if(blkline == line) { stopx = line->line.Length; } blkline = blkline->next; } } } } } { UWORD blockstart = 0; UWORD blockwidth = 0; struct RastPort *old = muiRenderInfo(data->object)->mri_RastPort; if(startx < x+c_length && stopx > x) { if(startx > x) blockstart = TextLength(&data->tmprp, text+x, startx-x); else startx = x; blockwidth = ((stopx >= c_length+x) ? data->innerwidth-(blockstart+flow) : TextLength(&data->tmprp, text+startx, stopx-startx)); } else if(!(data->flags & (FLG_ReadOnly | FLG_Ghosted)) && line == data->actualline && data->CPos_X >= x && data->CPos_X < x+c_length && !Enabled(data) && (data->flags & FLG_Active || data->inactiveCursor == TRUE)) { cursor = TRUE; blockstart = TextLength(&data->tmprp, text+x, data->CPos_X-x); // calculate the cursor width // if it is set to 6 then we should find out how the width of the current char is if(data->CursorWidth == 6) blockwidth = TextLength(&data->tmprp, (*(text+data->CPos_X) < ' ') ? (char *)" " : (char *)(text+data->CPos_X), 1); else blockwidth = data->CursorWidth; } SetDrMd(rp, JAM1); muiRenderInfo(data->object)->mri_RastPort = rp; // clear the background first DoMethod(data->object, MUIM_DrawBackground, xoffset, starty, flow+blockstart, data->height, (data->flags & FLG_InVGrp) ? 0 : data->xpos, (data->flags & FLG_InVGrp) ? data->height*(data->visual_y+line_nr-2) : data->realypos+data->height * (data->visual_y+line_nr-2), 0); if(blockwidth) { ULONG color; // in case the gadget is in inactive state we use a different background // color for our selected area if((data->flags & FLG_Active) == 0 && (data->flags & FLG_Activated) == 0 && (data->flags & FLG_ActiveOnClick) != 0) { color = data->inactivecolor; } else color = data->markedcolor; // if selectmode == 2 then a whole line should be drawn as being marked, so // we have to start at xoffset instead of xoffset+flow+blockstart. // Please note that the second part of the following "empiric" evaluation should // prevent that centered or right aligned lines are not correctly marked right // from the beginning of the line. However, it seems to be not cover 100% of all different // cases so that the evaluation if a line should be completely marked should be probably // moved elsewhere in future. if(data->selectmode == 2 || (flow && data->selectmode != 1 && startx-x == 0 && cursor == FALSE && ((data->blockinfo.startline != data->blockinfo.stopline) || x > 0))) { SetAPen(rp, color); RectFill(rp, xoffset, starty, xoffset+flow+blockwidth-1, starty+data->height-1); } else { SetAPen(rp, cursor ? data->cursorcolor : color); RectFill(rp, xoffset+flow+blockstart, starty, xoffset+flow+blockstart+blockwidth-1, starty+data->height-1); // if the gadget is in inactive state we just draw a skeleton cursor instead if(cursor == TRUE && (data->flags & FLG_Active) == 0 && (data->flags & FLG_Activated) == 0) { DoMethod(data->object, MUIM_DrawBackground, xoffset+flow+blockstart+1, starty+1, blockwidth-2, data->height-2, (data->flags & FLG_InVGrp) ? 0 : data->xpos, (data->flags & FLG_InVGrp) ? data->height*(data->visual_y+line_nr-2) : data->realypos+data->height * (data->visual_y+line_nr-2), 0); } } } { LONG x_start = xoffset+blockstart+blockwidth, y_start = starty, x_width = data->innerwidth-(blockstart+blockwidth), y_width = data->height, x_ptrn = blockstart+blockwidth, y_ptrn = data->height*(data->visual_y+line_nr-2); if(blockwidth) { x_start += flow; x_width -= flow; x_ptrn += flow; } if(!(data->flags & FLG_InVGrp)) { x_ptrn += data->xpos; y_ptrn += data->realypos; } DoMethod(data->object, MUIM_DrawBackground, x_start, y_start, x_width, y_width, x_ptrn, y_ptrn); } muiRenderInfo(data->object)->mri_RastPort = old; } if(doublebuffer == FALSE) AddClipping(data); SetAPen(rp, (line->line.Color ? data->highlightcolor : data->textcolor)); while(c_length) { LONG p_length = c_length; SetSoftStyle(rp, convert(GetStyle(x, line)), AskSoftStyle(rp)); if(styles) { while(*styles-1 <= x) { styles += 2; } if(*styles-x-1 < p_length) { p_length = *styles-x-1; } } if(colors) { while(*colors-1 <= x) { SetAPen(rp, ConvertPen(*(colors+1), line->line.Color, data)); colors += 2; } if(*colors-x-1 < p_length) { p_length = *colors-x-1; } } /* if(stopx) { if((startx > x) && (startx-x < p_length)) { p_length = startx-x; SetAPen(rp, 3); } else { if((stopx > x) && (stopx-x < p_length)) { p_length = stopx-x; SetAPen(rp, 4); } else SetAPen(rp, (line->color ? data->highlightcolor : data->textcolor)); } } */ if(text[x+p_length-1] < ' ') Text(rp, text+x, p_length-1); else Text(rp, text+x, p_length); x += p_length; c_length -= p_length; } SetSoftStyle(rp, FS_NORMAL, AskSoftStyle(rp)); if(line->line.Separator) { WORD LeftX, LeftWidth, RightX, RightWidth, Y, Height; LeftX = xoffset; LeftWidth = flow-3; RightX = rp->cp_x+3; RightWidth = xoffset+data->innerwidth - RightX; Y = starty; Height = (line->line.Separator & LNSF_Thick) ? 2 : 1; if(line->line.Separator & LNSF_Middle) Y += (data->height/2)-Height; else { if(line->line.Separator & LNSF_Bottom) Y += data->height-(2*Height); } if(line->line.Separator & LNSF_StrikeThru || line->line.Length == 1) { LeftWidth = data->innerwidth; } else { DrawSeparator(rp, RightX, Y, RightWidth, Height, data); } DrawSeparator(rp, LeftX, Y, LeftWidth, Height, data); } if(data->flags & FLG_Ghosted) { UWORD *oldPattern = (UWORD *)rp->AreaPtrn; UBYTE oldSize = rp->AreaPtSz; UWORD newPattern[] = {0x1111, 0x4444}; if(doublebuffer == TRUE) { ULONG ptrn1 = 0x11111111; ULONG ptrn2 = 0x44444444; ptrn1 = ptrn1>>((data->xpos-xoffset)%16); ptrn2 = ptrn2>>((data->xpos-xoffset)%16); if((data->height*(data->visual_y+line_nr-2))%2 == 0) { newPattern[0] = ptrn2; newPattern[1] = ptrn1; } else { newPattern[0] = ptrn1; newPattern[1] = ptrn2; } }
/*--------------------------* * Merge two lines into one * *--------------------------*/ BOOL MergeLines(struct line_node *line, struct InstData *data) { struct line_node *next; char *newbuffer; LONG visual, oldvisual, line_nr; LONG emptyline = FALSE; LONG color = line->line.Color; UWORD flow = line->line.Flow; UWORD separator = line->line.Separator; ENTER(); data->HasChanged = TRUE; if(line->line.Length == 1) { emptyline = TRUE; color = line->next->line.Color; flow = line->next->line.Flow; separator = line->next->line.Separator; } visual = line->visual + line->next->visual; if((newbuffer = MyAllocPooled(data->mypool, line->line.Length+line->next->line.Length+1)) != NULL) { memcpy(newbuffer, line->line.Contents, line->line.Length-1); memcpy(newbuffer+line->line.Length-1, line->next->line.Contents, line->next->line.Length+1); MyFreePooled(data->mypool, line->line.Contents); MyFreePooled(data->mypool, line->next->line.Contents); if(emptyline == TRUE) { if(line->line.Styles != NULL) MyFreePooled(data->mypool, line->line.Styles); line->line.Styles = line->next->line.Styles; if(line->line.Colors != NULL) MyFreePooled(data->mypool, line->line.Colors); line->line.Colors = line->next->line.Colors; } else { UWORD *styles; UWORD *styles1 = line->line.Styles; UWORD *styles2 = line->next->line.Styles; UWORD *colors; UWORD *colors1 = line->line.Colors; UWORD *colors2 = line->next->line.Colors; UWORD length = 12; if(styles1 != NULL) length += *((long *)styles1-1) - 4; if(styles2 != NULL) length += *((long *)styles2-1) - 4; if((styles = MyAllocPooled(data->mypool, length)) != NULL) { unsigned short* t_styles = styles; unsigned short style = 0; SHOWVALUE(DBF_CLIPBOARD, length); SHOWVALUE(DBF_CLIPBOARD, styles); SHOWVALUE(DBF_CLIPBOARD, styles1); SHOWVALUE(DBF_CLIPBOARD, styles2); if(styles2 != NULL) { unsigned short* t_styles2 = styles2; while(*t_styles2++ == 1) { if(*t_styles2 > 0xff) style &= *t_styles2++; else style |= *t_styles2++; } } if(styles1 != NULL) { while(*styles1 != EOS) { if((*styles1 == line->line.Length) && ((~*(styles1+1) & style) == (*(styles1+1) ^ 0xffff))) { style &= *(styles1+1); styles1 += 2; } else { *styles++ = *styles1++; *styles++ = *styles1++; } } SHOWVALUE(DBF_CLIPBOARD, line->line.Styles); MyFreePooled(data->mypool, line->line.Styles); } if(styles2 != NULL) { while(*styles2 != EOS) { if((*styles2 == 1) && (!(*(styles2+1) & style))) { styles2 += 2; } else { *styles++ = *styles2++ + line->line.Length - 1; *styles++ = *styles2++; } } SHOWVALUE(DBF_CLIPBOARD, line->next->line.Styles); MyFreePooled(data->mypool, line->next->line.Styles); } *styles = EOS; line->line.Styles = t_styles; } length = 12; if(colors1 != NULL) length += *((long *)colors1-1) - 4; if(colors2 != NULL) length += *((long *)colors2-1) - 4; if((colors = MyAllocPooled(data->mypool, length)) != NULL) { UWORD *t_colors = colors; UWORD end_color = 0; SHOWVALUE(DBF_CLIPBOARD, length); SHOWVALUE(DBF_CLIPBOARD, colors); SHOWVALUE(DBF_CLIPBOARD, colors1); SHOWVALUE(DBF_CLIPBOARD, colors2); if(colors1 != NULL) { while(*colors1 < line->line.Length && *colors1 != 0xffff) { *colors++ = *colors1++; end_color = *colors1; *colors++ = *colors1++; } SHOWVALUE(DBF_CLIPBOARD, line->line.Colors); MyFreePooled(data->mypool, line->line.Colors); } if(end_color && (colors2 == NULL || *colors2 != 1)) { *colors++ = line->line.Length; *colors++ = 0; } if(colors2 != NULL) { if(*colors2 == 1 && *(colors2+1) == end_color) colors2 += 2; while(*colors2 != 0xffff) { *colors++ = *colors2++ + line->line.Length - 1; *colors++ = *colors2++; } SHOWVALUE(DBF_CLIPBOARD, line->next->line.Colors); MyFreePooled(data->mypool, line->next->line.Colors); } *colors = 0xffff; line->line.Colors = t_colors; } } line->line.Contents = newbuffer; line->line.Length = strlen(newbuffer); next = line->next; line->next = line->next->next; if(line->next != NULL) line->next->previous = line; oldvisual = line->visual; line->visual = VisualHeight(line, data); line->line.Color = color; line->line.Flow = flow; line->line.Separator = separator; FreeLine(next, data); line_nr = LineToVisual(line, data); // handle that we have to scroll up/down due to word wrapping // that occurrs when merging lines if(visual > line->visual) { data->totallines -= 1; if(line_nr+line->visual-1 < data->maxlines) { if(emptyline && line_nr > 0) { if(data->fastbackground) { ScrollUp(line_nr - 1, 1, data); SetCursor(data->CPos_X, data->actualline, TRUE, data); } else DumpText(data->visual_y+line_nr-1, line_nr-1, data->maxlines, TRUE, data); } else { if(data->fastbackground) ScrollUp(line_nr + line->visual - 1, 1, data); else DumpText(data->visual_y+line_nr+line->visual-1, line_nr+line->visual-1, data->maxlines, TRUE, data); } } } else if(visual < line->visual) { data->totallines += 1; if(line_nr+line->visual-1 < data->maxlines) ScrollDown(line_nr + line->visual - 2, 1, data); } if(!(emptyline && (line_nr + line->visual - 1 < data->maxlines))) { LONG t_oldvisual = oldvisual; LONG t_line_nr = line_nr; ULONG c = 0; while((--t_oldvisual) && (t_line_nr++ <= data->maxlines)) c = c + LineCharsWidth(line->line.Contents+c, data); while((c < line->line.Length) && (t_line_nr <= data->maxlines)) c = c + PrintLine(c, line, t_line_nr++, TRUE, data); } if(line_nr + oldvisual == 1 && line->visual == visual-1) { data->visual_y--; data->totallines -= 1; if(data->fastbackground) DumpText(data->visual_y, 0, visual-1, TRUE, data); else DumpText(data->visual_y, 0, data->maxlines, TRUE, data); } RETURN(TRUE); return(TRUE); } else { RETURN(FALSE); return(FALSE); } }
static void UpdateChange(LONG x, struct line_node *line, LONG length, const char *characters, struct UserAction *buffer, struct InstData *data) { LONG diff; LONG skip=0; LONG line_nr; LONG orgline_nr; LONG width=0; LONG lineabove_width=0; ENTER(); line_nr = LineToVisual(line, data); orgline_nr = line_nr; do { // don't exceed the line length! if(skip > (LONG)line->line.Length) break; width = LineCharsWidth(line->line.Contents + skip, data); if(width > 0 && skip + width < x) { lineabove_width = width; skip += width; line_nr++; } else break; } while(TRUE); if(characters != NULL) { strcpyback(line->line.Contents+x+length, line->line.Contents+x); memcpy(line->line.Contents+x, characters, length); width += length; line->line.Length += length; if(buffer != NULL) { UWORD style = buffer->del.style; AddStyleToLine(x, line, 1, (style & BOLD) ? BOLD : ~BOLD, data); AddStyleToLine(x, line, 1, (style & ITALIC) ? ITALIC : ~ITALIC, data); AddStyleToLine(x, line, 1, (style & UNDERLINE) ? UNDERLINE : ~UNDERLINE, data); line->line.Flow = buffer->del.flow; line->line.Separator = buffer->del.separator; } } else { strlcpy(line->line.Contents+x, line->line.Contents+x+length, line->line.Length); width -= length; line->line.Length -= length; } diff = VisualHeight(line, data) - line->visual; if(diff != 0) { LONG movement; movement = orgline_nr + line->visual - 1; line->visual += diff; data->totallines += diff; if(diff > 0) { if(movement < data->maxlines) ScrollDown(movement, diff, data); } else { movement = orgline_nr + line->visual - 1; if(movement <= data->maxlines) ScrollUp(movement, -diff, data); } } if(orgline_nr != line_nr) { if(lineabove_width != LineCharsWidth(line->line.Contents+skip-lineabove_width, data)) { LONG newwidth; newwidth = PrintLine(skip-lineabove_width, line, line_nr-1, TRUE, data) - lineabove_width; skip += newwidth; width -= newwidth; if(skip >= (LONG)line->line.Length) { LEAVE(); return; } } } OptimizedPrint(skip, line, line_nr, width, data); ScrollIntoDisplay(data); data->HasChanged = TRUE; LEAVE(); }