@@ -2483,8 +2483,123 @@ int2 MCParagraph::fdelete(Field_translations type, MCParagraph *&undopgptr)
24832483 return 0 ;
24842484}
24852485
2486- uint1 MCParagraph::fmovefocus (Field_translations type)
2486+ uint1 MCParagraph::fmovefocus_visual (Field_translations type)
24872487{
2488+ // Get the current block and its text direction
2489+ MCBlock *sbptr = indextoblock (focusedindex, false );
2490+ bool t_is_rtl = sbptr->is_rtl ();
2491+
2492+ // Attempt to move non-visually and then back-out if we crossed a text
2493+ // direction boundary (as this is where visual order matters)
2494+ findex_t t_original_index = focusedindex;
2495+ Field_translations t_logical_type;
2496+ bool t_direction_matters = true ;
2497+ switch (type)
2498+ {
2499+ case FT_LEFTCHAR :
2500+ t_logical_type = t_is_rtl ? FT_FORWARDCHAR : FT_BACKCHAR ;
2501+ break ;
2502+
2503+ case FT_LEFTWORD :
2504+ t_logical_type = t_is_rtl ? FT_FORWARDWORD : FT_BACKWORD ;
2505+ break ;
2506+
2507+ case FT_RIGHTCHAR :
2508+ t_logical_type = t_is_rtl ? FT_BACKCHAR : FT_FORWARDCHAR ;
2509+ break ;
2510+
2511+ case FT_RIGHTWORD :
2512+ t_logical_type = t_is_rtl ? FT_BACKWORD : FT_FORWARDWORD ;
2513+ break ;
2514+
2515+ default :
2516+ t_logical_type = type;
2517+ t_direction_matters = false ;
2518+ break ;
2519+ }
2520+
2521+ uint1 t_result = fmovefocus (t_logical_type, true );
2522+ if (!t_direction_matters || t_result != FT_UNDEFINED )
2523+ return t_result;
2524+
2525+ // Blocks may have been crossed. Did we cross any directional boundaries?
2526+ bool t_direction_changed = false ;
2527+ MCBlock *bptr = sbptr;
2528+ MCBlock *ebptr = indextoblock (focusedindex, false );
2529+ while (bptr != ebptr)
2530+ {
2531+ if (bptr->is_rtl () != t_is_rtl)
2532+ {
2533+ t_direction_changed = true ;
2534+ break ;
2535+ }
2536+ bptr = bptr->next ();
2537+ }
2538+
2539+ // If no directional boundaries were crossed, nothing needs to be done
2540+ if (!t_direction_changed)
2541+ return t_result;
2542+
2543+ // Block boundary was crossed. We will decree that changing text direction
2544+ // always ends a word or character (not doing so would seem a bit odd).
2545+ MCBlock *tbptr;
2546+ if (type == FT_LEFTCHAR || type == FT_LEFTWORD )
2547+ {
2548+ tbptr = sbptr->GetPrevBlockVisualOrder ();
2549+
2550+ // Position cursor at the beginning/end of this block, as appropriate
2551+ if (tbptr == nil)
2552+ return FT_LEFTCHAR ;
2553+ else if (tbptr->is_rtl ())
2554+ focusedindex = tbptr->GetOffset () + tbptr->GetLength ();
2555+ else
2556+ focusedindex = tbptr->GetOffset ();
2557+ }
2558+ else // type == FT_RIGHTCHAR || type == FT_RIGHTWORD
2559+ {
2560+ tbptr = sbptr->GetNextBlockVisualOrder ();
2561+
2562+ // Position cursor at the beginning/end of this block, as appropriate
2563+ if (tbptr == nil)
2564+ return FT_RIGHTCHAR ;
2565+ if (tbptr->is_rtl ())
2566+ focusedindex = tbptr->GetOffset ();
2567+ else
2568+ focusedindex = tbptr->GetOffset () + tbptr->GetLength ();
2569+ }
2570+
2571+ // All done
2572+ return FT_UNDEFINED ;
2573+ }
2574+
2575+ uint1 MCParagraph::fmovefocus (Field_translations type, bool p_force_logical)
2576+ {
2577+ // Get the cursor movement style of the parent field
2578+ bool t_visual_movement;
2579+ t_visual_movement = parent->IsCursorMovementVisual ();
2580+ if (!p_force_logical && t_visual_movement)
2581+ return fmovefocus_visual (type);
2582+
2583+ // Using logical ordering so translate the type
2584+ switch (type)
2585+ {
2586+ case FT_LEFTCHAR :
2587+ type = FT_BACKCHAR ;
2588+ break ;
2589+
2590+ case FT_LEFTWORD :
2591+ type = FT_BACKWORD ;
2592+ break ;
2593+
2594+ case FT_RIGHTCHAR :
2595+ type = FT_FORWARDCHAR ;
2596+ break ;
2597+
2598+ case FT_RIGHTWORD :
2599+ type = FT_FORWARDWORD ;
2600+ break ;
2601+ }
2602+
24882603 findex_t oldfocused = focusedindex;
24892604 uindex_t t_length = gettextlength ();
24902605 switch (type)
0 commit comments