NetListItem::NetListItem(event_type type, const char* text, const BFont* font, uint32 level, bool expanded) : BListItem(level, expanded) { font_height height; font->GetHeight(&height); fFontAscent = height.ascent; fLineHeight = static_cast<int>(height.ascent + height.descent + height.leading); fText = static_cast<char*>(malloc(strlen(text) + 1)); strcpy(fText, text); fLineInfo.count = 1; fLineInfo.lines = (line_info*)malloc(sizeof(line_info)); fLineInfo.lines[0].numChars = 0; fLineInfo.lines[0].numWrapPoints = 0; fLineInfo.lines[0].byteNum = (int32*)malloc(sizeof(int32)); fLineInfo.lines[0].byteNum[0] = 0; for(int32 byteNum = 0; fText[byteNum] != 0; byteNum++) { if(BEGINS_CHAR(fText[byteNum])) { fLineInfo.lines[fLineInfo.count - 1].numChars++; if(WrapChar(fText[byteNum])) fLineInfo.lines[fLineInfo.count - 1].numWrapPoints++; if(fText[byteNum] == '\n') { // Don't count '\n' as a character fLineInfo.lines[fLineInfo.count - 1].numChars--; fLineInfo.count++; fLineInfo.lines = (line_info*)realloc(fLineInfo.lines, fLineInfo.count * sizeof(line_info)); fLineInfo.lines[fLineInfo.count - 1].numChars = 0; fLineInfo.lines[fLineInfo.count - 1].numWrapPoints = 0; fLineInfo.lines[fLineInfo.count - 1].byteNum = (int32*)malloc(sizeof(int32)); fLineInfo.lines[fLineInfo.count - 1].byteNum[0] = byteNum + 1; } } } // First pass finished, now know how many characters in each line for(int lineNum = 0; lineNum < fLineInfo.count; lineNum++) { fLineInfo.lines[lineNum].cumulativeWidth = (float*)malloc(fLineInfo.lines[lineNum].numChars * sizeof(float)); fLineInfo.lines[lineNum].byteNum = (int32*)realloc(fLineInfo.lines[lineNum].byteNum, fLineInfo.lines[lineNum].numChars * sizeof(int32)); fLineInfo.lines[lineNum].wrapPoints = (int32*)malloc(fLineInfo.lines[lineNum].numWrapPoints * sizeof(int32)); // Get escapements float* tmpEscapements = new float[fLineInfo.lines[lineNum].numChars]; font->GetEscapements(&fText[fLineInfo.lines[lineNum].byteNum[0]], fLineInfo.lines[lineNum].numChars, tmpEscapements); // Loop over that line to fill in details int charNum = -1; int wrapNum = -1; float cumulWidth = 0; for(int byteNum = fLineInfo.lines[lineNum].byteNum[0]; fText[byteNum] != '\n' && fText[byteNum] != 0; byteNum++) { if(BEGINS_CHAR(fText[byteNum])) { charNum++; fLineInfo.lines[lineNum].byteNum[charNum] = byteNum; cumulWidth += tmpEscapements[charNum]; fLineInfo.lines[lineNum].cumulativeWidth[charNum] = cumulWidth; if(WrapChar(fText[byteNum])) { wrapNum++; fLineInfo.lines[lineNum].wrapPoints[wrapNum] = charNum; } } } } fType = type; }
void LWrapChar(Layer *l, struct mchar *c, int y, int top, int bot, bool ins) { Canvas *cvlist, *cvlnext; Viewport *vp, *evp, **vpp; int yy, y2, yy2, top2, bot2; int bce; if (l->l_pause.d) /* XXX: 'y'? */ LayPauseUpdateRegion(l, 0, l->l_width - 1, top, bot); bce = c->colorbg; if (y != bot) { /* simple case: no scrolling */ /* cursor after wrapping */ yy = y == l->l_height - 1 ? y : y + 1; for (Canvas *cv = l->l_cvlist; cv; cv = cv->c_lnext) { if (l->l_pause.d && cv->c_slorient) continue; y2 = 0; /* gcc -Wall */ display = cv->c_display; if (D_blocked) continue; /* find the viewport of the wrapped character */ for (vp = cv->c_vplist; vp; vp = vp->v_next) { y2 = y + vp->v_yoff; yy2 = yy + vp->v_yoff; if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe) break; } if (vp == NULL) continue; /* nothing to do, character not visible */ /* find the viewport of the character at the end of the line */ for (evp = cv->c_vplist; evp; evp = evp->v_next) if (y2 >= evp->v_ys && y2 <= evp->v_ye && evp->v_xoff + l->l_width - 1 >= evp->v_xs && evp->v_xoff + l->l_width - 1 <= evp->v_xe) break; /* gotcha! */ if (evp == NULL || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye)) { /* no wrapping possible */ cvlist = l->l_cvlist; cvlnext = cv->c_lnext; l->l_cvlist = cv; cv->c_lnext = NULL; if (ins) LInsChar(l, c, 0, yy, NULL); else LPutChar(l, c, 0, yy); l->l_cvlist = cvlist; cv->c_lnext = cvlnext; } else { WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins); } } } else { /* hard case: scroll up */ for (Canvas *cv = l->l_cvlist; cv; cv = cv->c_lnext) { if (l->l_pause.d && cv->c_slorient) continue; display = cv->c_display; if (D_blocked) continue; /* search for wrap viewport */ for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next) { yy2 = bot + vp->v_yoff; if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff + l->l_width - 1 <= vp->v_xe) break; } if (vp) { /* great, can use Wrap on the vp */ /* temporarily remove vp from cvlist */ *vpp = vp->v_next; } if (cv->c_vplist) { /* scroll all viewports != vp */ cvlist = l->l_cvlist; cvlnext = cv->c_lnext; l->l_cvlist = cv; cv->c_lnext = NULL; LScrollV(l, 1, top, bot, bce); if (!vp) { if (ins) LInsChar(l, c, 0, bot, NULL); else LPutChar(l, c, 0, bot); } l->l_cvlist = cvlist; cv->c_lnext = cvlnext; } if (vp) { /* add vp back to cvlist */ *vpp = vp; top2 = top + vp->v_yoff; bot2 = bot + vp->v_yoff; if (top2 < vp->v_ys) top2 = vp->v_ys; WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins); } } } }