pub struct BuffRow<'a> {
pub length: usize,
pub char_size: usize,
/* private fields */
}
Expand description
Class to read characters from the terminal’s buffer rows. Includes indexing access and iterators This is a low-level “protected” class
Fields§
§length: usize
Number of characters in the row
char_size: usize
sizeof(Fl_Terminal::Utf8Char)
Implementations§
Source§impl<'a> BuffRow<'a>
impl<'a> BuffRow<'a>
Sourcepub fn new(ptr: *const Fl_Terminal_Utf8Char, parent: &'a Terminal) -> Self
pub fn new(ptr: *const Fl_Terminal_Utf8Char, parent: &'a Terminal) -> Self
Generate a new BuffRow
object based on a pointer from C++ Fl_Terminal
Sourcepub fn trim(self) -> Self
pub fn trim(self) -> Self
Trim trailing blanks off of BuffRow
object.
Does not affect the data in the RingBuff
, just this object’s access.
Examples found in repository?
examples/terminal.rs (line 619)
615 fn read_disp(term: &Terminal) -> String {
616 let rows = term.display_rows();
617 let mut text: Vec<u8> = Vec::with_capacity((rows * 64) as usize);
618 for row in 0..rows {
619 let r = term.u8c_disp_row(row).trim();
620 // Iterate through a row, accumulating [u8]
621 for c in r.iter() {
622 // Note: Sometimes utf-8 length is > 1
623 text.extend_from_slice(c.text_utf8());
624 }
625 text.extend_from_slice(b"\n");
626 }
627 // Return the result as a string
628 std::str::from_utf8(&text).unwrap().to_string()
629 }
Sourcepub fn col(&self, idx: usize) -> Utf8Char
pub fn col(&self, idx: usize) -> Utf8Char
Index into row array of Utf8Char
Examples found in repository?
examples/terminal.rs (line 644)
554fn mb_test4_cb(_choice: &mut fltk::menu::Choice, term: &mut Terminal) {
555 let sel_len = term.selection_text_len();
556 let sel = term.selection_text();
557
558 term.take_focus().unwrap();
559 term.reset_terminal();
560 // Test the Utf8Char primitive
561 let uc = Utf8Char::new(b'Q');
562 let uc1 = uc.text_utf8();
563 assert_eq!(&uc1, b"Q");
564 assert_eq!(&uc.attrib(), &Attrib::Normal);
565 assert_eq!(
566 &uc.charflags(),
567 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
568 );
569 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
570 assert_eq!(&uc.bgcolor(), &Color::TransparentBg);
571
572 let ring_rows = term.ring_rows();
573
574 term.take_focus().unwrap();
575 term.clear_history();
576 assert_eq!(term.history_use(), 0);
577
578 // Subtract row numbers, modulo `rows`
579 fn row_diff(rows: i32, a: i32, b: i32) -> i32 {
580 match a - b {
581 n if n < 0 => n + rows,
582 n => n,
583 }
584 }
585 // disp_srow is always 1 greater than hist_erow, modulo (ring_rows+1)
586 assert_eq!(row_diff(ring_rows, term.disp_srow(), term.hist_erow()), 1);
587 assert!(term.disp_srow() >= 0);
588 assert!(term.disp_erow() >= 0);
589 assert!(term.hist_srow() >= 0);
590 assert!(term.hist_erow() >= 0);
591 assert!(term.offset() >= 0);
592 assert!(term.disp_srow() <= ring_rows);
593 assert!(term.disp_erow() <= ring_rows);
594 assert!(term.hist_srow() <= ring_rows);
595 assert!(term.hist_erow() <= ring_rows);
596 assert!(term.offset() <= ring_rows);
597
598 assert_eq!(term.ring_srow(), 0);
599 assert_eq!(term.ring_erow(), ring_rows - 1);
600 assert_eq!(
601 row_diff(ring_rows, term.disp_erow(), term.disp_srow()) + 1,
602 term.display_rows()
603 );
604 assert_eq!(
605 row_diff(ring_rows, term.hist_erow(), term.hist_srow()) + 1,
606 term.history_rows()
607 );
608
609 assert_eq!(term.ring_erow(), term.ring_rows() - 1);
610 assert_eq!(term.ring_srow(), 0);
611
612 /// Local function to read back all rows from the display into a long string.
613 /// Does not include scrollback history.
614 /// Trims trailing blanks on each line
615 fn read_disp(term: &Terminal) -> String {
616 let rows = term.display_rows();
617 let mut text: Vec<u8> = Vec::with_capacity((rows * 64) as usize);
618 for row in 0..rows {
619 let r = term.u8c_disp_row(row).trim();
620 // Iterate through a row, accumulating [u8]
621 for c in r.iter() {
622 // Note: Sometimes utf-8 length is > 1
623 text.extend_from_slice(c.text_utf8());
624 }
625 text.extend_from_slice(b"\n");
626 }
627 // Return the result as a string
628 std::str::from_utf8(&text).unwrap().to_string()
629 }
630
631 term.clear();
632 term.append("Top line ↑ (up-arrow)");
633 term.set_text_attrib(Attrib::Underline);
634 term.append(" ");
635 term.set_text_attrib(Attrib::Normal);
636 term.append(" \n");
637 let mut text_out = read_disp(term);
638 // Trim trailing empty lines
639 text_out = text_out.trim_end_matches(&"\n").to_string();
640 // The two plain blanks at the end will be trimmed, the two underlined blanks will be retained.
641
642 assert_eq!(text_out, "Top line ↑ (up-arrow) ");
643 let r = term.u8c_disp_row(0);
644 assert_eq!(r.col(0).text_utf8(), b"T");
645 assert_eq!(r.col(10).text_utf8(), b"\xe2\x86\x91"); // UTF-8 up-arrow
646 assert_eq!(r.col(24).text_utf8(), b" "); // First blank after test text, NOT trimmed
647 let r = term.u8c_disp_row(1);
648 assert_eq!(r.col(0).text_utf8(), b" "); // Second row starts with blanks
649 assert_eq!(r.col(1).text_utf8(), b" "); // Second row is full of blanks
650
651 // Clear the screen again, then append test text, then read it back and compare
652 let test_text = "The wind was a torrent of darkness among the gusty trees.
653The moon was a ghostly galleon tossed upon cloudy seas.
654The road was a ribbon of moonlight over the purple moor,
655And the highwayman came riding—
656 Riding—riding—
657The highwayman came riding, up to the old inn-door.";
658
659 term.clear_history();
660 term.clear();
661 let bg_save = term.text_bg_color();
662 let fg_save = term.text_fg_color();
663 term.set_text_bg_color(Color::DarkBlue); // Set spooky colors
664 term.set_text_fg_color(Color::from_rgb(0x40, 0x40, 0xff));
665 term.append(test_text);
666 term.set_text_bg_color(bg_save);
667 term.set_text_fg_color(fg_save);
668
669 let mut text_out = read_disp(term);
670 // Trim trailing empty lines
671 text_out = text_out.trim_end_matches(&"\n").to_string();
672 assert_eq!(test_text, text_out);
673
674 assert_eq!(row_diff(ring_rows, term.disp_srow(), term.hist_erow()), 1);
675
676 assert_eq!(term.ring_srow(), 0);
677 assert_eq!(term.ring_erow(), ring_rows - 1);
678 assert_eq!(
679 row_diff(ring_rows, term.disp_erow(), term.disp_srow()) + 1,
680 term.display_rows()
681 );
682 assert_eq!(
683 row_diff(ring_rows, term.hist_erow(), term.hist_srow()) + 1,
684 term.history_rows()
685 );
686
687 term.append(&format!(
688 "\n\nScreen has {} rows of {} columns.\n",
689 term.display_rows(),
690 term.display_columns()
691 ));
692
693 term.append(&format!("Selection len: {sel_len}\nSelection: '{sel:?}'\n"));
694}
695
696//--------------------------------------------------------------------------------------
697/// Yet another set of tests for misc cursor functions and other stuff
698/// Note: these tests depend heavily on the low-level "protected" parts of the fltk library, which should be used with caution.
699fn mb_test5_cb(_choice: &mut fltk::menu::Choice, term: &mut Terminal) {
700 term.take_focus().unwrap();
701
702 // Test the attr_fg_color and attr_bg_color methods.
703 // Put a single character 'A' into the buffer and check it
704 term.clear(); // No reset_terminal(), just clear() to preserve the mouse selection for later
705 term.set_text_bg_color(Color::TransparentBg);
706 term.set_text_fg_color(Color::XtermWhite);
707 term.append("A");
708 let r = &term.u8c_disp_row(0);
709 let uc = r.col(0);
710 assert_eq!(uc.text_utf8(), b"A");
711 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermWhite);
712 assert_eq!(&uc.attr_bgcolor(None), &Color::TransparentBg);
713 assert_eq!(&uc.attr_bgcolor(Some(term)), &Color::Black);
714 assert_eq!(&uc.attr_fgcolor(Some(term)), &Color::XtermWhite);
715 assert_eq!(&uc.attrib(), &Attrib::Normal);
716
717 // Put a short string "BCD" into the first line of the buffer, with fg color change after the 'B' and bold after 'C'
718 term.clear();
719 term.set_text_fg_color_xterm(XtermColor::White);
720 term.set_text_bg_color_xterm(XtermColor::Black);
721 assert_eq!(term.text_attrib(), Attrib::Normal);
722
723 assert!(term.ansi());
724 term.append("B\x1b[32mC\x1b[1mD\n");
725
726 let r = &term.u8c_disp_row(0);
727 let uc = r.col(0);
728 assert_eq!(uc.text_utf8(), b"B");
729 assert!(uc.is_char(b'B'));
730 assert!(!uc.is_char(b'A'));
731 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
732 assert_eq!(&uc.bgcolor(), &Color::XtermBlack);
733 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermWhite);
734 assert_eq!(&uc.attr_bgcolor(None), &Color::XtermBlack);
735 assert_eq!(
736 &uc.charflags(),
737 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
738 );
739
740 let uc = r.col(1);
741 assert_eq!(uc.text_utf8(), b"C");
742 assert!(uc.is_char(b'C'));
743 assert_eq!(&uc.fgcolor(), &Color::XtermGreen);
744 assert_eq!(&uc.bgcolor(), &Color::XtermBlack);
745 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermGreen);
746 assert_eq!(&uc.attr_bgcolor(None), &Color::XtermBlack);
747 assert_eq!(
748 &uc.charflags(),
749 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
750 );
751
752 let uc = r.col(2);
753 assert_eq!(uc.text_utf8(), b"D");
754 assert!(uc.is_char(b'D'));
755 assert_eq!(&uc.fgcolor(), &Color::XtermGreen);
756 assert_eq!(&uc.bgcolor(), &Color::XtermBlack);
757 assert_eq!(&uc.attr_fgcolor(None), &Color::from_rgb(0x20, 0xf0, 0x20));
758 assert_eq!(&uc.attr_bgcolor(None), &Color::from_rgb(0x20, 0x20, 0x20));
759 assert_eq!(
760 &uc.attr_fgcolor(Some(term)),
761 &Color::from_rgb(0x20, 0xf0, 0x20)
762 );
763 assert_eq!(&uc.attr_bgcolor(None), &Color::from_rgb(0x20, 0x20, 0x20));
764 assert_eq!(
765 &uc.charflags(),
766 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
767 );
768
769 // Put a short string "BCDE" into the buffer, with fg color change after the 'B', bg change after 'C', and bold after 'D'
770 term.clear();
771 term.set_text_fg_color_xterm(XtermColor::White);
772 term.set_text_bg_color_xterm(XtermColor::Black);
773 term.set_text_attrib(Attrib::Normal);
774 assert_eq!(term.text_attrib(), Attrib::Normal);
775
776 assert!(term.ansi());
777 term.append("B\x1b[37mC\x1b[44mD\x1b[1mE\n");
778
779 let r = &term.u8c_disp_row(0);
780 let uc = r.col(0);
781 assert_eq!(uc.text_utf8(), b"B");
782 assert!(uc.is_char(b'B'));
783 assert!(!uc.is_char(b'A'));
784 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
785 assert_eq!(&uc.bgcolor(), &Color::XtermBlack);
786 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermWhite);
787 assert_eq!(&uc.attr_bgcolor(None), &Color::XtermBlack);
788 assert_eq!(
789 &uc.charflags(),
790 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
791 );
792
793 let uc = r.col(1);
794 assert_eq!(uc.text_utf8(), b"C");
795 assert!(uc.is_char(b'C'));
796 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
797 assert_eq!(&uc.bgcolor(), &Color::XtermBlack);
798 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermWhite);
799 assert_eq!(&uc.attr_bgcolor(None), &Color::XtermBlack);
800 assert_eq!(
801 &uc.charflags(),
802 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
803 );
804
805 let uc = r.col(2);
806 assert_eq!(uc.text_utf8(), b"D");
807 assert!(uc.is_char(b'D'));
808 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
809 assert_eq!(&uc.bgcolor(), &Color::XtermBgBlue);
810 assert_eq!(&uc.attr_fgcolor(None), &Color::XtermWhite);
811 assert_eq!(&uc.attr_bgcolor(None), &Color::XtermBgBlue);
812 assert_eq!(
813 &uc.charflags(),
814 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
815 );
816
817 let uc = r.col(3);
818 assert_eq!(uc.text_utf8(), b"E");
819 assert!(uc.is_char(b'E'));
820 assert_eq!(&uc.fgcolor(), &Color::XtermWhite);
821 assert_eq!(&uc.bgcolor(), &Color::XtermBgBlue);
822 assert_eq!(&uc.attr_fgcolor(None), &Color::from_hex(0xf0f0f0));
823 assert_eq!(&uc.attr_bgcolor(None), &Color::from_hex(0x2020e0));
824 assert_eq!(
825 &uc.charflags(),
826 &(CharFlags::FG_XTERM | CharFlags::BG_XTERM)
827 );
828
829 // Test some miscellaneous Utf8 constants
830 assert_eq!(uc.length(), 1);
831 assert_eq!(uc.max_utf8(), 4);
832 assert_eq!(uc.pwidth(), 9.0);
833 assert_eq!(uc.pwidth_int(), 9);
834
835 term.set_text_fg_color_xterm(XtermColor::White);
836 term.set_text_bg_color_xterm(XtermColor::Black);
837 term.clear();
838 term.set_text_attrib(Attrib::Normal);
839
840 // Mouse selection functions
841 term.append(&format!("Mouse selection: {:?}\n", &term.get_selection()));
842 term.clear_mouse_selection();
843 assert_eq!(term.get_selection(), None);
844
845 // Play with cursor position
846 term.append("0123456789\n"); // Set up test pattern
847 term.append("ABCDEFGHIJ\n");
848 term.append("abcdefghij\n");
849
850 term.set_cursor_row(1);
851 assert_eq!(term.cursor_row(), 1);
852 term.set_cursor_col(1);
853 assert_eq!(term.cursor_col(), 1);
854 assert_eq!(term.u8c_cursor().text_utf8(), b"1");
855
856 term.append("----"); // Overwrites text at cursor and moves cursor forward
857 assert_eq!(term.cursor_row(), 1);
858 assert_eq!(term.cursor_col(), 5);
859 assert_eq!(term.u8c_cursor().text_utf8(), b"5");
860 term.set_cursor_col(1);
861 assert_eq!(term.u8c_cursor().text_utf8(), b"-"); // Overwritten text
862
863 term.cursor_up(1, false);
864 assert_eq!(term.cursor_row(), 0);
865 assert_eq!(term.cursor_col(), 1);
866 assert_eq!(term.u8c_cursor().text_utf8(), b"o");
867
868 // Hit top of screen, so nothing happens
869 term.cursor_up(1, false);
870 assert_eq!(term.cursor_row(), 0);
871 assert_eq!(term.cursor_col(), 1);
872 assert_eq!(term.u8c_cursor().text_utf8(), b"o");
873
874 // Hit top of screen with scroll enabled. A blank line from history is scrolled in.
875 term.cursor_up(1, true);
876 assert_eq!(term.cursor_row(), 0);
877 assert_eq!(term.cursor_col(), 1);
878 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
879
880 // Go back down to the overwritten text
881 term.cursor_down(2, false);
882 assert_eq!(term.cursor_row(), 2);
883 assert_eq!(term.cursor_col(), 1);
884 assert_eq!(term.u8c_cursor().text_utf8(), b"-");
885
886 // Go right past the overwritten text
887 term.cursor_right(4, false);
888 assert_eq!(term.cursor_row(), 2);
889 assert_eq!(term.cursor_col(), 5);
890 assert_eq!(term.u8c_cursor().text_utf8(), b"5");
891
892 // Go left to the end of the overwritten text
893 term.cursor_left(1);
894 assert_eq!(term.cursor_row(), 2);
895 assert_eq!(term.cursor_col(), 4);
896 assert_eq!(term.u8c_cursor().text_utf8(), b"-");
897
898 // Scroll back down, removing the blank line at the top.
899 // Cursor stays in place, the text moves under it.
900 term.scroll(1);
901 assert_eq!(term.cursor_row(), 2);
902 assert_eq!(term.cursor_col(), 4);
903 assert_eq!(term.u8c_cursor().text_utf8(), b"E");
904
905 // Clear from here to end-of-line
906 term.clear_eol();
907 assert_eq!(term.cursor_row(), 2);
908 assert_eq!(term.cursor_col(), 4);
909 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
910
911 // Now clear from here to start-of-line. Cursor does not move.
912 term.clear_sol();
913 assert_eq!(term.cursor_row(), 2);
914 assert_eq!(term.cursor_col(), 4);
915 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
916 term.cursor_left(1);
917 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
918 term.set_cursor_col(0);
919 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
920
921 // Clear some lines
922 term.clear_line(1);
923 assert_eq!(term.cursor_row(), 2);
924 assert_eq!(term.cursor_col(), 0);
925 term.set_cursor_row(1);
926 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
927 term.set_cursor_row(3);
928 term.clear_cur_line();
929 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
930 assert_eq!(term.cursor_row(), 3);
931 assert_eq!(term.cursor_col(), 0);
932
933 term.append("Two lines above are intentionally left blank.\n");
934 assert_eq!(term.cursor_row(), 4);
935 assert_eq!(term.cursor_col(), 0);
936
937 // Set up the test pattern again, then play with insert/delete
938 term.append("0123456789\n");
939 term.append("ABCDEFGHIJ\n");
940 term.append("abcdefghij\n");
941 assert_eq!(term.cursor_row(), 7);
942
943 term.set_cursor_row(4);
944 term.set_cursor_col(4);
945 assert_eq!(term.u8c_cursor().text_utf8(), b"4");
946
947 term.insert_char('x', 5); // Push this row right 5 chars starting at col 4
948 assert_eq!(term.u8c_cursor().text_utf8(), b"x");
949 term.cursor_right(5, false);
950 assert_eq!(term.cursor_col(), 9);
951 assert_eq!(term.u8c_cursor().text_utf8(), b"4");
952
953 // Insert two blank rows above cursor. Cursor stays put.
954 term.insert_rows(2);
955 assert_eq!(term.cursor_row(), 4);
956 assert_eq!(term.cursor_col(), 9);
957 assert_eq!(term.u8c_cursor().text_utf8(), b" ");
958 term.cursor_down(2, false); // Go down to find our text again
959 assert_eq!(term.u8c_cursor().text_utf8(), b"4");
960
961 // Go back to the beginning of the inserted 'x' characters and delete them.
962 term.cursor_left(5);
963 assert_eq!(term.u8c_cursor().text_utf8(), b"x");
964 term.delete_cur_chars(5);
965 assert_eq!(term.cursor_row(), 6);
966 assert_eq!(term.cursor_col(), 4);
967 assert_eq!(term.u8c_cursor().text_utf8(), b"4");
968
969 term.delete_chars(7, 2, 2); // Delete "CD" from the next row
970 term.cursor_down(1, false);
971 term.cursor_left(2);
972 assert_eq!(term.u8c_cursor().text_utf8(), b"E");
973
974 term.delete_rows(1); // Middle row of pattern is gone, cursor stays put
975 assert_eq!(term.u8c_cursor().text_utf8(), b"c");
976 term.cursor_up(1, false);
977 term.delete_rows(2); // Delete remains of test pattern
978
979 term.set_text_attrib(Attrib::Bold);
980 term.insert_char_eol('-', 3, 15, 20);
981 term.set_cursor_row(3);
982 term.set_cursor_col(15);
983 assert_eq!(term.u8c_cursor().text_utf8(), b"-"); // Check the insertion
984 assert_eq!(term.u8c_cursor().attrib(), Attrib::Bold);
985
986 term.set_text_attrib(Attrib::Italic);
987 term.append(" and all lines below");
988 term.set_text_attrib(Attrib::Normal);
989 term.cursor_down(1, false);
990
991 let mut hsb = term.hscrollbar();
992 let mut sb = term.scrollbar();
993 hsb.set_value(100.0);
994 assert_eq!(hsb.value(), 100.0);
995 sb.set_value(50.0);
996 assert_eq!(sb.value(), 50.0);
997 hsb.set_value(0.0);
998 assert_eq!(hsb.value(), 0.0);
999 sb.set_value(0.0);
1000 assert_eq!(sb.value(), 0.0);
1001}
Sourcepub fn iter(&self) -> BuffRowIter<'_> ⓘ
pub fn iter(&self) -> BuffRowIter<'_> ⓘ
Iterator object to step through a sequence of Utf8Char
in a BuffRow
Examples found in repository?
examples/terminal.rs (line 621)
615 fn read_disp(term: &Terminal) -> String {
616 let rows = term.display_rows();
617 let mut text: Vec<u8> = Vec::with_capacity((rows * 64) as usize);
618 for row in 0..rows {
619 let r = term.u8c_disp_row(row).trim();
620 // Iterate through a row, accumulating [u8]
621 for c in r.iter() {
622 // Note: Sometimes utf-8 length is > 1
623 text.extend_from_slice(c.text_utf8());
624 }
625 text.extend_from_slice(b"\n");
626 }
627 // Return the result as a string
628 std::str::from_utf8(&text).unwrap().to_string()
629 }
Trait Implementations§
Auto Trait Implementations§
impl<'a> Freeze for BuffRow<'a>
impl<'a> RefUnwindSafe for BuffRow<'a>
impl<'a> !Send for BuffRow<'a>
impl<'a> !Sync for BuffRow<'a>
impl<'a> Unpin for BuffRow<'a>
impl<'a> UnwindSafe for BuffRow<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more