(visually, cm, lineObj, lineNo, dir)
| 9335 | } |
| 9336 | |
| 9337 | function endOfLine(visually, cm, lineObj, lineNo, dir) { |
| 9338 | if (visually) { |
| 9339 | var order = getOrder(lineObj, cm.doc.direction) |
| 9340 | if (order) { |
| 9341 | var part = dir < 0 ? lst(order) : order[0] |
| 9342 | var moveInStorageOrder = dir < 0 == (part.level == 1) |
| 9343 | var sticky = moveInStorageOrder ? "after" : "before" |
| 9344 | var ch |
| 9345 | // With a wrapped rtl chunk (possibly spanning multiple bidi parts), |
| 9346 | // it could be that the last bidi part is not on the last visual line, |
| 9347 | // since visual lines contain content order-consecutive chunks. |
| 9348 | // Thus, in rtl, we are looking for the first (content-order) character |
| 9349 | // in the rtl chunk that is on the last line (that is, the same line |
| 9350 | // as the last (content-order) character). |
| 9351 | if (part.level > 0 || cm.doc.direction == "rtl") { |
| 9352 | var prep = prepareMeasureForLine(cm, lineObj) |
| 9353 | ch = dir < 0 ? lineObj.text.length - 1 : 0 |
| 9354 | var targetTop = measureCharPrepared(cm, prep, ch).top |
| 9355 | ch = findFirst( |
| 9356 | function (ch) { |
| 9357 | return measureCharPrepared(cm, prep, ch).top == targetTop |
| 9358 | }, |
| 9359 | dir < 0 == (part.level == 1) ? part.from : part.to - 1, |
| 9360 | ch |
| 9361 | ) |
| 9362 | if (sticky == "before") { |
| 9363 | ch = moveCharLogically(lineObj, ch, 1) |
| 9364 | } |
| 9365 | } else { |
| 9366 | ch = dir < 0 ? part.to : part.from |
| 9367 | } |
| 9368 | return new Pos(lineNo, ch, sticky) |
| 9369 | } |
| 9370 | } |
| 9371 | return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") |
| 9372 | } |
| 9373 | |
| 9374 | function moveVisually(cm, line, start, dir) { |
| 9375 | var bidi = getOrder(line, cm.doc.direction) |
no test coverage detected