++ed by:

12 PAUSE users
12 non-PAUSE users.

Dmitry Karasik


Prima::Bidi - helper routines for bi-directional text input and output


   use Prima::Bidi qw(:enable is_bidi);
   $bidi_text = "'אפס123'";
   say Prima::Bidi::visual( $bidi_text ) if is_bidi($bidi_text);


or same, for classes

   use Prima::Bidi qw(:methods);
   say $self->bidi_visual( $bidi_text ) if $self-> is_bidi($bidi_text);


The API follows closely Text::Bidi api, with view to serve as a loose set of helper routines for input and output in Prima widgets. It also makes use of installations without Text::Bidi safe. Exports set of bidi_XXX names, available as method calls.

is_bidi $TEXT

Returns boolean flags whether the text contains any bidirectional characters.

bidi_map $TEXT, ...

Shortcut for Text::Bidi::Paragraph->new($TEXT, ...)->map.

Returns a set of integer indices, showing placement of where in original bidi text a corresponding character can be found, i.e. $map[0] contains the index of the character to be displayed leftmost, etc.

This function could be useful f.ex. for translating screen position to text position.

See "map" in Text::Bidi::Paragraph for more.

bidi_paragraph $TEXT, $RTL, $FLAGS

Returns a Text::Bidi::Paragraph(dir = $RTL)> object together with result of call to visual($FLAGS).

bidi_revmap $MAP

Returns an inverse array of result of map, i.e. showing where, if any, a bidi character is to be displayed in visual text, so that f.ex. $revmap[0] contains visual position of character #0, etc.


Handles bidirectional deletion, emulating user hitting a backspace ($DELETE = 0) or delete ($DELETE = 1) key at $VISUAL_POSITION in text represented by a Text::Bidi::Paragraph object.

Returns three integers, showing 1) how many characters are to be deleted, 2) at which text offset, and 3) how many characters to the right the cursor has to move.

$PARAGRAPH can be a non-object, in which case the text is considered to be non-bidi.


Handles typing of bidirectional text $NEW_STRING, inside an existing $PARAGRAPH represented by a Text::Bidi::Paragraph object, where cursor is a $VISUAL_POSITION.

$PARAGRAPH can be a non-object, in which case the text is considered to be non-bidi.

bidi_map_find $MAP, $INDEX

Searches thround $MAP (returned by bidi_map) for integer $INDEX, returns its position if found.

bidi_selection_chunks $MAP, $START, $END, $OFFSET = 0

Calculates a set of chunks of texts, that, given a text selection from positions $START to $END, represent each either a set of selected and non-selected visual characters. The text is represented by a result of bidi_map.

Returns array of integers, RLE-encoding the chunks, where the first integer signifies number of non-selected characters to display, the second - number of selected characters, the third the non-selected again, etc. If the first character belongs to the selected chunk, the first integer in the result is set to 0.

$MAP can be also an integer length of text (i.e. shortcut for an identity array (0,1,2,3...) in which case the text is considered to be non-bidi, and selection result will contain max 3 chunks).

$OFFSET may be greater that 0, but less than $START, if that information is not needed.

Example: consider embedded number in a bidi text. For the sake of clarity I'll use latin characters here. For example, we have a text scalar containing these characters:


where ABC is right-to-left text, and which, when rendered on screen, should be displayed as


(and $MAP will be (3,4,5,2,1,0) ).

Next, the user clicks the mouse between A and B (in text offset 1), drags the mouse then to the left, and finally stops between characters 2 and 3 (text offset 4). The resulting selection then should not be, as one might naively expect, this:


but this instead:


because the next character after C is 1, and the range of the selected sub-text is from characters 1 to 4.

In this case, the result of call to bidi_selection_chunks( $MAP, 1, 4 ) will be 0,2,1,2,1 .

bidi_selection_diff $OLD, $NEW

Given set of two chunk lists, in format as returned by bidi_selection_chunks, calculates the list of chunks affected by the selection change. Can be used for efficient repaints when the user interactively changes text selection, to redraw only the changed regions.

bidi_selection_map $TEXT

Same as bidi_map, except when $TEXT is not bidi, returns just the length of it. Such format can be used to pass the result further to bidi_selection_chunks efficiently where operations are performed on a non-bidi text.

bidi_selection_walk $CHUNKS, $FROM, $TO = length, $SUB

Walks the selection chunks array, returned by bidi_selection_chunks, between $FROM and $TO visual positions, and for each chunk calls the provided $SUB->($offset, $length, $selected), where each call contains 2 integers to chunk offset and length, and a boolean flag whether the chunk is selected or not.

Can be also used on a result of bidi_selection_walk, in which case $selected flag is irrelevant.

bidi_visual $TEXT, $RTL, $FLAGS

Same as bidi_paragraph but returns only the rendered text, omitting the paragraph object.


Dmitry Karasik, <dmitry@karasik.eu.org>.


examples/bidi.pl, Text::Bidi